node_modules ignore

This commit is contained in:
2025-05-08 23:43:47 +02:00
parent e19d52f172
commit 4574544c9f
65041 changed files with 10593536 additions and 0 deletions

17
server/node_modules/player.style/README.md generated vendored Normal file
View File

@@ -0,0 +1,17 @@
# player.style
A fresh collection of media player themes for every use case!
# Local Development
This is a monorepo that uses NPM workspaces and Turbo. The root package is
also a published package which currently makes it impossible to have similar
named NPM scripts in the root package and the workspace packages.
For this reason we use the `turbo` CLI directly in the root directory.
1. Install Turbo globally: `npm install -g turbo`
1. Clone the repository
1. Run `npm install`
1. Run `turbo build`

70
server/node_modules/player.style/package.json generated vendored Normal file
View File

@@ -0,0 +1,70 @@
{
"name": "player.style",
"version": "0.0.8",
"description": "A fresh collection of media player themes for every use case!",
"author": "@muxinc",
"license": "MIT",
"homepage": "https://github.com/muxinc/player.style#readme",
"bugs": {
"url": "https://github.com/muxinc/player.style/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/muxinc/player.style.git"
},
"files": [
"themes/*",
"!.*"
],
"type": "module",
"exports": {
"./*/react": "./themes/*/dist/react.js",
"./*.js": "./themes/*/dist/media-theme.js",
"./*": "./themes/*/dist/media-theme.js"
},
"workspaces": [
".",
"site",
"examples/*",
"scripts/*",
"themes/*"
],
"scripts": {
"dev": "chokidar --debounce 50 './themes/*/!(dist|.turbo)' -c 'turbo build --force --filter=./$(dirname {path}) && touch ./site/$(dirname {path}).md'"
},
"dependencies": {
"media-chrome": "^4.1.0"
},
"devDependencies": {
"@player.style/demuxed-2022": "0.0.8",
"@player.style/instaplay": "0.0.3",
"@player.style/microvideo": "0.0.7",
"@player.style/minimal": "0.0.7",
"@player.style/sutro": "0.0.3",
"@player.style/sutro-audio": "0.0.2",
"@player.style/tailwind-audio": "0.0.7",
"@player.style/vimeonova": "0.0.7",
"@player.style/winamp": "0.0.7",
"@player.style/yt": "0.0.7",
"chokidar-cli": "^3.0.0",
"eslint": "^8.57.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.3.3",
"rimraf": "^6.0.1",
"turbo": "^2.1.1",
"typescript": "^5"
},
"prettier": {
"printWidth": 120,
"singleQuote": true,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"quoteProps": "as-needed",
"jsxSingleQuote": false,
"trailingComma": "es5",
"bracketSpacing": true,
"arrowParens": "always"
},
"packageManager": "npm@10.8.3"
}

View File

@@ -0,0 +1,34 @@
# Changelog
## [0.0.8](https://github.com/muxinc/player.style/compare/@player.style/demuxed-2022@0.0.7...@player.style/demuxed-2022@0.0.8) (2024-09-10)
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.3 to ^0.0.4
## [0.0.7](https://github.com/muxinc/player.style/compare/@player.style/demuxed-2022@0.0.6...@player.style/demuxed-2022@0.0.7) (2024-08-15)
### Bug Fixes
* improve color CSS vars & site color picker ([#49](https://github.com/muxinc/player.style/issues/49)) ([a8e8dc0](https://github.com/muxinc/player.style/commit/a8e8dc0898979e72d035af87233b2a0941fdcc7f))
* no render on preload none ([#38](https://github.com/muxinc/player.style/issues/38)) ([64dda58](https://github.com/muxinc/player.style/commit/64dda5825562da846edb33ddc7d4ba2548c08e00))
* remove unneeded package.json extra ([f869248](https://github.com/muxinc/player.style/commit/f86924841e9c04e68ac96c3c091eaf192f446772))
* upgrade to Media Chrome v4 ([#64](https://github.com/muxinc/player.style/issues/64)) ([be68af2](https://github.com/muxinc/player.style/commit/be68af2f9c3a6ff6674b9951f0b34f2bfdb042aa))
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.2 to ^0.0.3
## [0.0.6](https://github.com/muxinc/player.style/compare/@player.style/demuxed-2022-v0.0.5...@player.style/demuxed-2022@0.0.6) (2024-06-21)
### Features
* add Demuxed 2022 theme ([#20](https://github.com/muxinc/player.style/issues/20)) ([f61ba1c](https://github.com/muxinc/player.style/commit/f61ba1cb1dc39e1f2f3d503c1fb4b26aa25f0759))

View File

@@ -0,0 +1,13 @@
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
declare global {
interface HTMLElementTagNameMap {
'media-theme-demuxed-2022': MediaThemeDemuxed2022Element;
}
}
declare class MediaThemeDemuxed2022Element extends MediaThemeElement {
static template: HTMLTemplateElement;
}
export default MediaThemeDemuxed2022Element;

View File

@@ -0,0 +1,292 @@
<style>
:host {
--media-primary-color: black;
--media-tertiary-color: var(--media-accent-color, #7596CC);
--media-text-color: white;
--media-control-hover-background: transparent;
--media-range-track-height: 6px;
--media-range-bar-color: white;
--media-range-track-background: rgba(0,0,0,0.4);
--media-range-track-border-radius: 9999px;
--media-range-thumb-background: var(--media-tertiary-color);
--media-range-thumb-width: 14px;
--media-range-thumb-height: 14px;
--media-tooltip-display: none;
}
:host([mediastreamtype="live"]) media-time-range,
:host([mediastreamtype="live"]) media-time-display {
opacity: 0;
}
media-control-bar {
position: relative;
margin: 30px;
padding: 10px 14px;
border-radius: 9999px;
background: rgba(0,0,0,0.2);
align-items: center;
}
media-control-bar :first-child {
margin: 0 5px 0 0;
}
media-control-bar :last-child {
margin: 0 0 0 5px;
}
.small-button {
position: relative;
flex: none;
margin: 0 5px;
display: flex;
align-items: center;
justify-items: center;
height: 32px;
width: 32px;
background: var(--media-secondary-color, white);
border-radius: 9999px;
}
.small-button svg {
position: absolute;
overflow: hidden;
width: 100%;
height: 20px;
margin: 0 !important;
padding: 0 !important;
}
.small-button:hover {
box-shadow: 0 0 0 calc(2px) var(--media-tertiary-color);
}
div[slot="centered-chrome"] media-play-button {
position: relative;
flex: none;
display: flex;
margin-bottom: 10px;
align-items: center;
justify-items: center;
height: 96px;
width: 96px;
background: rgb(0 0 0 / 0.8);
border-radius: 9999px;
}
div[slot="centered-chrome"] media-play-button:hover {
box-shadow: 0 0 0 calc(2px) var(--media-tertiary-color);
}
div[slot="centered-chrome"] media-play-button svg {
fill: #fff;
height: 64px;
}
media-time-range {
--media-secondary-color: transparent;
height: 32px;
margin: 0 8px 0 0;
}
media-volume-range {
height: 100%;
}
media-time-display {
--media-secondary-color: transparent;
min-width: 92px;
padding: 0 6px 3px 8px;
}
media-time-display, media-preview-time-display {
font-size: 14px;
font-family: sofia-pro, sans-serif;
}
.demuxed-gradient-bottom {
padding-top: 37px;
position: absolute;
width: 100%;
height: 200px;
bottom: 0;
pointer-events: none;
background-position: bottom;
background-repeat: repeat-x;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAACqCAYAAABsziWkAAAAAXNSR0IArs4c6QAAAQVJREFUOE9lyNdHBQAAhfHb3nvvuu2997jNe29TJJEkkkgSSSSJJJJEEkkiifRH5jsP56Xz8PM5gcC/xfDEmjhKxEOCSaREEiSbFEqkQppJpzJMJiWyINvkUCIX8kw+JQqg0BRRxaaEEqVQZsopUQGVpooS1VBjglStqaNEPTSYRko0QbNpoUQrtJl2qsN0UqILuk0PJXqhz/RTYgAGzRA1bEYoMQpjZpwSExAyk5SYgmkzQ82aOUqEIWKilJiHBbNIiSVYhhVYhTVYhw3YhC3Yhh3YhT3YhwM4hCM4hhM4hTM4hwu4hCu4hhu4hTu4hwd4hCd4hhd4hTd4hw/4hC/4hh/4/QM2/id28uIEJAAAAABJRU5ErkJggg==");
}
div[slot="top-chrome"] {
width: calc(100% - 36px);
display: flex;
flex-direction: row-reverse;
padding-right: 36px;
}
div[slot="top-chrome"] .small-button {
margin: 32px 8px;
}
media-controller[breakpointsm] .media-volume-wrapper {
position: relative;
padding-left: 6px;
}
.media-volume-range-wrapper {
width: 122px;
height: 34px;
overflow: hidden;
opacity: 0;
transform: rotate(-90deg);
position: absolute;
top: -75px;
left: -52px;
border-left: 16px solid transparent;
}
media-volume-range {
border-radius: 0 9999px 9999px 0;
background: rgba(0,0,0,0.2);
--media-range-track-width: 80px;
}
media-mute-button:hover + .media-volume-range-wrapper,
media-mute-button:focus + .media-volume-range-wrapper,
media-mute-button:focus-within + .media-volume-range-wrapper,
.media-volume-range-wrapper:hover,
.media-volume-range-wrapper:focus,
.media-volume-range-wrapper:focus-within {
opacity: 1;
}
media-controller:not([breakpointsm]) media-control-bar {
position: static;
background: transparent;
margin: 0;
padding: 22px 15px;
}
media-controller:not([breakpointsm]) media-time-display,
media-controller:not([breakpointsm]) .media-volume-range-wrapper {
display: none;
}
media-controller:not([breakpointsm]) .small-button {
display: none;
width: 48px;
height: 48px;
}
media-controller:not([breakpointsm]) .small-button svg {
transform: scale(1.4);
}
media-controller:not([breakpointsm]) div[slot="top-chrome"] {
width: calc(100% - 13px);
padding-right: 13px;
}
media-controller:not([breakpointsm]) div[slot="top-chrome"] .small-button {
display: flex;
margin: 22px 7px;
}
media-controller:not([breakpointsm]) media-fullscreen-button.small-button {
display: flex;
}
media-controller:not([breakpointsm]) media-airplay-button[mediaairplayunavailable].small-button {
display: none;
}
media-controller:not([breakpointsm]) media-cast-button[mediacastunavailable].small-button {
display: none;
}
media-controller:not([breakpointsm]) media-mute-button.small-button {
display: flex;
}
media-controller:not([breakpointsm]) media-captions-button.small-button {
position: absolute;
top: 22px;
left: 16px;
}
media-controller:not([breakpointsm]) div[slot="centered-chrome"] media-play-button {
z-index: 1;
height: 72px;
width: 72px;
}
media-controller:not([breakpointsm]) div[slot="centered-chrome"] media-play-button svg {
margin-left: -2px;
height: 48px;
}
</style>
<media-controller
breakpoints="xs:360 sm:600 md:760 lg:960 xl:1100"
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<div class="demuxed-gradient-bottom"></div>
<div slot="top-chrome">
<media-cast-button class="small-button">
<svg slot="enter" viewBox="0 0 26 26"><path d="M2.5 18.5v3h3c0-1.7-1.34-3-3-3ZM2.5 14.5v2c2.76 0 5 2.2 5 5h2c0-3.87-3.13-7-7-7Z"/><path d="M2.5 10.5v2c4.97 0 9 4 9 9h2c0-6.08-4.93-11-11-11Z"/><path d="M22.5 3.5h-18c-1.1 0-2 .9-2 2v3h2v-3h18v14h-7v2h7c1.1 0 2-.9 2-2v-14c0-1.1-.9-2-2-2Z"/></svg>
<svg slot="exit" viewBox="0 0 26 26"><path d="M2.5 18.5v3h3c0-1.7-1.34-3-3-3ZM2.5 14.5v2c2.76 0 5 2.2 5 5h2c0-3.87-3.13-7-7-7Z"/><path d="M2.5 10.5v2c4.97 0 9 4 9 9h2c0-6.08-4.93-11-11-11Z"/><path d="M22.5 3.5h-18c-1.1 0-2 .9-2 2v3h2v-3h18v14h-7v2h7c1.1 0 2-.9 2-2v-14c0-1.1-.9-2-2-2Z"/></svg>
</media-cast-button>
<media-airplay-button class="small-button">
<svg slot="icon" viewBox="0 0 23 23"><path d="M20.88 3.5H2.62a.87.87 0 0 0-.87.87v13.26a.87.87 0 0 0 .87.87h3.4l1.73-2h-4v-11h16v11h-4l1.72 2h3.4a.87.87 0 0 0 .87-.87V4.37a.87.87 0 0 0-.86-.87Zm-8.75 11.44a.5.5 0 0 0-.76 0l-4.91 5.73a.5.5 0 0 0 .38.83h9.82a.501.501 0 0 0 .38-.83l-4.91-5.73Z"/></svg>
</media-airplay-button>
</div>
<div slot="centered-chrome">
<media-play-button>
<svg slot="play" viewBox="0 0 16 16"><path d="M13.6 7.2 5.1 3c-.6-.3-1.2.1-1.2.7v8.5c0 .6.7 1 1.2.7l8.5-4.2c.6-.3.6-1.1 0-1.5z"/></svg>
<svg slot="pause" viewBox="0 0 16 16"><path d="M11.8 14c-.5 0-.9-.4-.9-.9V2.9c0-.5.4-.9.9-.9s.9.4.9.9v10.2c0 .5-.4.9-.9.9zM4.1 14c-.5 0-.9-.4-.9-.9V2.9c0-.5.4-.9.9-.9s.9.4.9.9v10.2c-.1.5-.5.9-.9.9z"/></svg>
</media-play-button>
</div>
<media-control-bar>
<media-play-button class="small-button">
<svg slot="play" viewBox="0 0 16 16"><path d="M13.6 7.2 5.1 3c-.6-.3-1.2.1-1.2.7v8.5c0 .6.7 1 1.2.7l8.5-4.2c.6-.3.6-1.1 0-1.5z"/></svg>
<svg slot="pause" viewBox="0 0 16 16"><path d="M11.8 14c-.5 0-.9-.4-.9-.9V2.9c0-.5.4-.9.9-.9s.9.4.9.9v10.2c0 .5-.4.9-.9.9zM4.1 14c-.5 0-.9-.4-.9-.9V2.9c0-.5.4-.9.9-.9s.9.4.9.9v10.2c-.1.5-.5.9-.9.9z"/></svg>
</media-play-button>
<div class="media-volume-wrapper">
<media-mute-button class="small-button">
<svg slot="off" viewBox="0 0 16 16"><path d="M7 2.2 4.2 5.1v.1H1.4c-.5 0-.9.4-.9.9V10c0 .5.4.9.9.9h2.8L7 13.8c.3.3.8.1.8-.3v-11c0-.4-.5-.6-.8-.3ZM13.4 8l2-2" fill-rule="nonzero"/><path d="M15.622 5.479a.606.606 0 0 1 0 .857l-4.286 4.286a.606.606 0 1 1-.857-.857l4.286-4.286a.606.606 0 0 1 .857 0Z"/><path d="M10.479 5.479a.606.606 0 0 0 0 .857l4.286 4.286a.606.606 0 1 0 .857-.857l-4.286-4.286a.606.606 0 0 0-.857 0Z"/></svg>
<svg slot="low" viewBox="0 0 16 16"><path d="m7.1 2.2-2.8 3H1.5c-.5 0-.9.4-.9.9V10c0 .5.4.9.9.9h2.8l2.8 2.9c.3.3.8.1.8-.3v-11c0-.4-.5-.6-.8-.3zM10.3 11.4c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9.6-.6 1-1.4 1-2.3s-.4-1.6-1-2.3c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 .9.8 1.4 2 1.4 3.2s-.5 2.3-1.4 3.2c-.2.2-.4.2-.5.2z"/></svg>
<svg slot="medium" viewBox="0 0 16 16"><path d="m7.1 2.2-2.8 3H1.5c-.5 0-.9.4-.9.9V10c0 .5.4.9.9.9h2.8l2.8 2.9c.3.3.8.1.8-.3v-11c0-.4-.5-.6-.8-.3zM12.6 13.8c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9 1.3-1.2 2-2.8 2-4.5s-.7-3.3-2-4.5c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 1.5 1.5 2.3 3.4 2.3 5.4 0 2.1-.8 4-2.3 5.4-.2.1-.4.2-.5.2z"/><path d="M10.3 11.4c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9.6-.6 1-1.4 1-2.3s-.4-1.6-1-2.3c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 .9.8 1.4 2 1.4 3.2s-.5 2.3-1.4 3.2c-.2.2-.4.2-.5.2z"/></svg>
<svg slot="high" viewBox="0 0 16 16"><path d="m7.1 2.2-2.8 3H1.5c-.5 0-.9.4-.9.9V10c0 .5.4.9.9.9h2.8l2.8 2.9c.3.3.8.1.8-.3v-11c0-.4-.5-.6-.8-.3zM12.6 13.8c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9 1.3-1.2 2-2.8 2-4.5s-.7-3.3-2-4.5c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 1.5 1.5 2.3 3.4 2.3 5.4 0 2.1-.8 4-2.3 5.4-.2.1-.4.2-.5.2z"/><path d="M10.3 11.4c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9.6-.6 1-1.4 1-2.3s-.4-1.6-1-2.3c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 .9.8 1.4 2 1.4 3.2s-.5 2.3-1.4 3.2c-.2.2-.4.2-.5.2z"/></svg>
</media-mute-button>
<div class="media-volume-range-wrapper">
<media-volume-range></media-volume-range>
</div>
</div>
<media-time-display showduration></media-time-display>
<media-time-range>
<media-preview-thumbnail slot="preview"></media-preview-thumbnail>
<media-preview-time-display slot="preview"></media-preview-time-display>
</media-time-range>
<media-captions-button class="small-button">
<svg slot="off" viewBox="0 0 16 16"><path d="M12.6 13.7H3.4C2 13.7.8 12.6.8 11.1V4.9c0-1.4 1.1-2.6 2.6-2.6h9.3c1.4 0 2.6 1.1 2.6 2.6v6.2c-.1 1.5-1.3 2.6-2.7 2.6z"/><path fill="#fff" d="M4.7 8H3.2c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h1.5c.2 0 .4.2.4.4s-.2.4-.4.4zM12.5 8H6.7c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h5.7c.2 0 .4.2.4.4s-.1.4-.3.4zM7.7 10.2H3.2c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h4.6c.2 0 .4.2.4.4-.1.2-.3.4-.5.4zM12.5 10.2H9.8c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h2.7c.2 0 .4.2.4.4s-.2.4-.4.4z"/></svg>
<svg slot="on" viewBox="0 0 16 16"><path d="M4.7 8H3.2c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h1.5c.2 0 .4.2.4.4s-.2.4-.4.4zM12.5 8H6.7c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h5.7c.2 0 .4.2.4.4s-.1.4-.3.4zM7.7 10.2H3.2c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h4.6c.2 0 .4.2.4.4-.1.2-.3.4-.5.4zM12.5 10.2H9.8c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h2.7c.2 0 .4.2.4.4s-.2.4-.4.4z"/></svg>
</media-captions-button>
<media-pip-button class="small-button">
<svg slot="enter" viewBox="0 0 16 16"><path d="M14.2 13.1H1.8c-.4 0-.7-.3-.7-.7V3.5c0-.4.3-.7.7-.7h12.3c.4 0 .7.3.7.7v8.9c.1.5-.2.7-.6.7zM2.5 11.8h11V4.3h-11v7.5z"/><path d="M7.2 7.3h5.1v3.1H7.2z"/></svg>
<svg slot="exit" viewBox="0 0 16 16"><path d="M14.2 13.1H1.8c-.4 0-.7-.3-.7-.7V3.5c0-.4.3-.7.7-.7h12.3c.4 0 .7.3.7.7v8.9c.1.5-.2.7-.6.7zM2.5 11.8h11V4.3h-11v7.5z"/><path d="M7.2 7.3h5.1v3.1H7.2z"/></svg>
</media-pip-button>
<media-fullscreen-button class="small-button">
<svg slot="enter" viewBox="0 0 16 16"><path d="M2.9 6.6c-.4 0-.7-.3-.7-.7v-3c0-.4.3-.7.7-.7h3c.4 0 .7.3.7.7s-.2.7-.6.7H3.6V6c0 .3-.3.6-.7.6zM13.1 6.6c-.4 0-.7-.3-.7-.7V3.6H10c-.4 0-.7-.3-.7-.7s.3-.7.7-.7h3c.4 0 .7.3.7.7v3c.1.4-.2.7-.6.7zM6 13.8H3c-.4 0-.7-.3-.7-.7v-3c0-.4.3-.7.7-.7.4 0 .7.3.7.7v2.4H6c.4 0 .7.3.7.7-.1.3-.4.6-.7.6zM13.1 13.8h-3c-.4 0-.7-.3-.7-.7 0-.4.3-.7.7-.7h2.4V10c0-.4.3-.7.7-.7.4 0 .7.3.7.7v3c-.1.5-.4.8-.8.8z"/></svg>
<svg slot="exit" viewBox="0 0 16 16"><path d="M2.9 6.6c-.4 0-.7-.3-.7-.7v-3c0-.4.3-.7.7-.7h3c.4 0 .7.3.7.7s-.2.7-.6.7H3.6V6c0 .3-.3.6-.7.6zM13.1 6.6c-.4 0-.7-.3-.7-.7V3.6H10c-.4 0-.7-.3-.7-.7s.3-.7.7-.7h3c.4 0 .7.3.7.7v3c.1.4-.2.7-.6.7zM6 13.8H3c-.4 0-.7-.3-.7-.7v-3c0-.4.3-.7.7-.7.4 0 .7.3.7.7v2.4H6c.4 0 .7.3.7.7-.1.3-.4.6-.7.6zM13.1 13.8h-3c-.4 0-.7-.3-.7-.7 0-.4.3-.7.7-.7h2.4V10c0-.4.3-.7.7-.7.4 0 .7.3.7.7v3c-.1.5-.4.8-.8.8z"/></svg>
</media-fullscreen-button>
</media-control-bar>
</media-controller>

View File

@@ -0,0 +1,322 @@
/*
<media-theme-demuxed-2022>
<video
slot="media"
src="https://stream.mux.com/fXNzVtmtWuyz00xnSrJg4OJH6PyNo6D02UzmgeKGkP5YQ/high.mp4"
></video>
</media-theme-demuxed-2022>
*/
import 'media-chrome';
import { globalThis } from 'media-chrome/dist/utils/server-safe-globals.js';
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
import 'media-chrome/dist/menu/index.js';
const template = globalThis.document?.createElement?.('template');
if (template) {
template.innerHTML = /*html*/`
<style>
:host {
--media-primary-color: black;
--media-tertiary-color: var(--media-accent-color, #7596CC);
--media-text-color: white;
--media-control-hover-background: transparent;
--media-range-track-height: 6px;
--media-range-bar-color: white;
--media-range-track-background: rgba(0,0,0,0.4);
--media-range-track-border-radius: 9999px;
--media-range-thumb-background: var(--media-tertiary-color);
--media-range-thumb-width: 14px;
--media-range-thumb-height: 14px;
--media-tooltip-display: none;
}
:host([mediastreamtype="live"]) media-time-range,
:host([mediastreamtype="live"]) media-time-display {
opacity: 0;
}
media-control-bar {
position: relative;
margin: 30px;
padding: 10px 14px;
border-radius: 9999px;
background: rgba(0,0,0,0.2);
align-items: center;
}
media-control-bar :first-child {
margin: 0 5px 0 0;
}
media-control-bar :last-child {
margin: 0 0 0 5px;
}
.small-button {
position: relative;
flex: none;
margin: 0 5px;
display: flex;
align-items: center;
justify-items: center;
height: 32px;
width: 32px;
background: var(--media-secondary-color, white);
border-radius: 9999px;
}
.small-button svg {
position: absolute;
overflow: hidden;
width: 100%;
height: 20px;
margin: 0 !important;
padding: 0 !important;
}
.small-button:hover {
box-shadow: 0 0 0 calc(2px) var(--media-tertiary-color);
}
div[slot="centered-chrome"] media-play-button {
position: relative;
flex: none;
display: flex;
margin-bottom: 10px;
align-items: center;
justify-items: center;
height: 96px;
width: 96px;
background: rgb(0 0 0 / 0.8);
border-radius: 9999px;
}
div[slot="centered-chrome"] media-play-button:hover {
box-shadow: 0 0 0 calc(2px) var(--media-tertiary-color);
}
div[slot="centered-chrome"] media-play-button svg {
fill: #fff;
height: 64px;
}
media-time-range {
--media-secondary-color: transparent;
height: 32px;
margin: 0 8px 0 0;
}
media-volume-range {
height: 100%;
}
media-time-display {
--media-secondary-color: transparent;
min-width: 92px;
padding: 0 6px 3px 8px;
}
media-time-display, media-preview-time-display {
font-size: 14px;
font-family: sofia-pro, sans-serif;
}
.demuxed-gradient-bottom {
padding-top: 37px;
position: absolute;
width: 100%;
height: 200px;
bottom: 0;
pointer-events: none;
background-position: bottom;
background-repeat: repeat-x;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAACqCAYAAABsziWkAAAAAXNSR0IArs4c6QAAAQVJREFUOE9lyNdHBQAAhfHb3nvvuu2997jNe29TJJEkkkgSSSSJJJJEEkkiifRH5jsP56Xz8PM5gcC/xfDEmjhKxEOCSaREEiSbFEqkQppJpzJMJiWyINvkUCIX8kw+JQqg0BRRxaaEEqVQZsopUQGVpooS1VBjglStqaNEPTSYRko0QbNpoUQrtJl2qsN0UqILuk0PJXqhz/RTYgAGzRA1bEYoMQpjZpwSExAyk5SYgmkzQ82aOUqEIWKilJiHBbNIiSVYhhVYhTVYhw3YhC3Yhh3YhT3YhwM4hCM4hhM4hTM4hwu4hCu4hhu4hTu4hwd4hCd4hhd4hTd4hw/4hC/4hh/4/QM2/id28uIEJAAAAABJRU5ErkJggg==");
}
div[slot="top-chrome"] {
width: calc(100% - 36px);
display: flex;
flex-direction: row-reverse;
padding-right: 36px;
}
div[slot="top-chrome"] .small-button {
margin: 32px 8px;
}
media-controller[breakpointsm] .media-volume-wrapper {
position: relative;
padding-left: 6px;
}
.media-volume-range-wrapper {
width: 122px;
height: 34px;
overflow: hidden;
opacity: 0;
transform: rotate(-90deg);
position: absolute;
top: -75px;
left: -52px;
border-left: 16px solid transparent;
}
media-volume-range {
border-radius: 0 9999px 9999px 0;
background: rgba(0,0,0,0.2);
--media-range-track-width: 80px;
}
media-mute-button:hover + .media-volume-range-wrapper,
media-mute-button:focus + .media-volume-range-wrapper,
media-mute-button:focus-within + .media-volume-range-wrapper,
.media-volume-range-wrapper:hover,
.media-volume-range-wrapper:focus,
.media-volume-range-wrapper:focus-within {
opacity: 1;
}
media-controller:not([breakpointsm]) media-control-bar {
position: static;
background: transparent;
margin: 0;
padding: 22px 15px;
}
media-controller:not([breakpointsm]) media-time-display,
media-controller:not([breakpointsm]) .media-volume-range-wrapper {
display: none;
}
media-controller:not([breakpointsm]) .small-button {
display: none;
width: 48px;
height: 48px;
}
media-controller:not([breakpointsm]) .small-button svg {
transform: scale(1.4);
}
media-controller:not([breakpointsm]) div[slot="top-chrome"] {
width: calc(100% - 13px);
padding-right: 13px;
}
media-controller:not([breakpointsm]) div[slot="top-chrome"] .small-button {
display: flex;
margin: 22px 7px;
}
media-controller:not([breakpointsm]) media-fullscreen-button.small-button {
display: flex;
}
media-controller:not([breakpointsm]) media-airplay-button[mediaairplayunavailable].small-button {
display: none;
}
media-controller:not([breakpointsm]) media-cast-button[mediacastunavailable].small-button {
display: none;
}
media-controller:not([breakpointsm]) media-mute-button.small-button {
display: flex;
}
media-controller:not([breakpointsm]) media-captions-button.small-button {
position: absolute;
top: 22px;
left: 16px;
}
media-controller:not([breakpointsm]) div[slot="centered-chrome"] media-play-button {
z-index: 1;
height: 72px;
width: 72px;
}
media-controller:not([breakpointsm]) div[slot="centered-chrome"] media-play-button svg {
margin-left: -2px;
height: 48px;
}
</style>
<media-controller
breakpoints="xs:360 sm:600 md:760 lg:960 xl:1100"
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<div class="demuxed-gradient-bottom"></div>
<div slot="top-chrome">
<media-cast-button class="small-button">
<svg slot="enter" viewBox="0 0 26 26"><path d="M2.5 18.5v3h3c0-1.7-1.34-3-3-3ZM2.5 14.5v2c2.76 0 5 2.2 5 5h2c0-3.87-3.13-7-7-7Z"/><path d="M2.5 10.5v2c4.97 0 9 4 9 9h2c0-6.08-4.93-11-11-11Z"/><path d="M22.5 3.5h-18c-1.1 0-2 .9-2 2v3h2v-3h18v14h-7v2h7c1.1 0 2-.9 2-2v-14c0-1.1-.9-2-2-2Z"/></svg>
<svg slot="exit" viewBox="0 0 26 26"><path d="M2.5 18.5v3h3c0-1.7-1.34-3-3-3ZM2.5 14.5v2c2.76 0 5 2.2 5 5h2c0-3.87-3.13-7-7-7Z"/><path d="M2.5 10.5v2c4.97 0 9 4 9 9h2c0-6.08-4.93-11-11-11Z"/><path d="M22.5 3.5h-18c-1.1 0-2 .9-2 2v3h2v-3h18v14h-7v2h7c1.1 0 2-.9 2-2v-14c0-1.1-.9-2-2-2Z"/></svg>
</media-cast-button>
<media-airplay-button class="small-button">
<svg slot="icon" viewBox="0 0 23 23"><path d="M20.88 3.5H2.62a.87.87 0 0 0-.87.87v13.26a.87.87 0 0 0 .87.87h3.4l1.73-2h-4v-11h16v11h-4l1.72 2h3.4a.87.87 0 0 0 .87-.87V4.37a.87.87 0 0 0-.86-.87Zm-8.75 11.44a.5.5 0 0 0-.76 0l-4.91 5.73a.5.5 0 0 0 .38.83h9.82a.501.501 0 0 0 .38-.83l-4.91-5.73Z"/></svg>
</media-airplay-button>
</div>
<div slot="centered-chrome">
<media-play-button>
<svg slot="play" viewBox="0 0 16 16"><path d="M13.6 7.2 5.1 3c-.6-.3-1.2.1-1.2.7v8.5c0 .6.7 1 1.2.7l8.5-4.2c.6-.3.6-1.1 0-1.5z"/></svg>
<svg slot="pause" viewBox="0 0 16 16"><path d="M11.8 14c-.5 0-.9-.4-.9-.9V2.9c0-.5.4-.9.9-.9s.9.4.9.9v10.2c0 .5-.4.9-.9.9zM4.1 14c-.5 0-.9-.4-.9-.9V2.9c0-.5.4-.9.9-.9s.9.4.9.9v10.2c-.1.5-.5.9-.9.9z"/></svg>
</media-play-button>
</div>
<media-control-bar>
<media-play-button class="small-button">
<svg slot="play" viewBox="0 0 16 16"><path d="M13.6 7.2 5.1 3c-.6-.3-1.2.1-1.2.7v8.5c0 .6.7 1 1.2.7l8.5-4.2c.6-.3.6-1.1 0-1.5z"/></svg>
<svg slot="pause" viewBox="0 0 16 16"><path d="M11.8 14c-.5 0-.9-.4-.9-.9V2.9c0-.5.4-.9.9-.9s.9.4.9.9v10.2c0 .5-.4.9-.9.9zM4.1 14c-.5 0-.9-.4-.9-.9V2.9c0-.5.4-.9.9-.9s.9.4.9.9v10.2c-.1.5-.5.9-.9.9z"/></svg>
</media-play-button>
<div class="media-volume-wrapper">
<media-mute-button class="small-button">
<svg slot="off" viewBox="0 0 16 16"><path d="M7 2.2 4.2 5.1v.1H1.4c-.5 0-.9.4-.9.9V10c0 .5.4.9.9.9h2.8L7 13.8c.3.3.8.1.8-.3v-11c0-.4-.5-.6-.8-.3ZM13.4 8l2-2" fill-rule="nonzero"/><path d="M15.622 5.479a.606.606 0 0 1 0 .857l-4.286 4.286a.606.606 0 1 1-.857-.857l4.286-4.286a.606.606 0 0 1 .857 0Z"/><path d="M10.479 5.479a.606.606 0 0 0 0 .857l4.286 4.286a.606.606 0 1 0 .857-.857l-4.286-4.286a.606.606 0 0 0-.857 0Z"/></svg>
<svg slot="low" viewBox="0 0 16 16"><path d="m7.1 2.2-2.8 3H1.5c-.5 0-.9.4-.9.9V10c0 .5.4.9.9.9h2.8l2.8 2.9c.3.3.8.1.8-.3v-11c0-.4-.5-.6-.8-.3zM10.3 11.4c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9.6-.6 1-1.4 1-2.3s-.4-1.6-1-2.3c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 .9.8 1.4 2 1.4 3.2s-.5 2.3-1.4 3.2c-.2.2-.4.2-.5.2z"/></svg>
<svg slot="medium" viewBox="0 0 16 16"><path d="m7.1 2.2-2.8 3H1.5c-.5 0-.9.4-.9.9V10c0 .5.4.9.9.9h2.8l2.8 2.9c.3.3.8.1.8-.3v-11c0-.4-.5-.6-.8-.3zM12.6 13.8c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9 1.3-1.2 2-2.8 2-4.5s-.7-3.3-2-4.5c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 1.5 1.5 2.3 3.4 2.3 5.4 0 2.1-.8 4-2.3 5.4-.2.1-.4.2-.5.2z"/><path d="M10.3 11.4c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9.6-.6 1-1.4 1-2.3s-.4-1.6-1-2.3c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 .9.8 1.4 2 1.4 3.2s-.5 2.3-1.4 3.2c-.2.2-.4.2-.5.2z"/></svg>
<svg slot="high" viewBox="0 0 16 16"><path d="m7.1 2.2-2.8 3H1.5c-.5 0-.9.4-.9.9V10c0 .5.4.9.9.9h2.8l2.8 2.9c.3.3.8.1.8-.3v-11c0-.4-.5-.6-.8-.3zM12.6 13.8c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9 1.3-1.2 2-2.8 2-4.5s-.7-3.3-2-4.5c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 1.5 1.5 2.3 3.4 2.3 5.4 0 2.1-.8 4-2.3 5.4-.2.1-.4.2-.5.2z"/><path d="M10.3 11.4c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9.6-.6 1-1.4 1-2.3s-.4-1.6-1-2.3c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 .9.8 1.4 2 1.4 3.2s-.5 2.3-1.4 3.2c-.2.2-.4.2-.5.2z"/></svg>
</media-mute-button>
<div class="media-volume-range-wrapper">
<media-volume-range></media-volume-range>
</div>
</div>
<media-time-display showduration></media-time-display>
<media-time-range>
<media-preview-thumbnail slot="preview"></media-preview-thumbnail>
<media-preview-time-display slot="preview"></media-preview-time-display>
</media-time-range>
<media-captions-button class="small-button">
<svg slot="off" viewBox="0 0 16 16"><path d="M12.6 13.7H3.4C2 13.7.8 12.6.8 11.1V4.9c0-1.4 1.1-2.6 2.6-2.6h9.3c1.4 0 2.6 1.1 2.6 2.6v6.2c-.1 1.5-1.3 2.6-2.7 2.6z"/><path fill="#fff" d="M4.7 8H3.2c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h1.5c.2 0 .4.2.4.4s-.2.4-.4.4zM12.5 8H6.7c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h5.7c.2 0 .4.2.4.4s-.1.4-.3.4zM7.7 10.2H3.2c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h4.6c.2 0 .4.2.4.4-.1.2-.3.4-.5.4zM12.5 10.2H9.8c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h2.7c.2 0 .4.2.4.4s-.2.4-.4.4z"/></svg>
<svg slot="on" viewBox="0 0 16 16"><path d="M4.7 8H3.2c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h1.5c.2 0 .4.2.4.4s-.2.4-.4.4zM12.5 8H6.7c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h5.7c.2 0 .4.2.4.4s-.1.4-.3.4zM7.7 10.2H3.2c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h4.6c.2 0 .4.2.4.4-.1.2-.3.4-.5.4zM12.5 10.2H9.8c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h2.7c.2 0 .4.2.4.4s-.2.4-.4.4z"/></svg>
</media-captions-button>
<media-pip-button class="small-button">
<svg slot="enter" viewBox="0 0 16 16"><path d="M14.2 13.1H1.8c-.4 0-.7-.3-.7-.7V3.5c0-.4.3-.7.7-.7h12.3c.4 0 .7.3.7.7v8.9c.1.5-.2.7-.6.7zM2.5 11.8h11V4.3h-11v7.5z"/><path d="M7.2 7.3h5.1v3.1H7.2z"/></svg>
<svg slot="exit" viewBox="0 0 16 16"><path d="M14.2 13.1H1.8c-.4 0-.7-.3-.7-.7V3.5c0-.4.3-.7.7-.7h12.3c.4 0 .7.3.7.7v8.9c.1.5-.2.7-.6.7zM2.5 11.8h11V4.3h-11v7.5z"/><path d="M7.2 7.3h5.1v3.1H7.2z"/></svg>
</media-pip-button>
<media-fullscreen-button class="small-button">
<svg slot="enter" viewBox="0 0 16 16"><path d="M2.9 6.6c-.4 0-.7-.3-.7-.7v-3c0-.4.3-.7.7-.7h3c.4 0 .7.3.7.7s-.2.7-.6.7H3.6V6c0 .3-.3.6-.7.6zM13.1 6.6c-.4 0-.7-.3-.7-.7V3.6H10c-.4 0-.7-.3-.7-.7s.3-.7.7-.7h3c.4 0 .7.3.7.7v3c.1.4-.2.7-.6.7zM6 13.8H3c-.4 0-.7-.3-.7-.7v-3c0-.4.3-.7.7-.7.4 0 .7.3.7.7v2.4H6c.4 0 .7.3.7.7-.1.3-.4.6-.7.6zM13.1 13.8h-3c-.4 0-.7-.3-.7-.7 0-.4.3-.7.7-.7h2.4V10c0-.4.3-.7.7-.7.4 0 .7.3.7.7v3c-.1.5-.4.8-.8.8z"/></svg>
<svg slot="exit" viewBox="0 0 16 16"><path d="M2.9 6.6c-.4 0-.7-.3-.7-.7v-3c0-.4.3-.7.7-.7h3c.4 0 .7.3.7.7s-.2.7-.6.7H3.6V6c0 .3-.3.6-.7.6zM13.1 6.6c-.4 0-.7-.3-.7-.7V3.6H10c-.4 0-.7-.3-.7-.7s.3-.7.7-.7h3c.4 0 .7.3.7.7v3c.1.4-.2.7-.6.7zM6 13.8H3c-.4 0-.7-.3-.7-.7v-3c0-.4.3-.7.7-.7.4 0 .7.3.7.7v2.4H6c.4 0 .7.3.7.7-.1.3-.4.6-.7.6zM13.1 13.8h-3c-.4 0-.7-.3-.7-.7 0-.4.3-.7.7-.7h2.4V10c0-.4.3-.7.7-.7.4 0 .7.3.7.7v3c-.1.5-.4.8-.8.8z"/></svg>
</media-fullscreen-button>
</media-control-bar>
</media-controller>
`;
}
class MediaThemeDemuxed2022Element extends MediaThemeElement {
static template = template;
}
if (globalThis.customElements && !globalThis.customElements.get('media-theme-demuxed-2022')) {
globalThis.customElements.define('media-theme-demuxed-2022', MediaThemeDemuxed2022Element);
}
export default MediaThemeDemuxed2022Element;

View File

@@ -0,0 +1,7 @@
import MediaThemeDemuxed2022Element from './media-theme.js';
declare const MediaThemeDemuxed2022: React.ForwardRefExoticComponent<
React.DetailedHTMLProps<React.HTMLAttributes<MediaThemeDemuxed2022Element>, MediaThemeDemuxed2022Element>
>;
export default MediaThemeDemuxed2022;

View File

@@ -0,0 +1,94 @@
'use client';
import React from 'react';
import Element from './media-theme.js';
export default React.forwardRef((allProps, ref) => {
let { children, suppressHydrationWarning, ...props } = allProps;
const elementRef = React.useRef(null);
for (let name in props) {
if (name[0] === 'o' && name[1] === 'n') {
const useCapture = name.endsWith('Capture');
const eventName = name.slice(2, useCapture ? name.length - 7 : undefined).toLowerCase();
const callback = props[name];
React.useEffect(() => {
const eventTarget = elementRef?.current;
if (!eventTarget || typeof callback !== 'function') return;
eventTarget.addEventListener(eventName, callback, useCapture);
return () => {
eventTarget.removeEventListener(eventName, callback, useCapture);
};
}, [elementRef?.current, callback]);
}
}
const attrs = propsToAttrs(props);
// Only render the custom element template HTML on the server..
// The custom element will render itself on the client.
if (typeof window === 'undefined' && Element?.getTemplateHTML && Element?.shadowRootOptions) {
const { mode, delegatesFocus } = Element.shadowRootOptions;
const templateShadowRoot = React.createElement('template', {
shadowrootmode: mode,
shadowrootdelegatesfocus: delegatesFocus,
dangerouslySetInnerHTML: {
__html: Element.getTemplateHTML(attrs),
},
});
children = [templateShadowRoot, children];
}
return React.createElement('media-theme-demuxed-2022', {
...attrs,
ref: React.useCallback(
(node) => {
elementRef.current = node;
if (typeof ref === 'function') {
ref(node);
} else if (ref !== null) {
ref.current = node;
}
},
[ref]
),
children,
suppressHydrationWarning,
});
});
const ReactPropToAttrNameMap = {
className: 'class',
classname: 'class',
htmlFor: 'for',
viewBox: 'viewBox',
};
function propsToAttrs(props = {}) {
let attrs = {};
for (let [propName, propValue] of Object.entries(props)) {
let attrName = toAttrName(propName, propValue);
if (attrName) attrs[attrName] = toAttrValue(propValue);
}
return attrs;
}
function toAttrName(propName, propValue) {
if (ReactPropToAttrNameMap[propName]) return ReactPropToAttrNameMap[propName];
if (typeof propValue == 'undefined') return undefined;
if (typeof propValue === 'boolean' && !propValue) return undefined;
if (propName.startsWith('on') && typeof propValue === 'function') return undefined;
if (/[A-Z]/.test(propName)) return propName.toLowerCase();
return propName;
}
function toAttrValue(propValue) {
if (typeof propValue === 'boolean') return '';
if (Array.isArray(propValue)) return propValue.join(' ');
return propValue;
}

View File

@@ -0,0 +1,35 @@
{
"name": "@player.style/demuxed-2022",
"version": "0.0.8",
"description": "A media player theme created for Demuxed 2022",
"author": "@muxinc",
"license": "MIT",
"homepage": "https://github.com/muxinc/player.style#readme",
"bugs": {
"url": "https://github.com/muxinc/player.style/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/muxinc/player.style.git",
"directory": "themes/demuxed-2022"
},
"files": [
"dist"
],
"type": "module",
"main": "dist/media-theme.js",
"exports": {
".": "./dist/media-theme.js",
"./react": "./dist/react.js"
},
"scripts": {
"clean": "rimraf dist",
"build": "build-theme"
},
"peerDependencies": {
"media-chrome": ">=1.0.0"
},
"devDependencies": {
"build-theme": "^0.0.4"
}
}

View File

@@ -0,0 +1,292 @@
<style>
:host {
--media-primary-color: black;
--media-tertiary-color: var(--media-accent-color, #7596CC);
--media-text-color: white;
--media-control-hover-background: transparent;
--media-range-track-height: 6px;
--media-range-bar-color: white;
--media-range-track-background: rgba(0,0,0,0.4);
--media-range-track-border-radius: 9999px;
--media-range-thumb-background: var(--media-tertiary-color);
--media-range-thumb-width: 14px;
--media-range-thumb-height: 14px;
--media-tooltip-display: none;
}
:host([mediastreamtype="live"]) media-time-range,
:host([mediastreamtype="live"]) media-time-display {
opacity: 0;
}
media-control-bar {
position: relative;
margin: 30px;
padding: 10px 14px;
border-radius: 9999px;
background: rgba(0,0,0,0.2);
align-items: center;
}
media-control-bar :first-child {
margin: 0 5px 0 0;
}
media-control-bar :last-child {
margin: 0 0 0 5px;
}
.small-button {
position: relative;
flex: none;
margin: 0 5px;
display: flex;
align-items: center;
justify-items: center;
height: 32px;
width: 32px;
background: var(--media-secondary-color, white);
border-radius: 9999px;
}
.small-button svg {
position: absolute;
overflow: hidden;
width: 100%;
height: 20px;
margin: 0 !important;
padding: 0 !important;
}
.small-button:hover {
box-shadow: 0 0 0 calc(2px) var(--media-tertiary-color);
}
div[slot="centered-chrome"] media-play-button {
position: relative;
flex: none;
display: flex;
margin-bottom: 10px;
align-items: center;
justify-items: center;
height: 96px;
width: 96px;
background: rgb(0 0 0 / 0.8);
border-radius: 9999px;
}
div[slot="centered-chrome"] media-play-button:hover {
box-shadow: 0 0 0 calc(2px) var(--media-tertiary-color);
}
div[slot="centered-chrome"] media-play-button svg {
fill: #fff;
height: 64px;
}
media-time-range {
--media-secondary-color: transparent;
height: 32px;
margin: 0 8px 0 0;
}
media-volume-range {
height: 100%;
}
media-time-display {
--media-secondary-color: transparent;
min-width: 92px;
padding: 0 6px 3px 8px;
}
media-time-display, media-preview-time-display {
font-size: 14px;
font-family: sofia-pro, sans-serif;
}
.demuxed-gradient-bottom {
padding-top: 37px;
position: absolute;
width: 100%;
height: 200px;
bottom: 0;
pointer-events: none;
background-position: bottom;
background-repeat: repeat-x;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAACqCAYAAABsziWkAAAAAXNSR0IArs4c6QAAAQVJREFUOE9lyNdHBQAAhfHb3nvvuu2997jNe29TJJEkkkgSSSSJJJJEEkkiifRH5jsP56Xz8PM5gcC/xfDEmjhKxEOCSaREEiSbFEqkQppJpzJMJiWyINvkUCIX8kw+JQqg0BRRxaaEEqVQZsopUQGVpooS1VBjglStqaNEPTSYRko0QbNpoUQrtJl2qsN0UqILuk0PJXqhz/RTYgAGzRA1bEYoMQpjZpwSExAyk5SYgmkzQ82aOUqEIWKilJiHBbNIiSVYhhVYhTVYhw3YhC3Yhh3YhT3YhwM4hCM4hhM4hTM4hwu4hCu4hhu4hTu4hwd4hCd4hhd4hTd4hw/4hC/4hh/4/QM2/id28uIEJAAAAABJRU5ErkJggg==");
}
div[slot="top-chrome"] {
width: calc(100% - 36px);
display: flex;
flex-direction: row-reverse;
padding-right: 36px;
}
div[slot="top-chrome"] .small-button {
margin: 32px 8px;
}
media-controller[breakpointsm] .media-volume-wrapper {
position: relative;
padding-left: 6px;
}
.media-volume-range-wrapper {
width: 122px;
height: 34px;
overflow: hidden;
opacity: 0;
transform: rotate(-90deg);
position: absolute;
top: -75px;
left: -52px;
border-left: 16px solid transparent;
}
media-volume-range {
border-radius: 0 9999px 9999px 0;
background: rgba(0,0,0,0.2);
--media-range-track-width: 80px;
}
media-mute-button:hover + .media-volume-range-wrapper,
media-mute-button:focus + .media-volume-range-wrapper,
media-mute-button:focus-within + .media-volume-range-wrapper,
.media-volume-range-wrapper:hover,
.media-volume-range-wrapper:focus,
.media-volume-range-wrapper:focus-within {
opacity: 1;
}
media-controller:not([breakpointsm]) media-control-bar {
position: static;
background: transparent;
margin: 0;
padding: 22px 15px;
}
media-controller:not([breakpointsm]) media-time-display,
media-controller:not([breakpointsm]) .media-volume-range-wrapper {
display: none;
}
media-controller:not([breakpointsm]) .small-button {
display: none;
width: 48px;
height: 48px;
}
media-controller:not([breakpointsm]) .small-button svg {
transform: scale(1.4);
}
media-controller:not([breakpointsm]) div[slot="top-chrome"] {
width: calc(100% - 13px);
padding-right: 13px;
}
media-controller:not([breakpointsm]) div[slot="top-chrome"] .small-button {
display: flex;
margin: 22px 7px;
}
media-controller:not([breakpointsm]) media-fullscreen-button.small-button {
display: flex;
}
media-controller:not([breakpointsm]) media-airplay-button[mediaairplayunavailable].small-button {
display: none;
}
media-controller:not([breakpointsm]) media-cast-button[mediacastunavailable].small-button {
display: none;
}
media-controller:not([breakpointsm]) media-mute-button.small-button {
display: flex;
}
media-controller:not([breakpointsm]) media-captions-button.small-button {
position: absolute;
top: 22px;
left: 16px;
}
media-controller:not([breakpointsm]) div[slot="centered-chrome"] media-play-button {
z-index: 1;
height: 72px;
width: 72px;
}
media-controller:not([breakpointsm]) div[slot="centered-chrome"] media-play-button svg {
margin-left: -2px;
height: 48px;
}
</style>
<media-controller
breakpoints="xs:360 sm:600 md:760 lg:960 xl:1100"
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<div class="demuxed-gradient-bottom"></div>
<div slot="top-chrome">
<media-cast-button class="small-button">
<svg slot="enter" viewBox="0 0 26 26"><path d="M2.5 18.5v3h3c0-1.7-1.34-3-3-3ZM2.5 14.5v2c2.76 0 5 2.2 5 5h2c0-3.87-3.13-7-7-7Z"/><path d="M2.5 10.5v2c4.97 0 9 4 9 9h2c0-6.08-4.93-11-11-11Z"/><path d="M22.5 3.5h-18c-1.1 0-2 .9-2 2v3h2v-3h18v14h-7v2h7c1.1 0 2-.9 2-2v-14c0-1.1-.9-2-2-2Z"/></svg>
<svg slot="exit" viewBox="0 0 26 26"><path d="M2.5 18.5v3h3c0-1.7-1.34-3-3-3ZM2.5 14.5v2c2.76 0 5 2.2 5 5h2c0-3.87-3.13-7-7-7Z"/><path d="M2.5 10.5v2c4.97 0 9 4 9 9h2c0-6.08-4.93-11-11-11Z"/><path d="M22.5 3.5h-18c-1.1 0-2 .9-2 2v3h2v-3h18v14h-7v2h7c1.1 0 2-.9 2-2v-14c0-1.1-.9-2-2-2Z"/></svg>
</media-cast-button>
<media-airplay-button class="small-button">
<svg slot="icon" viewBox="0 0 23 23"><path d="M20.88 3.5H2.62a.87.87 0 0 0-.87.87v13.26a.87.87 0 0 0 .87.87h3.4l1.73-2h-4v-11h16v11h-4l1.72 2h3.4a.87.87 0 0 0 .87-.87V4.37a.87.87 0 0 0-.86-.87Zm-8.75 11.44a.5.5 0 0 0-.76 0l-4.91 5.73a.5.5 0 0 0 .38.83h9.82a.501.501 0 0 0 .38-.83l-4.91-5.73Z"/></svg>
</media-airplay-button>
</div>
<div slot="centered-chrome">
<media-play-button>
<svg slot="play" viewBox="0 0 16 16"><path d="M13.6 7.2 5.1 3c-.6-.3-1.2.1-1.2.7v8.5c0 .6.7 1 1.2.7l8.5-4.2c.6-.3.6-1.1 0-1.5z"/></svg>
<svg slot="pause" viewBox="0 0 16 16"><path d="M11.8 14c-.5 0-.9-.4-.9-.9V2.9c0-.5.4-.9.9-.9s.9.4.9.9v10.2c0 .5-.4.9-.9.9zM4.1 14c-.5 0-.9-.4-.9-.9V2.9c0-.5.4-.9.9-.9s.9.4.9.9v10.2c-.1.5-.5.9-.9.9z"/></svg>
</media-play-button>
</div>
<media-control-bar>
<media-play-button class="small-button">
<svg slot="play" viewBox="0 0 16 16"><path d="M13.6 7.2 5.1 3c-.6-.3-1.2.1-1.2.7v8.5c0 .6.7 1 1.2.7l8.5-4.2c.6-.3.6-1.1 0-1.5z"/></svg>
<svg slot="pause" viewBox="0 0 16 16"><path d="M11.8 14c-.5 0-.9-.4-.9-.9V2.9c0-.5.4-.9.9-.9s.9.4.9.9v10.2c0 .5-.4.9-.9.9zM4.1 14c-.5 0-.9-.4-.9-.9V2.9c0-.5.4-.9.9-.9s.9.4.9.9v10.2c-.1.5-.5.9-.9.9z"/></svg>
</media-play-button>
<div class="media-volume-wrapper">
<media-mute-button class="small-button">
<svg slot="off" viewBox="0 0 16 16"><path d="M7 2.2 4.2 5.1v.1H1.4c-.5 0-.9.4-.9.9V10c0 .5.4.9.9.9h2.8L7 13.8c.3.3.8.1.8-.3v-11c0-.4-.5-.6-.8-.3ZM13.4 8l2-2" fill-rule="nonzero"/><path d="M15.622 5.479a.606.606 0 0 1 0 .857l-4.286 4.286a.606.606 0 1 1-.857-.857l4.286-4.286a.606.606 0 0 1 .857 0Z"/><path d="M10.479 5.479a.606.606 0 0 0 0 .857l4.286 4.286a.606.606 0 1 0 .857-.857l-4.286-4.286a.606.606 0 0 0-.857 0Z"/></svg>
<svg slot="low" viewBox="0 0 16 16"><path d="m7.1 2.2-2.8 3H1.5c-.5 0-.9.4-.9.9V10c0 .5.4.9.9.9h2.8l2.8 2.9c.3.3.8.1.8-.3v-11c0-.4-.5-.6-.8-.3zM10.3 11.4c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9.6-.6 1-1.4 1-2.3s-.4-1.6-1-2.3c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 .9.8 1.4 2 1.4 3.2s-.5 2.3-1.4 3.2c-.2.2-.4.2-.5.2z"/></svg>
<svg slot="medium" viewBox="0 0 16 16"><path d="m7.1 2.2-2.8 3H1.5c-.5 0-.9.4-.9.9V10c0 .5.4.9.9.9h2.8l2.8 2.9c.3.3.8.1.8-.3v-11c0-.4-.5-.6-.8-.3zM12.6 13.8c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9 1.3-1.2 2-2.8 2-4.5s-.7-3.3-2-4.5c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 1.5 1.5 2.3 3.4 2.3 5.4 0 2.1-.8 4-2.3 5.4-.2.1-.4.2-.5.2z"/><path d="M10.3 11.4c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9.6-.6 1-1.4 1-2.3s-.4-1.6-1-2.3c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 .9.8 1.4 2 1.4 3.2s-.5 2.3-1.4 3.2c-.2.2-.4.2-.5.2z"/></svg>
<svg slot="high" viewBox="0 0 16 16"><path d="m7.1 2.2-2.8 3H1.5c-.5 0-.9.4-.9.9V10c0 .5.4.9.9.9h2.8l2.8 2.9c.3.3.8.1.8-.3v-11c0-.4-.5-.6-.8-.3zM12.6 13.8c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9 1.3-1.2 2-2.8 2-4.5s-.7-3.3-2-4.5c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 1.5 1.5 2.3 3.4 2.3 5.4 0 2.1-.8 4-2.3 5.4-.2.1-.4.2-.5.2z"/><path d="M10.3 11.4c-.2 0-.3-.1-.4-.2-.3-.3-.3-.6 0-.9.6-.6 1-1.4 1-2.3s-.4-1.6-1-2.3c-.3-.3-.3-.6 0-.9.3-.3.6-.3.9 0 .9.8 1.4 2 1.4 3.2s-.5 2.3-1.4 3.2c-.2.2-.4.2-.5.2z"/></svg>
</media-mute-button>
<div class="media-volume-range-wrapper">
<media-volume-range></media-volume-range>
</div>
</div>
<media-time-display showduration></media-time-display>
<media-time-range>
<media-preview-thumbnail slot="preview"></media-preview-thumbnail>
<media-preview-time-display slot="preview"></media-preview-time-display>
</media-time-range>
<media-captions-button class="small-button">
<svg slot="off" viewBox="0 0 16 16"><path d="M12.6 13.7H3.4C2 13.7.8 12.6.8 11.1V4.9c0-1.4 1.1-2.6 2.6-2.6h9.3c1.4 0 2.6 1.1 2.6 2.6v6.2c-.1 1.5-1.3 2.6-2.7 2.6z"/><path fill="#fff" d="M4.7 8H3.2c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h1.5c.2 0 .4.2.4.4s-.2.4-.4.4zM12.5 8H6.7c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h5.7c.2 0 .4.2.4.4s-.1.4-.3.4zM7.7 10.2H3.2c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h4.6c.2 0 .4.2.4.4-.1.2-.3.4-.5.4zM12.5 10.2H9.8c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h2.7c.2 0 .4.2.4.4s-.2.4-.4.4z"/></svg>
<svg slot="on" viewBox="0 0 16 16"><path d="M4.7 8H3.2c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h1.5c.2 0 .4.2.4.4s-.2.4-.4.4zM12.5 8H6.7c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h5.7c.2 0 .4.2.4.4s-.1.4-.3.4zM7.7 10.2H3.2c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h4.6c.2 0 .4.2.4.4-.1.2-.3.4-.5.4zM12.5 10.2H9.8c-.2 0-.4-.2-.4-.4s.2-.4.4-.4h2.7c.2 0 .4.2.4.4s-.2.4-.4.4z"/></svg>
</media-captions-button>
<media-pip-button class="small-button">
<svg slot="enter" viewBox="0 0 16 16"><path d="M14.2 13.1H1.8c-.4 0-.7-.3-.7-.7V3.5c0-.4.3-.7.7-.7h12.3c.4 0 .7.3.7.7v8.9c.1.5-.2.7-.6.7zM2.5 11.8h11V4.3h-11v7.5z"/><path d="M7.2 7.3h5.1v3.1H7.2z"/></svg>
<svg slot="exit" viewBox="0 0 16 16"><path d="M14.2 13.1H1.8c-.4 0-.7-.3-.7-.7V3.5c0-.4.3-.7.7-.7h12.3c.4 0 .7.3.7.7v8.9c.1.5-.2.7-.6.7zM2.5 11.8h11V4.3h-11v7.5z"/><path d="M7.2 7.3h5.1v3.1H7.2z"/></svg>
</media-pip-button>
<media-fullscreen-button class="small-button">
<svg slot="enter" viewBox="0 0 16 16"><path d="M2.9 6.6c-.4 0-.7-.3-.7-.7v-3c0-.4.3-.7.7-.7h3c.4 0 .7.3.7.7s-.2.7-.6.7H3.6V6c0 .3-.3.6-.7.6zM13.1 6.6c-.4 0-.7-.3-.7-.7V3.6H10c-.4 0-.7-.3-.7-.7s.3-.7.7-.7h3c.4 0 .7.3.7.7v3c.1.4-.2.7-.6.7zM6 13.8H3c-.4 0-.7-.3-.7-.7v-3c0-.4.3-.7.7-.7.4 0 .7.3.7.7v2.4H6c.4 0 .7.3.7.7-.1.3-.4.6-.7.6zM13.1 13.8h-3c-.4 0-.7-.3-.7-.7 0-.4.3-.7.7-.7h2.4V10c0-.4.3-.7.7-.7.4 0 .7.3.7.7v3c-.1.5-.4.8-.8.8z"/></svg>
<svg slot="exit" viewBox="0 0 16 16"><path d="M2.9 6.6c-.4 0-.7-.3-.7-.7v-3c0-.4.3-.7.7-.7h3c.4 0 .7.3.7.7s-.2.7-.6.7H3.6V6c0 .3-.3.6-.7.6zM13.1 6.6c-.4 0-.7-.3-.7-.7V3.6H10c-.4 0-.7-.3-.7-.7s.3-.7.7-.7h3c.4 0 .7.3.7.7v3c.1.4-.2.7-.6.7zM6 13.8H3c-.4 0-.7-.3-.7-.7v-3c0-.4.3-.7.7-.7.4 0 .7.3.7.7v2.4H6c.4 0 .7.3.7.7-.1.3-.4.6-.7.6zM13.1 13.8h-3c-.4 0-.7-.3-.7-.7 0-.4.3-.7.7-.7h2.4V10c0-.4.3-.7.7-.7.4 0 .7.3.7.7v3c-.1.5-.4.8-.8.8z"/></svg>
</media-fullscreen-button>
</media-control-bar>
</media-controller>

View File

@@ -0,0 +1,29 @@
# Changelog
## [0.0.3](https://github.com/muxinc/player.style/compare/@player.style/instaplay@0.0.2...@player.style/instaplay@0.0.3) (2024-09-10)
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.3 to ^0.0.4
## [0.0.2](https://github.com/muxinc/player.style/compare/@player.style/instaplay-v0.0.1...@player.style/instaplay@0.0.2) (2024-08-15)
### Features
* add Instaplay theme ([#58](https://github.com/muxinc/player.style/issues/58)) ([fb84b90](https://github.com/muxinc/player.style/commit/fb84b909f9c7dce6b8cd15ce3cc6af9ef6f21c1f))
### Bug Fixes
* upgrade to Media Chrome v4 ([#64](https://github.com/muxinc/player.style/issues/64)) ([be68af2](https://github.com/muxinc/player.style/commit/be68af2f9c3a6ff6674b9951f0b34f2bfdb042aa))
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.2 to ^0.0.3

View File

@@ -0,0 +1,13 @@
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
declare global {
interface HTMLElementTagNameMap {
'media-theme-instaplay': MediaThemeInstaplayElement;
}
}
declare class MediaThemeInstaplayElement extends MediaThemeElement {
static template: HTMLTemplateElement;
}
export default MediaThemeInstaplayElement;

View File

@@ -0,0 +1,147 @@
<style>
:host {
--_primary-color: var(--media-primary-color, #fff);
--_secondary-color: var(--media-secondary-color, rgb(38 38 38 / 0.75));
--_accent-color: var(--media-accent-color, #fff);
--media-icon-color: var(--_primary-color);
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-range-thumb-opacity: 0;
--media-control-height: 1.2em;
--media-font-weight: bold;
--media-tooltip-display: none;
font-size: 16px;
color: var(--_primary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
:host {
--_secondary-color: color-mix(
in srgb,
var(--media-secondary-color, rgb(38 38 38)) 75%,
transparent
);
--_accent-color: color-mix(in srgb, var(--media-accent-color, #fff) 75%, transparent);
}
}
.spacer {
flex: 1;
}
media-controller {
display: block;
overflow: hidden;
container: media-theme-instaplay / inline-size;
}
media-control-bar {
margin: 0.4em 0.8em;
}
media-play-button,
media-mute-button {
padding: .3em;
border-radius: 50%;
--media-control-background: var(--_secondary-color);
--media-control-hover-background: var(--_secondary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
media-play-button,
media-mute-button {
--media-control-hover-background: color-mix(in srgb, var(--_secondary-color) 85%, transparent);
}
}
media-play-button {
--media-button-icon-transform: translateX(.05em);
display: none;
padding: .7em;
}
media-play-button[mediapaused] {
display: block;
line-height: 1;
}
media-time-range {
--media-range-track-height: 4px;
--media-range-track-transition: height 0.1s linear;
--media-range-bar-color: var(--_accent-color);
--media-range-track-background: rgb(38 38 38 / 0.25);
--media-time-range-buffered-color: rgb(38 38 38 / 0.3);
--media-range-padding-left: 0;
--media-range-padding-right: 0;
--media-preview-time-background: var(--_secondary-color);
--media-preview-box-margin: 0 0 3px;
--media-preview-time-background: transparent;
--media-preview-thumbnail-border-radius: 4px;
width: 100%;
height: 8px;
bottom: -3px;
}
media-time-range::part(preview-box) {
/* Add more space so thumb doesn't hide preview. */
--media-preview-box-margin: 0 0 20px;
display: grid;
}
media-preview-thumbnail,
media-preview-time-display {
grid-area: 1 / 1;
}
media-preview-time-display {
place-self: end center;
position: relative;
line-height: 2;
}
@container (inline-size >=384px) {
[role='button'],
media-controller {
font-size: 17px;
}
media-time-range {
bottom: -2px;
}
media-time-range::part(preview-box) {
--media-preview-box-margin: 0 0 0.5em;
}
}
</style>
<media-controller
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<media-play-button slot="centered-chrome">
<svg slot="play" aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
<path fill-rule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clip-rule="evenodd" />
</svg>
</media-play-button>
<media-control-bar noautohide>
<div class="spacer"></div>
<media-mute-button></media-mute-button>
</media-control-bar>
<media-time-range noautohide>
<media-preview-thumbnail slot="preview"></media-preview-thumbnail>
<media-preview-time-display slot="preview"></media-preview-time-display>
</media-time-range>
<slot></slot>
</media-controller>

View File

@@ -0,0 +1,177 @@
/*
<media-theme-instaplay>
<video
slot="media"
src="https://stream.mux.com/fXNzVtmtWuyz00xnSrJg4OJH6PyNo6D02UzmgeKGkP5YQ/high.mp4"
></video>
</media-theme-instaplay>
*/
import 'media-chrome';
import { globalThis } from 'media-chrome/dist/utils/server-safe-globals.js';
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
import 'media-chrome/dist/menu/index.js';
const template = globalThis.document?.createElement?.('template');
if (template) {
template.innerHTML = /*html*/`
<style>
:host {
--_primary-color: var(--media-primary-color, #fff);
--_secondary-color: var(--media-secondary-color, rgb(38 38 38 / 0.75));
--_accent-color: var(--media-accent-color, #fff);
--media-icon-color: var(--_primary-color);
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-range-thumb-opacity: 0;
--media-control-height: 1.2em;
--media-font-weight: bold;
--media-tooltip-display: none;
font-size: 16px;
color: var(--_primary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
:host {
--_secondary-color: color-mix(
in srgb,
var(--media-secondary-color, rgb(38 38 38)) 75%,
transparent
);
--_accent-color: color-mix(in srgb, var(--media-accent-color, #fff) 75%, transparent);
}
}
.spacer {
flex: 1;
}
media-controller {
display: block;
overflow: hidden;
container: media-theme-instaplay / inline-size;
}
media-control-bar {
margin: 0.4em 0.8em;
}
media-play-button,
media-mute-button {
padding: .3em;
border-radius: 50%;
--media-control-background: var(--_secondary-color);
--media-control-hover-background: var(--_secondary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
media-play-button,
media-mute-button {
--media-control-hover-background: color-mix(in srgb, var(--_secondary-color) 85%, transparent);
}
}
media-play-button {
--media-button-icon-transform: translateX(.05em);
display: none;
padding: .7em;
}
media-play-button[mediapaused] {
display: block;
line-height: 1;
}
media-time-range {
--media-range-track-height: 4px;
--media-range-track-transition: height 0.1s linear;
--media-range-bar-color: var(--_accent-color);
--media-range-track-background: rgb(38 38 38 / 0.25);
--media-time-range-buffered-color: rgb(38 38 38 / 0.3);
--media-range-padding-left: 0;
--media-range-padding-right: 0;
--media-preview-time-background: var(--_secondary-color);
--media-preview-box-margin: 0 0 3px;
--media-preview-time-background: transparent;
--media-preview-thumbnail-border-radius: 4px;
width: 100%;
height: 8px;
bottom: -3px;
}
media-time-range::part(preview-box) {
/* Add more space so thumb doesn't hide preview. */
--media-preview-box-margin: 0 0 20px;
display: grid;
}
media-preview-thumbnail,
media-preview-time-display {
grid-area: 1 / 1;
}
media-preview-time-display {
place-self: end center;
position: relative;
line-height: 2;
}
@container (inline-size >=384px) {
[role='button'],
media-controller {
font-size: 17px;
}
media-time-range {
bottom: -2px;
}
media-time-range::part(preview-box) {
--media-preview-box-margin: 0 0 0.5em;
}
}
</style>
<media-controller
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<media-play-button slot="centered-chrome">
<svg slot="play" aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
<path fill-rule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clip-rule="evenodd" />
</svg>
</media-play-button>
<media-control-bar noautohide>
<div class="spacer"></div>
<media-mute-button></media-mute-button>
</media-control-bar>
<media-time-range noautohide>
<media-preview-thumbnail slot="preview"></media-preview-thumbnail>
<media-preview-time-display slot="preview"></media-preview-time-display>
</media-time-range>
<slot></slot>
</media-controller>
`;
}
class MediaThemeInstaplayElement extends MediaThemeElement {
static template = template;
}
if (globalThis.customElements && !globalThis.customElements.get('media-theme-instaplay')) {
globalThis.customElements.define('media-theme-instaplay', MediaThemeInstaplayElement);
}
export default MediaThemeInstaplayElement;

View File

@@ -0,0 +1,7 @@
import MediaThemeInstaplayElement from './media-theme.js';
declare const MediaThemeInstaplay: React.ForwardRefExoticComponent<
React.DetailedHTMLProps<React.HTMLAttributes<MediaThemeInstaplayElement>, MediaThemeInstaplayElement>
>;
export default MediaThemeInstaplay;

View File

@@ -0,0 +1,94 @@
'use client';
import React from 'react';
import Element from './media-theme.js';
export default React.forwardRef((allProps, ref) => {
let { children, suppressHydrationWarning, ...props } = allProps;
const elementRef = React.useRef(null);
for (let name in props) {
if (name[0] === 'o' && name[1] === 'n') {
const useCapture = name.endsWith('Capture');
const eventName = name.slice(2, useCapture ? name.length - 7 : undefined).toLowerCase();
const callback = props[name];
React.useEffect(() => {
const eventTarget = elementRef?.current;
if (!eventTarget || typeof callback !== 'function') return;
eventTarget.addEventListener(eventName, callback, useCapture);
return () => {
eventTarget.removeEventListener(eventName, callback, useCapture);
};
}, [elementRef?.current, callback]);
}
}
const attrs = propsToAttrs(props);
// Only render the custom element template HTML on the server..
// The custom element will render itself on the client.
if (typeof window === 'undefined' && Element?.getTemplateHTML && Element?.shadowRootOptions) {
const { mode, delegatesFocus } = Element.shadowRootOptions;
const templateShadowRoot = React.createElement('template', {
shadowrootmode: mode,
shadowrootdelegatesfocus: delegatesFocus,
dangerouslySetInnerHTML: {
__html: Element.getTemplateHTML(attrs),
},
});
children = [templateShadowRoot, children];
}
return React.createElement('media-theme-instaplay', {
...attrs,
ref: React.useCallback(
(node) => {
elementRef.current = node;
if (typeof ref === 'function') {
ref(node);
} else if (ref !== null) {
ref.current = node;
}
},
[ref]
),
children,
suppressHydrationWarning,
});
});
const ReactPropToAttrNameMap = {
className: 'class',
classname: 'class',
htmlFor: 'for',
viewBox: 'viewBox',
};
function propsToAttrs(props = {}) {
let attrs = {};
for (let [propName, propValue] of Object.entries(props)) {
let attrName = toAttrName(propName, propValue);
if (attrName) attrs[attrName] = toAttrValue(propValue);
}
return attrs;
}
function toAttrName(propName, propValue) {
if (ReactPropToAttrNameMap[propName]) return ReactPropToAttrNameMap[propName];
if (typeof propValue == 'undefined') return undefined;
if (typeof propValue === 'boolean' && !propValue) return undefined;
if (propName.startsWith('on') && typeof propValue === 'function') return undefined;
if (/[A-Z]/.test(propName)) return propName.toLowerCase();
return propName;
}
function toAttrValue(propValue) {
if (typeof propValue === 'boolean') return '';
if (Array.isArray(propValue)) return propValue.join(' ');
return propValue;
}

View File

@@ -0,0 +1,35 @@
{
"name": "@player.style/instaplay",
"version": "0.0.3",
"description": "Instaplay is a mobile-first theme inspired by playback experiences you can find in popular social media apps.",
"author": "@muxinc",
"license": "MIT",
"homepage": "https://github.com/muxinc/player.style#readme",
"bugs": {
"url": "https://github.com/muxinc/player.style/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/muxinc/player.style.git",
"directory": "themes/instaplay"
},
"files": [
"dist"
],
"type": "module",
"main": "dist/media-theme.js",
"exports": {
".": "./dist/media-theme.js",
"./react": "./dist/react.js"
},
"scripts": {
"clean": "rimraf dist",
"build": "build-theme"
},
"peerDependencies": {
"media-chrome": ">=1.0.0"
},
"devDependencies": {
"build-theme": "^0.0.4"
}
}

View File

@@ -0,0 +1,147 @@
<style>
:host {
--_primary-color: var(--media-primary-color, #fff);
--_secondary-color: var(--media-secondary-color, rgb(38 38 38 / 0.75));
--_accent-color: var(--media-accent-color, #fff);
--media-icon-color: var(--_primary-color);
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-range-thumb-opacity: 0;
--media-control-height: 1.2em;
--media-font-weight: bold;
--media-tooltip-display: none;
font-size: 16px;
color: var(--_primary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
:host {
--_secondary-color: color-mix(
in srgb,
var(--media-secondary-color, rgb(38 38 38)) 75%,
transparent
);
--_accent-color: color-mix(in srgb, var(--media-accent-color, #fff) 75%, transparent);
}
}
.spacer {
flex: 1;
}
media-controller {
display: block;
overflow: hidden;
container: media-theme-instaplay / inline-size;
}
media-control-bar {
margin: 0.4em 0.8em;
}
media-play-button,
media-mute-button {
padding: .3em;
border-radius: 50%;
--media-control-background: var(--_secondary-color);
--media-control-hover-background: var(--_secondary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
media-play-button,
media-mute-button {
--media-control-hover-background: color-mix(in srgb, var(--_secondary-color) 85%, transparent);
}
}
media-play-button {
--media-button-icon-transform: translateX(.05em);
display: none;
padding: .7em;
}
media-play-button[mediapaused] {
display: block;
line-height: 1;
}
media-time-range {
--media-range-track-height: 4px;
--media-range-track-transition: height 0.1s linear;
--media-range-bar-color: var(--_accent-color);
--media-range-track-background: rgb(38 38 38 / 0.25);
--media-time-range-buffered-color: rgb(38 38 38 / 0.3);
--media-range-padding-left: 0;
--media-range-padding-right: 0;
--media-preview-time-background: var(--_secondary-color);
--media-preview-box-margin: 0 0 3px;
--media-preview-time-background: transparent;
--media-preview-thumbnail-border-radius: 4px;
width: 100%;
height: 8px;
bottom: -3px;
}
media-time-range::part(preview-box) {
/* Add more space so thumb doesn't hide preview. */
--media-preview-box-margin: 0 0 20px;
display: grid;
}
media-preview-thumbnail,
media-preview-time-display {
grid-area: 1 / 1;
}
media-preview-time-display {
place-self: end center;
position: relative;
line-height: 2;
}
@container (inline-size >=384px) {
[role='button'],
media-controller {
font-size: 17px;
}
media-time-range {
bottom: -2px;
}
media-time-range::part(preview-box) {
--media-preview-box-margin: 0 0 0.5em;
}
}
</style>
<media-controller
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<media-play-button slot="centered-chrome">
<svg slot="play" aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
<path fill-rule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clip-rule="evenodd" />
</svg>
</media-play-button>
<media-control-bar noautohide>
<div class="spacer"></div>
<media-mute-button></media-mute-button>
</media-control-bar>
<media-time-range noautohide>
<media-preview-thumbnail slot="preview"></media-preview-thumbnail>
<media-preview-time-display slot="preview"></media-preview-time-display>
</media-time-range>
<slot></slot>
</media-controller>

View File

@@ -0,0 +1,69 @@
# Changelog
## [0.0.7](https://github.com/muxinc/player.style/compare/@player.style/microvideo@0.0.6...@player.style/microvideo@0.0.7) (2024-09-10)
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.3 to ^0.0.4
## [0.0.6](https://github.com/muxinc/player.style/compare/@player.style/microvideo@0.0.5...@player.style/microvideo@0.0.6) (2024-08-15)
### Bug Fixes
* improve color CSS vars & site color picker ([#49](https://github.com/muxinc/player.style/issues/49)) ([a8e8dc0](https://github.com/muxinc/player.style/commit/a8e8dc0898979e72d035af87233b2a0941fdcc7f))
* no render on preload none ([#38](https://github.com/muxinc/player.style/issues/38)) ([64dda58](https://github.com/muxinc/player.style/commit/64dda5825562da846edb33ddc7d4ba2548c08e00))
* remove unneeded package.json extra ([f869248](https://github.com/muxinc/player.style/commit/f86924841e9c04e68ac96c3c091eaf192f446772))
* upgrade to Media Chrome v4 ([#64](https://github.com/muxinc/player.style/issues/64)) ([be68af2](https://github.com/muxinc/player.style/commit/be68af2f9c3a6ff6674b9951f0b34f2bfdb042aa))
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.2 to ^0.0.3
## [0.0.5](https://github.com/muxinc/player.style/compare/@player.style/microvideo@0.0.4...@player.style/microvideo@0.0.5) (2024-06-17)
### Bug Fixes
* media theme types bug ([8dd42da](https://github.com/muxinc/player.style/commit/8dd42dab7f0536a49f2df5109f27c7285ad9ff48))
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.1 to ^0.0.2
## [0.0.4](https://github.com/muxinc/player.style/compare/@player.style/microvideo@0.0.3...@player.style/microvideo@0.0.4) (2024-06-17)
### Bug Fixes
* Changed Youtube theme name to YT ([#12](https://github.com/muxinc/player.style/issues/12)) ([e981669](https://github.com/muxinc/player.style/commit/e981669b170502e692eae355e904681b26b9552f))
## [0.0.3](https://github.com/muxinc/player.style/compare/@player.style/microvideo@0.0.2...@player.style/microvideo@0.0.3) (2024-06-14)
### Bug Fixes
* make subpackages publish-able ([f4208e8](https://github.com/muxinc/player.style/commit/f4208e89396241f64cce826a661bee9a6d45e76c))
## [0.0.2](https://github.com/muxinc/player.style/compare/@player.style/microvideo-v0.0.1...@player.style/microvideo@0.0.2) (2024-06-14)
### Features
* add collection, theme and about base pages ([8d96835](https://github.com/muxinc/player.style/commit/8d968357b5e1097fb75e925e6b0437da0df292b1))
* add packages restructure ([#2](https://github.com/muxinc/player.style/issues/2)) ([b23ddb0](https://github.com/muxinc/player.style/commit/b23ddb0fba3682b19b7d8e2912045ccbfbce6cb0))
* make theme work on entry page ([#1](https://github.com/muxinc/player.style/issues/1)) ([3f766ce](https://github.com/muxinc/player.style/commit/3f766ce271bbf6128e7fc8ef0475fa5c9eb895ae))
### Bug Fixes
* types and cleanup theme build ([#8](https://github.com/muxinc/player.style/issues/8)) ([21b9916](https://github.com/muxinc/player.style/commit/21b991621accfecba421f3cf1d2dbb0b98509d95))

View File

@@ -0,0 +1,13 @@
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
declare global {
interface HTMLElementTagNameMap {
'media-theme-microvideo': MediaThemeMicrovideoElement;
}
}
declare class MediaThemeMicrovideoElement extends MediaThemeElement {
static template: HTMLTemplateElement;
}
export default MediaThemeMicrovideoElement;

View File

@@ -0,0 +1,498 @@
<style>
:host {
--_primary-color: var(--media-primary-color, rgb(255 255 255 / .9));
--_secondary-color: var(--media-secondary-color, rgb(0 0 0 / .75));
--_volume-range-expand-width: 70px;
--_volume-range-expand-height: 42px;
--media-icon-color: var(--_primary-color);
--media-range-thumb-background: var(--_primary-color);
--media-range-bar-color: var(--_primary-color);
--media-range-thumb-opacity: 0;
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-control-padding: 5px 5px;
--media-preview-time-text-shadow: none;
--media-tooltip-display: none;
color: var(--_primary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
:host {
--_secondary-color: color-mix(in srgb, var(--media-secondary-color, #000) 75%, transparent);
}
}
[disabled]:not(media-live-button) {
opacity: 60%;
cursor: not-allowed;
}
[breakpointsm] {
--media-control-padding: 9px 5px;
}
[breakpointmd] {
--media-control-padding: 9px 7px;
}
media-time-range,
media-live-button,
media-time-display,
media-text-display,
media-playback-rate-button[role='button'] {
color: inherit;
}
media-controller::part(centered-layer) {
display: grid;
justify-content: unset;
padding-bottom: 6px;
}
:host([streamtype=live]:not([targetlivewindow])) media-controller::part(centered-layer),
:host([mediastreamtype=live]:not([mediatargetlivewindow])) media-controller::part(centered-layer) {
padding-bottom: 0;
}
media-loading-indicator {
place-self: center;
/* Stack the grid items on top of each other */
grid-area: 1 / 1;
}
media-control-bar {
place-self: var(--_control-bar-place-self, end center);
grid-area: 1 / 1;
position: relative;
margin: 10px;
gap: 4px;
align-items: start;
}
:host([controlbarplace$="end"]) media-control-bar {
align-items: end;
}
.control-group {
background: var(--_secondary-color);
position: relative;
display: inline-flex;
border-radius: 5px;
}
:host([controlbarvertical]) :is(media-control-bar, .control-group) {
flex-direction: column;
}
.volume-group {
position: relative;
display: inline-flex;
flex-direction: row;
}
:host([controlbarplace$="end"]) .volume-group {
flex-direction: row-reverse;
}
:host([controlbarplace$="end"]) .volume-group:first-child .volume-range-span {
--_volume-range-padding-left: 10px;
}
:host([controlbarvertical]) .volume-group {
flex-direction: column;
}
:host([controlbarvertical][controlbarplace^="end"]) .volume-group {
flex-direction: column-reverse;
}
:host([controlbarvertical][controlbarplace^="end"]) .volume-group:first-child .volume-range-span {
--_volume-range-padding-top: 10px;
}
.volume-range-span {
display: inline-flex;
position: relative;
overflow: hidden;
width: 0;
}
.volume-group:hover .volume-range-span,
[keyboardcontrol] .volume-group:focus-within .volume-range-span {
width: var(--_volume-range-expand-width);
padding-left: var(--_volume-range-padding-left);
padding-top: var(--_volume-range-padding-top);
}
:host([controlbarvertical]) .volume-range-span {
--_volume-range-padding-left: 0 !important;
display: inline-flex;
height: 0;
}
:host([controlbarvertical]) .volume-group:hover .volume-range-span,
:host([controlbarvertical]) [keyboardcontrol] .volume-group:focus-within .volume-range-span {
height: var(--_volume-range-expand-height);
width: auto;
max-width: 40px;
}
media-volume-range {
--media-range-track-border-radius: 2px;
--media-range-track-background: rgba(255, 255, 255, .2);
width: var(--_volume-range-expand-width);
display: var(--controls, var(--volume-range, inline-block));
border-radius: 5px;
}
:host([controlbarvertical]) media-volume-range {
width: var(--_volume-range-expand-height);
transform: rotate(-90deg);
}
media-control-bar:has(.volume-group:hover),
[keyboardcontrol] media-control-bar:has(.volume-group:focus-within) {
top: var(--_control-bar-offset-top, 0);
left: var(--_control-bar-offset-left, calc(var(--_volume-range-expand-width) / 2));
}
:host([controlbarplace$="start"]),
:host([controlbarplace$="end"]) {
--_control-bar-offset-left: 0;
}
:host([controlbarvertical]) {
--_control-bar-offset-left: 0;
}
:host([controlbarvertical][controlbarplace^="center"]) {
--_control-bar-offset-top: calc(var(--_volume-range-expand-height) / 2);
}
media-time-range {
--media-range-track-height: 6px;
--media-range-track-transition: height .1s linear;
--media-range-track-background: rgba(20, 20, 30, .25);
--media-time-range-buffered-color: rgba(20, 20, 30, .3);
--media-range-track-box-shadow: 0 -1px 0 rgba(20, 20, 30, .07);
--media-range-padding-left: 0;
--media-range-padding-right: 0;
--media-preview-time-background: var(--_secondary-color);
--media-preview-box-margin: 0 0 3px;
display: var(--controls, var(--time-range, inline-block));
width: 100%;
height: 10px;
bottom: -2px;
}
media-live-button {
--media-control-background: var(--_secondary-color);
--media-control-hover-background: var(--_secondary-color);
border-radius: 5px;
}
media-live-button::before {
content: '';
width: 5px;
}
media-live-button::after {
content: '';
width: 7px;
}
/* Turn some buttons off by default */
media-seek-backward-button {
display: var(--media-control-display, var(--media-seek-backward-button-display, none));
}
media-seek-forward-button {
display: var(--media-control-display, var(--media-seek-forward-button-display, none));
}
media-pip-button {
display: var(--media-control-display, var(--media-pip-button-display, none));
}
</style>
<template partial="PlayButton">
<media-play-button
part="play button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="play">
<path d="m6.73 20.93 14.05-8.54a.46.46 0 0 0 0-.78L6.73 3.07a.48.48 0 0 0-.73.39v17.07a.48.48 0 0 0 .73.4Z" />
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="pause">
<path
d="M6 19.5a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v15ZM14.5 4a.5.5 0 0 0-.5.5v15a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5h-3Z"
/>
</svg>
</media-play-button>
</template>
<template partial="SeekBackwardButton">
<media-seek-backward-button
seekoffset="{{backwardseekoffset ?? 10}}"
part="seek-backward button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 22 24" slot="icon">
<path d="M11 6V3L5.37 7 11 10.94V8a5.54 5.54 0 0 1 1.9 10.48v2.12A7.5 7.5 0 0 0 11 6Z" />
<text class="value" transform="translate(2.5 21)" style="font-size: 8px; font-family: 'ArialMT', 'Arial'">
{{backwardseekoffset ?? 10}}
</text>
</svg>
</media-seek-backward-button>
</template>
<template partial="SeekForwardButton">
<media-seek-forward-button
seekoffset="{{forwardseekoffset ?? 10}}"
part="seek-forward button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 22 24" slot="icon">
<path d="M11 6V3l5.61 4L11 10.94V8a5.54 5.54 0 0 0-1.9 10.48v2.12A7.5 7.5 0 0 1 11 6Z" />
<text class="value" transform="translate(10 21)" style="font-size: 8px; font-family: 'ArialMT', 'Arial'">
{{forwardseekoffset ?? 10}}
</text>
</svg>
</media-seek-forward-button>
</template>
<template partial="MuteButton">
<media-mute-button part="mute button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 24 24" slot="high">
<path
d="m11.14 4.86-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.21a.5.5 0 0 0-.86-.35Zm2.74-1.56v1.52A7.52 7.52 0 0 1 19.47 12a7.52 7.52 0 0 1-5.59 7.18v1.52A9 9 0 0 0 21 12a9 9 0 0 0-7.12-8.7Zm3.56 8.7a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="medium">
<path
d="m11.14 4.853-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.203a.5.5 0 0 0-.86-.35Zm6.3 7.14a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="low">
<path
d="m11.14 4.853-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.203a.5.5 0 0 0-.86-.35Zm6.3 7.14a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="off">
<path
d="m3 4.05 4.48 4.47-.33.33a.49.49 0 0 1-.36.15H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.48.48 0 0 0 .36.15.5.5 0 0 0 .5-.5v-5.75l4.67 4.66a7.71 7.71 0 0 1-2.79 1.47v1.52a9.32 9.32 0 0 0 3.87-1.91L20 21l1-1L4.06 3 3 4.05Zm5.36 5.36 2.39 2.39V17L8 14.26a1.74 1.74 0 0 0-1.24-.51H4.25v-3.5h2.54A1.74 1.74 0 0 0 8 9.74l.36-.33ZM19.47 12a7.19 7.19 0 0 1-.89 3.47l1.11 1.1A8.64 8.64 0 0 0 21 12a9 9 0 0 0-7.12-8.7v1.52A7.52 7.52 0 0 1 19.47 12ZM12 8.88V5.21a.5.5 0 0 0-.5-.5.48.48 0 0 0-.36.15L9.56 6.44 12 8.88ZM15.91 12a4.284 4.284 0 0 1-.07.72l1.22 1.22a5.2 5.2 0 0 0 .38-1.94 5.49 5.49 0 0 0-3.56-5.1v1.66A4 4 0 0 1 15.91 12Z"
/>
</svg>
</media-mute-button>
</template>
<template partial="CaptionsButton">
<media-captions-button
part="captions button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="on">
<path
d="M22.832 5.68a2.58 2.58 0 0 0-2.3-2.5c-3.62-.24-11.44-.24-15.06 0a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c3.62.24 11.44.24 15.06 0a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-11.41 10.1a3.63 3.63 0 0 1-1.51.32 4.76 4.76 0 0 1-1.63-.27 4 4 0 0 1-1.28-.83 3.67 3.67 0 0 1-.84-1.26 4.23 4.23 0 0 1-.3-1.63 4.28 4.28 0 0 1 .3-1.64 3.53 3.53 0 0 1 .84-1.21 3.89 3.89 0 0 1 1.29-.8 4.76 4.76 0 0 1 1.63-.27 4.06 4.06 0 0 1 1.35.24c.225.091.44.205.64.34a2.7 2.7 0 0 1 .55.52l-1.27 1a1.79 1.79 0 0 0-.6-.46 2 2 0 0 0-.83-.16 2 2 0 0 0-1.56.69 2.35 2.35 0 0 0-.46.77 2.78 2.78 0 0 0-.16 1c-.009.34.046.68.16 1 .104.283.26.545.46.77.188.21.415.38.67.5a2 2 0 0 0 .84.18 1.87 1.87 0 0 0 .9-.21 1.78 1.78 0 0 0 .65-.6l1.38 1a2.88 2.88 0 0 1-1.22 1.01Zm7.52 0a3.63 3.63 0 0 1-1.51.32 4.76 4.76 0 0 1-1.63-.27 3.89 3.89 0 0 1-1.28-.83 3.55 3.55 0 0 1-.85-1.26 4.23 4.23 0 0 1-.3-1.63 4.28 4.28 0 0 1 .3-1.64 3.43 3.43 0 0 1 .85-1.25 3.75 3.75 0 0 1 1.28-.8 4.76 4.76 0 0 1 1.63-.27 4 4 0 0 1 1.35.24c.225.091.44.205.64.34.21.144.395.32.55.52l-1.27 1a1.79 1.79 0 0 0-.6-.46 2 2 0 0 0-.83-.16 2 2 0 0 0-1.56.69 2.352 2.352 0 0 0-.46.77 3.01 3.01 0 0 0-.16 1c-.003.34.05.678.16 1 .108.282.263.542.46.77.188.21.416.38.67.5a2 2 0 0 0 .84.18 1.87 1.87 0 0 0 .9-.21 1.78 1.78 0 0 0 .65-.6l1.38 1a2.82 2.82 0 0 1-1.21 1.05Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="off">
<path
d="M22.832 5.68a2.58 2.58 0 0 0-2.3-2.5c-1.81-.12-4.67-.18-7.53-.18-2.86 0-5.72.06-7.53.18a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c1.81.12 4.67.18 7.53.18 2.86 0 5.72-.06 7.53-.18a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-1.49 12.53a1.11 1.11 0 0 1-.91 1.11c-1.67.11-4.45.18-7.43.18-2.98 0-5.76-.07-7.43-.18a1.11 1.11 0 0 1-.91-1.11c-.21-4.137-.21-8.283 0-12.42a1.11 1.11 0 0 1 .91-1.11c1.67-.11 4.43-.18 7.43-.18s5.76.07 7.43.18a1.11 1.11 0 0 1 .91 1.11c.21 4.137.21 8.283 0 12.42ZM10.843 14a1.55 1.55 0 0 1-.76.18 1.57 1.57 0 0 1-.71-.18 1.69 1.69 0 0 1-.57-.42 2.099 2.099 0 0 1-.38-.58 2.47 2.47 0 0 1 0-1.64 2 2 0 0 1 .39-.66 1.73 1.73 0 0 1 .58-.42c.23-.103.479-.158.73-.16.241-.004.48.044.7.14.199.088.373.222.51.39l1.08-.89a2.179 2.179 0 0 0-.47-.44 2.81 2.81 0 0 0-.54-.32 2.91 2.91 0 0 0-.58-.15 2.71 2.71 0 0 0-.56 0 4.08 4.08 0 0 0-1.38.15 3.27 3.27 0 0 0-1.09.67 3.14 3.14 0 0 0-.71 1.06 3.62 3.62 0 0 0-.26 1.39 3.57 3.57 0 0 0 .26 1.38 3 3 0 0 0 .71 1.06c.316.293.687.52 1.09.67.443.16.91.238 1.38.23a3.2 3.2 0 0 0 1.28-.27c.401-.183.747-.47 1-.83l-1.17-.88a1.42 1.42 0 0 1-.53.52Zm6.62 0a1.58 1.58 0 0 1-.76.18 1.54 1.54 0 0 1-.7-.18 1.69 1.69 0 0 1-.57-.42 2.12 2.12 0 0 1-.43-.58 2.29 2.29 0 0 1 .39-2.3 1.84 1.84 0 0 1 1.32-.58c.241-.003.48.045.7.14.199.088.373.222.51.39l1.08-.92a2.43 2.43 0 0 0-.47-.44 3.22 3.22 0 0 0-.53-.29 2.999 2.999 0 0 0-.57-.15 2.87 2.87 0 0 0-.57 0 4.06 4.06 0 0 0-1.36.15 3.17 3.17 0 0 0-1.09.67 3 3 0 0 0-.72 1.06 3.62 3.62 0 0 0-.25 1.39 3.57 3.57 0 0 0 .25 1.38c.16.402.405.764.72 1.06a3.17 3.17 0 0 0 1.09.67c.44.16.904.237 1.37.23.441 0 .877-.092 1.28-.27a2.45 2.45 0 0 0 1-.83l-1.15-.85a1.49 1.49 0 0 1-.54.49Z"
/>
</svg>
</media-captions-button>
</template>
<template partial="PipButton">
<media-pip-button part="pip button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="enter">
<path
d="M22 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h6.75v-1.25h-6.5V4.25h17.5v6.5H23V4a1 1 0 0 0-1-1Zm0 10h-8a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1Zm-.5 6.5h-7v-5h7v5Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="exit">
<path
d="M22 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h6.75v-1.25h-6.5V4.25h17.5v6.5H23V4a1 1 0 0 0-1-1Zm0 10h-8a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1Zm-.5 6.5h-7v-5h7v5Z"
/>
</svg>
</media-pip-button>
</template>
<template partial="AirplayButton">
<media-airplay-button part="airplay button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="icon">
<path
d="M13.19 14.22a.25.25 0 0 0-.38 0l-5.46 6.37a.25.25 0 0 0 .19.41h10.92a.25.25 0 0 0 .19-.41l-5.46-6.37Z"
/>
<path
d="M22 3H4a1 1 0 0 0-1 1v13a1 1 0 0 0 1 1h2.94L8 16.75H4.25V4.25h17.5v12.5H18L19.06 18H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
</svg>
</media-airplay-button>
</template>
<template partial="CastButton">
<media-cast-button part="cast button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="enter">
<path d="M3 15.5V17c2.206 0 4 1.794 4 4h1.5A5.5 5.5 0 0 0 3 15.5Zm0 3V21h2.5A2.5 2.5 0 0 0 3 18.5Z" />
<path d="M3 12.5V14c3.86 0 7 3.14 7 7h1.5A8.5 8.5 0 0 0 3 12.5Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v6.984c.424 0 .84.035 1.25.086V4.25h17.5v15.5h-8.82c.051.41.086.826.086 1.25H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="exit">
<path d="M3 15.5V17c2.206 0 4 1.794 4 4h1.5A5.5 5.5 0 0 0 3 15.5Zm0 3V21h2.5A2.5 2.5 0 0 0 3 18.5Z" />
<path d="M3 12.5V14c3.86 0 7 3.14 7 7h1.5A8.5 8.5 0 0 0 3 12.5Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v6.984c.424 0 .84.035 1.25.086V4.25h17.5v15.5h-8.82c.051.41.086.826.086 1.25H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
<path d="M20.5 5.5h-15v5.811c3.52.906 6.283 3.67 7.189 7.19H20.5V5.5Z" />
</svg>
</media-cast-button>
</template>
<template partial="FullscreenButton">
<media-fullscreen-button
part="fullscreen button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="enter">
<path
d="M20.25 14.5a.76.76 0 0 0-.75.75v4.25h-4.25a.75.75 0 1 0 0 1.5h5a.76.76 0 0 0 .75-.75v-5a.76.76 0 0 0-.75-.75Zm0-11.5h-5a.76.76 0 0 0-.75.75.76.76 0 0 0 .75.75h4.25v4.25a.75.75 0 1 0 1.5 0v-5a.76.76 0 0 0-.75-.75ZM8.75 19.5H4.5v-4.25a.76.76 0 0 0-.75-.75.76.76 0 0 0-.75.75v5a.76.76 0 0 0 .75.75h5a.75.75 0 1 0 0-1.5Zm0-16.5h-5a.76.76 0 0 0-.75.75v5a.76.76 0 0 0 .75.75.76.76 0 0 0 .75-.75V4.5h4.25a.76.76 0 0 0 .75-.75.76.76 0 0 0-.75-.75Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="exit">
<path
d="M20.25 14.5h-5a.76.76 0 0 0-.75.75v5a.75.75 0 1 0 1.5 0V16h4.25a.75.75 0 1 0 0-1.5Zm-5-5h5a.75.75 0 1 0 0-1.5H16V3.75a.75.75 0 1 0-1.5 0v5a.76.76 0 0 0 .75.75Zm-6.5 5h-5a.75.75 0 1 0 0 1.5H8v4.25a.75.75 0 1 0 1.5 0v-5a.76.76 0 0 0-.75-.75Zm0-11.5a.76.76 0 0 0-.75.75V8H3.75a.75.75 0 0 0 0 1.5h5a.76.76 0 0 0 .75-.75v-5A.76.76 0 0 0 8.75 3Z"
/>
</svg>
</media-fullscreen-button>
</template>
<template partial="LiveButton">
<media-live-button
part="live seek-live button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<span slot="text">Live</span>
</media-live-button>
</template>
<template partial="TimeRange">
<media-time-range
part="time range"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
></media-time-range>
</template>
<template partial="VolumeRange">
<span class="volume-range-span">
<media-volume-range
part="volume range"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
></media-volume-range>
</span>
</template>
<!--
controlbarplace targets the place-self CSS property of the controlbar.
e.g. controlbarplace="center center" will center the controlbar.
-->
<media-controller
style="--_control-bar-place-self:{{controlbarplace ?? 'unset'}}"
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<media-loading-indicator slot="centered-chrome" noautohide></media-loading-indicator>
<template if="streamtype == 'on-demand'">
<media-control-bar slot="centered-chrome">
<div class="control-group">
{{>PlayButton}}
{{>SeekBackwardButton}}
{{>SeekForwardButton}}
<span class="volume-group">
{{>MuteButton}}
{{>VolumeRange}}
</span>
{{>CaptionsButton}}
{{>AirplayButton}}
{{>CastButton}}
{{>PipButton}}
{{>FullscreenButton}}
</div>
</media-control-bar>
{{>TimeRange}}
</template>
<template if="streamtype == 'live'">
<template if="!targetlivewindow">
<media-control-bar slot="centered-chrome">
{{>LiveButton}}
<div class="control-group">
<span class="volume-group">
{{>MuteButton}}
{{>VolumeRange}}
</span>
{{>CaptionsButton}}
{{>AirplayButton}}
{{>CastButton}}
{{>PipButton}}
{{>FullscreenButton}}
</div>
</media-control-bar>
</template>
<template if="targetlivewindow > 0">
<media-control-bar slot="centered-chrome">
{{>LiveButton}}
<div class="control-group">
{{>PlayButton}}
{{>SeekBackwardButton}}
{{>SeekForwardButton}}
<span class="volume-group">
{{>MuteButton}}
{{>VolumeRange}}
</span>
{{>CaptionsButton}}
{{>AirplayButton}}
{{>CastButton}}
{{>PipButton}}
{{>FullscreenButton}}
</div>
</media-control-bar>
{{>TimeRange}}
</template>
</template>
<slot></slot>
</media-controller>

View File

@@ -0,0 +1,528 @@
/*
<media-theme-microvideo>
<video
slot="media"
src="https://stream.mux.com/fXNzVtmtWuyz00xnSrJg4OJH6PyNo6D02UzmgeKGkP5YQ/high.mp4"
></video>
</media-theme-microvideo>
*/
import 'media-chrome';
import { globalThis } from 'media-chrome/dist/utils/server-safe-globals.js';
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
import 'media-chrome/dist/menu/index.js';
const template = globalThis.document?.createElement?.('template');
if (template) {
template.innerHTML = /*html*/`
<style>
:host {
--_primary-color: var(--media-primary-color, rgb(255 255 255 / .9));
--_secondary-color: var(--media-secondary-color, rgb(0 0 0 / .75));
--_volume-range-expand-width: 70px;
--_volume-range-expand-height: 42px;
--media-icon-color: var(--_primary-color);
--media-range-thumb-background: var(--_primary-color);
--media-range-bar-color: var(--_primary-color);
--media-range-thumb-opacity: 0;
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-control-padding: 5px 5px;
--media-preview-time-text-shadow: none;
--media-tooltip-display: none;
color: var(--_primary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
:host {
--_secondary-color: color-mix(in srgb, var(--media-secondary-color, #000) 75%, transparent);
}
}
[disabled]:not(media-live-button) {
opacity: 60%;
cursor: not-allowed;
}
[breakpointsm] {
--media-control-padding: 9px 5px;
}
[breakpointmd] {
--media-control-padding: 9px 7px;
}
media-time-range,
media-live-button,
media-time-display,
media-text-display,
media-playback-rate-button[role='button'] {
color: inherit;
}
media-controller::part(centered-layer) {
display: grid;
justify-content: unset;
padding-bottom: 6px;
}
:host([streamtype=live]:not([targetlivewindow])) media-controller::part(centered-layer),
:host([mediastreamtype=live]:not([mediatargetlivewindow])) media-controller::part(centered-layer) {
padding-bottom: 0;
}
media-loading-indicator {
place-self: center;
/* Stack the grid items on top of each other */
grid-area: 1 / 1;
}
media-control-bar {
place-self: var(--_control-bar-place-self, end center);
grid-area: 1 / 1;
position: relative;
margin: 10px;
gap: 4px;
align-items: start;
}
:host([controlbarplace$="end"]) media-control-bar {
align-items: end;
}
.control-group {
background: var(--_secondary-color);
position: relative;
display: inline-flex;
border-radius: 5px;
}
:host([controlbarvertical]) :is(media-control-bar, .control-group) {
flex-direction: column;
}
.volume-group {
position: relative;
display: inline-flex;
flex-direction: row;
}
:host([controlbarplace$="end"]) .volume-group {
flex-direction: row-reverse;
}
:host([controlbarplace$="end"]) .volume-group:first-child .volume-range-span {
--_volume-range-padding-left: 10px;
}
:host([controlbarvertical]) .volume-group {
flex-direction: column;
}
:host([controlbarvertical][controlbarplace^="end"]) .volume-group {
flex-direction: column-reverse;
}
:host([controlbarvertical][controlbarplace^="end"]) .volume-group:first-child .volume-range-span {
--_volume-range-padding-top: 10px;
}
.volume-range-span {
display: inline-flex;
position: relative;
overflow: hidden;
width: 0;
}
.volume-group:hover .volume-range-span,
[keyboardcontrol] .volume-group:focus-within .volume-range-span {
width: var(--_volume-range-expand-width);
padding-left: var(--_volume-range-padding-left);
padding-top: var(--_volume-range-padding-top);
}
:host([controlbarvertical]) .volume-range-span {
--_volume-range-padding-left: 0 !important;
display: inline-flex;
height: 0;
}
:host([controlbarvertical]) .volume-group:hover .volume-range-span,
:host([controlbarvertical]) [keyboardcontrol] .volume-group:focus-within .volume-range-span {
height: var(--_volume-range-expand-height);
width: auto;
max-width: 40px;
}
media-volume-range {
--media-range-track-border-radius: 2px;
--media-range-track-background: rgba(255, 255, 255, .2);
width: var(--_volume-range-expand-width);
display: var(--controls, var(--volume-range, inline-block));
border-radius: 5px;
}
:host([controlbarvertical]) media-volume-range {
width: var(--_volume-range-expand-height);
transform: rotate(-90deg);
}
media-control-bar:has(.volume-group:hover),
[keyboardcontrol] media-control-bar:has(.volume-group:focus-within) {
top: var(--_control-bar-offset-top, 0);
left: var(--_control-bar-offset-left, calc(var(--_volume-range-expand-width) / 2));
}
:host([controlbarplace$="start"]),
:host([controlbarplace$="end"]) {
--_control-bar-offset-left: 0;
}
:host([controlbarvertical]) {
--_control-bar-offset-left: 0;
}
:host([controlbarvertical][controlbarplace^="center"]) {
--_control-bar-offset-top: calc(var(--_volume-range-expand-height) / 2);
}
media-time-range {
--media-range-track-height: 6px;
--media-range-track-transition: height .1s linear;
--media-range-track-background: rgba(20, 20, 30, .25);
--media-time-range-buffered-color: rgba(20, 20, 30, .3);
--media-range-track-box-shadow: 0 -1px 0 rgba(20, 20, 30, .07);
--media-range-padding-left: 0;
--media-range-padding-right: 0;
--media-preview-time-background: var(--_secondary-color);
--media-preview-box-margin: 0 0 3px;
display: var(--controls, var(--time-range, inline-block));
width: 100%;
height: 10px;
bottom: -2px;
}
media-live-button {
--media-control-background: var(--_secondary-color);
--media-control-hover-background: var(--_secondary-color);
border-radius: 5px;
}
media-live-button::before {
content: '';
width: 5px;
}
media-live-button::after {
content: '';
width: 7px;
}
/* Turn some buttons off by default */
media-seek-backward-button {
display: var(--media-control-display, var(--media-seek-backward-button-display, none));
}
media-seek-forward-button {
display: var(--media-control-display, var(--media-seek-forward-button-display, none));
}
media-pip-button {
display: var(--media-control-display, var(--media-pip-button-display, none));
}
</style>
<template partial="PlayButton">
<media-play-button
part="play button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="play">
<path d="m6.73 20.93 14.05-8.54a.46.46 0 0 0 0-.78L6.73 3.07a.48.48 0 0 0-.73.39v17.07a.48.48 0 0 0 .73.4Z" />
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="pause">
<path
d="M6 19.5a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v15ZM14.5 4a.5.5 0 0 0-.5.5v15a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5h-3Z"
/>
</svg>
</media-play-button>
</template>
<template partial="SeekBackwardButton">
<media-seek-backward-button
seekoffset="{{backwardseekoffset ?? 10}}"
part="seek-backward button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 22 24" slot="icon">
<path d="M11 6V3L5.37 7 11 10.94V8a5.54 5.54 0 0 1 1.9 10.48v2.12A7.5 7.5 0 0 0 11 6Z" />
<text class="value" transform="translate(2.5 21)" style="font-size: 8px; font-family: 'ArialMT', 'Arial'">
{{backwardseekoffset ?? 10}}
</text>
</svg>
</media-seek-backward-button>
</template>
<template partial="SeekForwardButton">
<media-seek-forward-button
seekoffset="{{forwardseekoffset ?? 10}}"
part="seek-forward button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 22 24" slot="icon">
<path d="M11 6V3l5.61 4L11 10.94V8a5.54 5.54 0 0 0-1.9 10.48v2.12A7.5 7.5 0 0 1 11 6Z" />
<text class="value" transform="translate(10 21)" style="font-size: 8px; font-family: 'ArialMT', 'Arial'">
{{forwardseekoffset ?? 10}}
</text>
</svg>
</media-seek-forward-button>
</template>
<template partial="MuteButton">
<media-mute-button part="mute button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 24 24" slot="high">
<path
d="m11.14 4.86-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.21a.5.5 0 0 0-.86-.35Zm2.74-1.56v1.52A7.52 7.52 0 0 1 19.47 12a7.52 7.52 0 0 1-5.59 7.18v1.52A9 9 0 0 0 21 12a9 9 0 0 0-7.12-8.7Zm3.56 8.7a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="medium">
<path
d="m11.14 4.853-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.203a.5.5 0 0 0-.86-.35Zm6.3 7.14a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="low">
<path
d="m11.14 4.853-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.203a.5.5 0 0 0-.86-.35Zm6.3 7.14a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="off">
<path
d="m3 4.05 4.48 4.47-.33.33a.49.49 0 0 1-.36.15H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.48.48 0 0 0 .36.15.5.5 0 0 0 .5-.5v-5.75l4.67 4.66a7.71 7.71 0 0 1-2.79 1.47v1.52a9.32 9.32 0 0 0 3.87-1.91L20 21l1-1L4.06 3 3 4.05Zm5.36 5.36 2.39 2.39V17L8 14.26a1.74 1.74 0 0 0-1.24-.51H4.25v-3.5h2.54A1.74 1.74 0 0 0 8 9.74l.36-.33ZM19.47 12a7.19 7.19 0 0 1-.89 3.47l1.11 1.1A8.64 8.64 0 0 0 21 12a9 9 0 0 0-7.12-8.7v1.52A7.52 7.52 0 0 1 19.47 12ZM12 8.88V5.21a.5.5 0 0 0-.5-.5.48.48 0 0 0-.36.15L9.56 6.44 12 8.88ZM15.91 12a4.284 4.284 0 0 1-.07.72l1.22 1.22a5.2 5.2 0 0 0 .38-1.94 5.49 5.49 0 0 0-3.56-5.1v1.66A4 4 0 0 1 15.91 12Z"
/>
</svg>
</media-mute-button>
</template>
<template partial="CaptionsButton">
<media-captions-button
part="captions button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="on">
<path
d="M22.832 5.68a2.58 2.58 0 0 0-2.3-2.5c-3.62-.24-11.44-.24-15.06 0a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c3.62.24 11.44.24 15.06 0a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-11.41 10.1a3.63 3.63 0 0 1-1.51.32 4.76 4.76 0 0 1-1.63-.27 4 4 0 0 1-1.28-.83 3.67 3.67 0 0 1-.84-1.26 4.23 4.23 0 0 1-.3-1.63 4.28 4.28 0 0 1 .3-1.64 3.53 3.53 0 0 1 .84-1.21 3.89 3.89 0 0 1 1.29-.8 4.76 4.76 0 0 1 1.63-.27 4.06 4.06 0 0 1 1.35.24c.225.091.44.205.64.34a2.7 2.7 0 0 1 .55.52l-1.27 1a1.79 1.79 0 0 0-.6-.46 2 2 0 0 0-.83-.16 2 2 0 0 0-1.56.69 2.35 2.35 0 0 0-.46.77 2.78 2.78 0 0 0-.16 1c-.009.34.046.68.16 1 .104.283.26.545.46.77.188.21.415.38.67.5a2 2 0 0 0 .84.18 1.87 1.87 0 0 0 .9-.21 1.78 1.78 0 0 0 .65-.6l1.38 1a2.88 2.88 0 0 1-1.22 1.01Zm7.52 0a3.63 3.63 0 0 1-1.51.32 4.76 4.76 0 0 1-1.63-.27 3.89 3.89 0 0 1-1.28-.83 3.55 3.55 0 0 1-.85-1.26 4.23 4.23 0 0 1-.3-1.63 4.28 4.28 0 0 1 .3-1.64 3.43 3.43 0 0 1 .85-1.25 3.75 3.75 0 0 1 1.28-.8 4.76 4.76 0 0 1 1.63-.27 4 4 0 0 1 1.35.24c.225.091.44.205.64.34.21.144.395.32.55.52l-1.27 1a1.79 1.79 0 0 0-.6-.46 2 2 0 0 0-.83-.16 2 2 0 0 0-1.56.69 2.352 2.352 0 0 0-.46.77 3.01 3.01 0 0 0-.16 1c-.003.34.05.678.16 1 .108.282.263.542.46.77.188.21.416.38.67.5a2 2 0 0 0 .84.18 1.87 1.87 0 0 0 .9-.21 1.78 1.78 0 0 0 .65-.6l1.38 1a2.82 2.82 0 0 1-1.21 1.05Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="off">
<path
d="M22.832 5.68a2.58 2.58 0 0 0-2.3-2.5c-1.81-.12-4.67-.18-7.53-.18-2.86 0-5.72.06-7.53.18a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c1.81.12 4.67.18 7.53.18 2.86 0 5.72-.06 7.53-.18a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-1.49 12.53a1.11 1.11 0 0 1-.91 1.11c-1.67.11-4.45.18-7.43.18-2.98 0-5.76-.07-7.43-.18a1.11 1.11 0 0 1-.91-1.11c-.21-4.137-.21-8.283 0-12.42a1.11 1.11 0 0 1 .91-1.11c1.67-.11 4.43-.18 7.43-.18s5.76.07 7.43.18a1.11 1.11 0 0 1 .91 1.11c.21 4.137.21 8.283 0 12.42ZM10.843 14a1.55 1.55 0 0 1-.76.18 1.57 1.57 0 0 1-.71-.18 1.69 1.69 0 0 1-.57-.42 2.099 2.099 0 0 1-.38-.58 2.47 2.47 0 0 1 0-1.64 2 2 0 0 1 .39-.66 1.73 1.73 0 0 1 .58-.42c.23-.103.479-.158.73-.16.241-.004.48.044.7.14.199.088.373.222.51.39l1.08-.89a2.179 2.179 0 0 0-.47-.44 2.81 2.81 0 0 0-.54-.32 2.91 2.91 0 0 0-.58-.15 2.71 2.71 0 0 0-.56 0 4.08 4.08 0 0 0-1.38.15 3.27 3.27 0 0 0-1.09.67 3.14 3.14 0 0 0-.71 1.06 3.62 3.62 0 0 0-.26 1.39 3.57 3.57 0 0 0 .26 1.38 3 3 0 0 0 .71 1.06c.316.293.687.52 1.09.67.443.16.91.238 1.38.23a3.2 3.2 0 0 0 1.28-.27c.401-.183.747-.47 1-.83l-1.17-.88a1.42 1.42 0 0 1-.53.52Zm6.62 0a1.58 1.58 0 0 1-.76.18 1.54 1.54 0 0 1-.7-.18 1.69 1.69 0 0 1-.57-.42 2.12 2.12 0 0 1-.43-.58 2.29 2.29 0 0 1 .39-2.3 1.84 1.84 0 0 1 1.32-.58c.241-.003.48.045.7.14.199.088.373.222.51.39l1.08-.92a2.43 2.43 0 0 0-.47-.44 3.22 3.22 0 0 0-.53-.29 2.999 2.999 0 0 0-.57-.15 2.87 2.87 0 0 0-.57 0 4.06 4.06 0 0 0-1.36.15 3.17 3.17 0 0 0-1.09.67 3 3 0 0 0-.72 1.06 3.62 3.62 0 0 0-.25 1.39 3.57 3.57 0 0 0 .25 1.38c.16.402.405.764.72 1.06a3.17 3.17 0 0 0 1.09.67c.44.16.904.237 1.37.23.441 0 .877-.092 1.28-.27a2.45 2.45 0 0 0 1-.83l-1.15-.85a1.49 1.49 0 0 1-.54.49Z"
/>
</svg>
</media-captions-button>
</template>
<template partial="PipButton">
<media-pip-button part="pip button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="enter">
<path
d="M22 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h6.75v-1.25h-6.5V4.25h17.5v6.5H23V4a1 1 0 0 0-1-1Zm0 10h-8a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1Zm-.5 6.5h-7v-5h7v5Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="exit">
<path
d="M22 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h6.75v-1.25h-6.5V4.25h17.5v6.5H23V4a1 1 0 0 0-1-1Zm0 10h-8a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1Zm-.5 6.5h-7v-5h7v5Z"
/>
</svg>
</media-pip-button>
</template>
<template partial="AirplayButton">
<media-airplay-button part="airplay button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="icon">
<path
d="M13.19 14.22a.25.25 0 0 0-.38 0l-5.46 6.37a.25.25 0 0 0 .19.41h10.92a.25.25 0 0 0 .19-.41l-5.46-6.37Z"
/>
<path
d="M22 3H4a1 1 0 0 0-1 1v13a1 1 0 0 0 1 1h2.94L8 16.75H4.25V4.25h17.5v12.5H18L19.06 18H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
</svg>
</media-airplay-button>
</template>
<template partial="CastButton">
<media-cast-button part="cast button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="enter">
<path d="M3 15.5V17c2.206 0 4 1.794 4 4h1.5A5.5 5.5 0 0 0 3 15.5Zm0 3V21h2.5A2.5 2.5 0 0 0 3 18.5Z" />
<path d="M3 12.5V14c3.86 0 7 3.14 7 7h1.5A8.5 8.5 0 0 0 3 12.5Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v6.984c.424 0 .84.035 1.25.086V4.25h17.5v15.5h-8.82c.051.41.086.826.086 1.25H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="exit">
<path d="M3 15.5V17c2.206 0 4 1.794 4 4h1.5A5.5 5.5 0 0 0 3 15.5Zm0 3V21h2.5A2.5 2.5 0 0 0 3 18.5Z" />
<path d="M3 12.5V14c3.86 0 7 3.14 7 7h1.5A8.5 8.5 0 0 0 3 12.5Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v6.984c.424 0 .84.035 1.25.086V4.25h17.5v15.5h-8.82c.051.41.086.826.086 1.25H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
<path d="M20.5 5.5h-15v5.811c3.52.906 6.283 3.67 7.189 7.19H20.5V5.5Z" />
</svg>
</media-cast-button>
</template>
<template partial="FullscreenButton">
<media-fullscreen-button
part="fullscreen button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="enter">
<path
d="M20.25 14.5a.76.76 0 0 0-.75.75v4.25h-4.25a.75.75 0 1 0 0 1.5h5a.76.76 0 0 0 .75-.75v-5a.76.76 0 0 0-.75-.75Zm0-11.5h-5a.76.76 0 0 0-.75.75.76.76 0 0 0 .75.75h4.25v4.25a.75.75 0 1 0 1.5 0v-5a.76.76 0 0 0-.75-.75ZM8.75 19.5H4.5v-4.25a.76.76 0 0 0-.75-.75.76.76 0 0 0-.75.75v5a.76.76 0 0 0 .75.75h5a.75.75 0 1 0 0-1.5Zm0-16.5h-5a.76.76 0 0 0-.75.75v5a.76.76 0 0 0 .75.75.76.76 0 0 0 .75-.75V4.5h4.25a.76.76 0 0 0 .75-.75.76.76 0 0 0-.75-.75Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="exit">
<path
d="M20.25 14.5h-5a.76.76 0 0 0-.75.75v5a.75.75 0 1 0 1.5 0V16h4.25a.75.75 0 1 0 0-1.5Zm-5-5h5a.75.75 0 1 0 0-1.5H16V3.75a.75.75 0 1 0-1.5 0v5a.76.76 0 0 0 .75.75Zm-6.5 5h-5a.75.75 0 1 0 0 1.5H8v4.25a.75.75 0 1 0 1.5 0v-5a.76.76 0 0 0-.75-.75Zm0-11.5a.76.76 0 0 0-.75.75V8H3.75a.75.75 0 0 0 0 1.5h5a.76.76 0 0 0 .75-.75v-5A.76.76 0 0 0 8.75 3Z"
/>
</svg>
</media-fullscreen-button>
</template>
<template partial="LiveButton">
<media-live-button
part="live seek-live button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<span slot="text">Live</span>
</media-live-button>
</template>
<template partial="TimeRange">
<media-time-range
part="time range"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
></media-time-range>
</template>
<template partial="VolumeRange">
<span class="volume-range-span">
<media-volume-range
part="volume range"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
></media-volume-range>
</span>
</template>
<!--
controlbarplace targets the place-self CSS property of the controlbar.
e.g. controlbarplace="center center" will center the controlbar.
-->
<media-controller
style="--_control-bar-place-self:{{controlbarplace ?? 'unset'}}"
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<media-loading-indicator slot="centered-chrome" noautohide></media-loading-indicator>
<template if="streamtype == 'on-demand'">
<media-control-bar slot="centered-chrome">
<div class="control-group">
{{>PlayButton}}
{{>SeekBackwardButton}}
{{>SeekForwardButton}}
<span class="volume-group">
{{>MuteButton}}
{{>VolumeRange}}
</span>
{{>CaptionsButton}}
{{>AirplayButton}}
{{>CastButton}}
{{>PipButton}}
{{>FullscreenButton}}
</div>
</media-control-bar>
{{>TimeRange}}
</template>
<template if="streamtype == 'live'">
<template if="!targetlivewindow">
<media-control-bar slot="centered-chrome">
{{>LiveButton}}
<div class="control-group">
<span class="volume-group">
{{>MuteButton}}
{{>VolumeRange}}
</span>
{{>CaptionsButton}}
{{>AirplayButton}}
{{>CastButton}}
{{>PipButton}}
{{>FullscreenButton}}
</div>
</media-control-bar>
</template>
<template if="targetlivewindow > 0">
<media-control-bar slot="centered-chrome">
{{>LiveButton}}
<div class="control-group">
{{>PlayButton}}
{{>SeekBackwardButton}}
{{>SeekForwardButton}}
<span class="volume-group">
{{>MuteButton}}
{{>VolumeRange}}
</span>
{{>CaptionsButton}}
{{>AirplayButton}}
{{>CastButton}}
{{>PipButton}}
{{>FullscreenButton}}
</div>
</media-control-bar>
{{>TimeRange}}
</template>
</template>
<slot></slot>
</media-controller>
`;
}
class MediaThemeMicrovideoElement extends MediaThemeElement {
static template = template;
}
if (globalThis.customElements && !globalThis.customElements.get('media-theme-microvideo')) {
globalThis.customElements.define('media-theme-microvideo', MediaThemeMicrovideoElement);
}
export default MediaThemeMicrovideoElement;

View File

@@ -0,0 +1,7 @@
import MediaThemeMicrovideoElement from './media-theme.js';
declare const MediaThemeMicrovideo: React.ForwardRefExoticComponent<
React.DetailedHTMLProps<React.HTMLAttributes<MediaThemeMicrovideoElement>, MediaThemeMicrovideoElement>
>;
export default MediaThemeMicrovideo;

View File

@@ -0,0 +1,94 @@
'use client';
import React from 'react';
import Element from './media-theme.js';
export default React.forwardRef((allProps, ref) => {
let { children, suppressHydrationWarning, ...props } = allProps;
const elementRef = React.useRef(null);
for (let name in props) {
if (name[0] === 'o' && name[1] === 'n') {
const useCapture = name.endsWith('Capture');
const eventName = name.slice(2, useCapture ? name.length - 7 : undefined).toLowerCase();
const callback = props[name];
React.useEffect(() => {
const eventTarget = elementRef?.current;
if (!eventTarget || typeof callback !== 'function') return;
eventTarget.addEventListener(eventName, callback, useCapture);
return () => {
eventTarget.removeEventListener(eventName, callback, useCapture);
};
}, [elementRef?.current, callback]);
}
}
const attrs = propsToAttrs(props);
// Only render the custom element template HTML on the server..
// The custom element will render itself on the client.
if (typeof window === 'undefined' && Element?.getTemplateHTML && Element?.shadowRootOptions) {
const { mode, delegatesFocus } = Element.shadowRootOptions;
const templateShadowRoot = React.createElement('template', {
shadowrootmode: mode,
shadowrootdelegatesfocus: delegatesFocus,
dangerouslySetInnerHTML: {
__html: Element.getTemplateHTML(attrs),
},
});
children = [templateShadowRoot, children];
}
return React.createElement('media-theme-microvideo', {
...attrs,
ref: React.useCallback(
(node) => {
elementRef.current = node;
if (typeof ref === 'function') {
ref(node);
} else if (ref !== null) {
ref.current = node;
}
},
[ref]
),
children,
suppressHydrationWarning,
});
});
const ReactPropToAttrNameMap = {
className: 'class',
classname: 'class',
htmlFor: 'for',
viewBox: 'viewBox',
};
function propsToAttrs(props = {}) {
let attrs = {};
for (let [propName, propValue] of Object.entries(props)) {
let attrName = toAttrName(propName, propValue);
if (attrName) attrs[attrName] = toAttrValue(propValue);
}
return attrs;
}
function toAttrName(propName, propValue) {
if (ReactPropToAttrNameMap[propName]) return ReactPropToAttrNameMap[propName];
if (typeof propValue == 'undefined') return undefined;
if (typeof propValue === 'boolean' && !propValue) return undefined;
if (propName.startsWith('on') && typeof propValue === 'function') return undefined;
if (/[A-Z]/.test(propName)) return propName.toLowerCase();
return propName;
}
function toAttrValue(propValue) {
if (typeof propValue === 'boolean') return '';
if (Array.isArray(propValue)) return propValue.join(' ');
return propValue;
}

View File

@@ -0,0 +1,35 @@
{
"name": "@player.style/microvideo",
"version": "0.0.7",
"description": "This theme optimizes for shorter content that doesn't need the robust playback controls that longer content typically requires.",
"author": "@muxinc",
"license": "MIT",
"homepage": "https://github.com/muxinc/player.style#readme",
"bugs": {
"url": "https://github.com/muxinc/player.style/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/muxinc/player.style.git",
"directory": "themes/microvideo"
},
"files": [
"dist"
],
"type": "module",
"main": "dist/media-theme.js",
"exports": {
".": "./dist/media-theme.js",
"./react": "./dist/react.js"
},
"scripts": {
"clean": "rimraf dist",
"build": "build-theme"
},
"peerDependencies": {
"media-chrome": ">=1.0.0"
},
"devDependencies": {
"build-theme": "^0.0.4"
}
}

View File

@@ -0,0 +1,498 @@
<style>
:host {
--_primary-color: var(--media-primary-color, rgb(255 255 255 / .9));
--_secondary-color: var(--media-secondary-color, rgb(0 0 0 / .75));
--_volume-range-expand-width: 70px;
--_volume-range-expand-height: 42px;
--media-icon-color: var(--_primary-color);
--media-range-thumb-background: var(--_primary-color);
--media-range-bar-color: var(--_primary-color);
--media-range-thumb-opacity: 0;
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-control-padding: 5px 5px;
--media-preview-time-text-shadow: none;
--media-tooltip-display: none;
color: var(--_primary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
:host {
--_secondary-color: color-mix(in srgb, var(--media-secondary-color, #000) 75%, transparent);
}
}
[disabled]:not(media-live-button) {
opacity: 60%;
cursor: not-allowed;
}
[breakpointsm] {
--media-control-padding: 9px 5px;
}
[breakpointmd] {
--media-control-padding: 9px 7px;
}
media-time-range,
media-live-button,
media-time-display,
media-text-display,
media-playback-rate-button[role='button'] {
color: inherit;
}
media-controller::part(centered-layer) {
display: grid;
justify-content: unset;
padding-bottom: 6px;
}
:host([streamtype=live]:not([targetlivewindow])) media-controller::part(centered-layer),
:host([mediastreamtype=live]:not([mediatargetlivewindow])) media-controller::part(centered-layer) {
padding-bottom: 0;
}
media-loading-indicator {
place-self: center;
/* Stack the grid items on top of each other */
grid-area: 1 / 1;
}
media-control-bar {
place-self: var(--_control-bar-place-self, end center);
grid-area: 1 / 1;
position: relative;
margin: 10px;
gap: 4px;
align-items: start;
}
:host([controlbarplace$="end"]) media-control-bar {
align-items: end;
}
.control-group {
background: var(--_secondary-color);
position: relative;
display: inline-flex;
border-radius: 5px;
}
:host([controlbarvertical]) :is(media-control-bar, .control-group) {
flex-direction: column;
}
.volume-group {
position: relative;
display: inline-flex;
flex-direction: row;
}
:host([controlbarplace$="end"]) .volume-group {
flex-direction: row-reverse;
}
:host([controlbarplace$="end"]) .volume-group:first-child .volume-range-span {
--_volume-range-padding-left: 10px;
}
:host([controlbarvertical]) .volume-group {
flex-direction: column;
}
:host([controlbarvertical][controlbarplace^="end"]) .volume-group {
flex-direction: column-reverse;
}
:host([controlbarvertical][controlbarplace^="end"]) .volume-group:first-child .volume-range-span {
--_volume-range-padding-top: 10px;
}
.volume-range-span {
display: inline-flex;
position: relative;
overflow: hidden;
width: 0;
}
.volume-group:hover .volume-range-span,
[keyboardcontrol] .volume-group:focus-within .volume-range-span {
width: var(--_volume-range-expand-width);
padding-left: var(--_volume-range-padding-left);
padding-top: var(--_volume-range-padding-top);
}
:host([controlbarvertical]) .volume-range-span {
--_volume-range-padding-left: 0 !important;
display: inline-flex;
height: 0;
}
:host([controlbarvertical]) .volume-group:hover .volume-range-span,
:host([controlbarvertical]) [keyboardcontrol] .volume-group:focus-within .volume-range-span {
height: var(--_volume-range-expand-height);
width: auto;
max-width: 40px;
}
media-volume-range {
--media-range-track-border-radius: 2px;
--media-range-track-background: rgba(255, 255, 255, .2);
width: var(--_volume-range-expand-width);
display: var(--controls, var(--volume-range, inline-block));
border-radius: 5px;
}
:host([controlbarvertical]) media-volume-range {
width: var(--_volume-range-expand-height);
transform: rotate(-90deg);
}
media-control-bar:has(.volume-group:hover),
[keyboardcontrol] media-control-bar:has(.volume-group:focus-within) {
top: var(--_control-bar-offset-top, 0);
left: var(--_control-bar-offset-left, calc(var(--_volume-range-expand-width) / 2));
}
:host([controlbarplace$="start"]),
:host([controlbarplace$="end"]) {
--_control-bar-offset-left: 0;
}
:host([controlbarvertical]) {
--_control-bar-offset-left: 0;
}
:host([controlbarvertical][controlbarplace^="center"]) {
--_control-bar-offset-top: calc(var(--_volume-range-expand-height) / 2);
}
media-time-range {
--media-range-track-height: 6px;
--media-range-track-transition: height .1s linear;
--media-range-track-background: rgba(20, 20, 30, .25);
--media-time-range-buffered-color: rgba(20, 20, 30, .3);
--media-range-track-box-shadow: 0 -1px 0 rgba(20, 20, 30, .07);
--media-range-padding-left: 0;
--media-range-padding-right: 0;
--media-preview-time-background: var(--_secondary-color);
--media-preview-box-margin: 0 0 3px;
display: var(--controls, var(--time-range, inline-block));
width: 100%;
height: 10px;
bottom: -2px;
}
media-live-button {
--media-control-background: var(--_secondary-color);
--media-control-hover-background: var(--_secondary-color);
border-radius: 5px;
}
media-live-button::before {
content: '';
width: 5px;
}
media-live-button::after {
content: '';
width: 7px;
}
/* Turn some buttons off by default */
media-seek-backward-button {
display: var(--media-control-display, var(--media-seek-backward-button-display, none));
}
media-seek-forward-button {
display: var(--media-control-display, var(--media-seek-forward-button-display, none));
}
media-pip-button {
display: var(--media-control-display, var(--media-pip-button-display, none));
}
</style>
<template partial="PlayButton">
<media-play-button
part="play button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="play">
<path d="m6.73 20.93 14.05-8.54a.46.46 0 0 0 0-.78L6.73 3.07a.48.48 0 0 0-.73.39v17.07a.48.48 0 0 0 .73.4Z" />
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="pause">
<path
d="M6 19.5a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v15ZM14.5 4a.5.5 0 0 0-.5.5v15a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5h-3Z"
/>
</svg>
</media-play-button>
</template>
<template partial="SeekBackwardButton">
<media-seek-backward-button
seekoffset="{{backwardseekoffset ?? 10}}"
part="seek-backward button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 22 24" slot="icon">
<path d="M11 6V3L5.37 7 11 10.94V8a5.54 5.54 0 0 1 1.9 10.48v2.12A7.5 7.5 0 0 0 11 6Z" />
<text class="value" transform="translate(2.5 21)" style="font-size: 8px; font-family: 'ArialMT', 'Arial'">
{{backwardseekoffset ?? 10}}
</text>
</svg>
</media-seek-backward-button>
</template>
<template partial="SeekForwardButton">
<media-seek-forward-button
seekoffset="{{forwardseekoffset ?? 10}}"
part="seek-forward button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 22 24" slot="icon">
<path d="M11 6V3l5.61 4L11 10.94V8a5.54 5.54 0 0 0-1.9 10.48v2.12A7.5 7.5 0 0 1 11 6Z" />
<text class="value" transform="translate(10 21)" style="font-size: 8px; font-family: 'ArialMT', 'Arial'">
{{forwardseekoffset ?? 10}}
</text>
</svg>
</media-seek-forward-button>
</template>
<template partial="MuteButton">
<media-mute-button part="mute button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 24 24" slot="high">
<path
d="m11.14 4.86-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.21a.5.5 0 0 0-.86-.35Zm2.74-1.56v1.52A7.52 7.52 0 0 1 19.47 12a7.52 7.52 0 0 1-5.59 7.18v1.52A9 9 0 0 0 21 12a9 9 0 0 0-7.12-8.7Zm3.56 8.7a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="medium">
<path
d="m11.14 4.853-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.203a.5.5 0 0 0-.86-.35Zm6.3 7.14a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="low">
<path
d="m11.14 4.853-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.203a.5.5 0 0 0-.86-.35Zm6.3 7.14a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="off">
<path
d="m3 4.05 4.48 4.47-.33.33a.49.49 0 0 1-.36.15H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.48.48 0 0 0 .36.15.5.5 0 0 0 .5-.5v-5.75l4.67 4.66a7.71 7.71 0 0 1-2.79 1.47v1.52a9.32 9.32 0 0 0 3.87-1.91L20 21l1-1L4.06 3 3 4.05Zm5.36 5.36 2.39 2.39V17L8 14.26a1.74 1.74 0 0 0-1.24-.51H4.25v-3.5h2.54A1.74 1.74 0 0 0 8 9.74l.36-.33ZM19.47 12a7.19 7.19 0 0 1-.89 3.47l1.11 1.1A8.64 8.64 0 0 0 21 12a9 9 0 0 0-7.12-8.7v1.52A7.52 7.52 0 0 1 19.47 12ZM12 8.88V5.21a.5.5 0 0 0-.5-.5.48.48 0 0 0-.36.15L9.56 6.44 12 8.88ZM15.91 12a4.284 4.284 0 0 1-.07.72l1.22 1.22a5.2 5.2 0 0 0 .38-1.94 5.49 5.49 0 0 0-3.56-5.1v1.66A4 4 0 0 1 15.91 12Z"
/>
</svg>
</media-mute-button>
</template>
<template partial="CaptionsButton">
<media-captions-button
part="captions button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="on">
<path
d="M22.832 5.68a2.58 2.58 0 0 0-2.3-2.5c-3.62-.24-11.44-.24-15.06 0a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c3.62.24 11.44.24 15.06 0a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-11.41 10.1a3.63 3.63 0 0 1-1.51.32 4.76 4.76 0 0 1-1.63-.27 4 4 0 0 1-1.28-.83 3.67 3.67 0 0 1-.84-1.26 4.23 4.23 0 0 1-.3-1.63 4.28 4.28 0 0 1 .3-1.64 3.53 3.53 0 0 1 .84-1.21 3.89 3.89 0 0 1 1.29-.8 4.76 4.76 0 0 1 1.63-.27 4.06 4.06 0 0 1 1.35.24c.225.091.44.205.64.34a2.7 2.7 0 0 1 .55.52l-1.27 1a1.79 1.79 0 0 0-.6-.46 2 2 0 0 0-.83-.16 2 2 0 0 0-1.56.69 2.35 2.35 0 0 0-.46.77 2.78 2.78 0 0 0-.16 1c-.009.34.046.68.16 1 .104.283.26.545.46.77.188.21.415.38.67.5a2 2 0 0 0 .84.18 1.87 1.87 0 0 0 .9-.21 1.78 1.78 0 0 0 .65-.6l1.38 1a2.88 2.88 0 0 1-1.22 1.01Zm7.52 0a3.63 3.63 0 0 1-1.51.32 4.76 4.76 0 0 1-1.63-.27 3.89 3.89 0 0 1-1.28-.83 3.55 3.55 0 0 1-.85-1.26 4.23 4.23 0 0 1-.3-1.63 4.28 4.28 0 0 1 .3-1.64 3.43 3.43 0 0 1 .85-1.25 3.75 3.75 0 0 1 1.28-.8 4.76 4.76 0 0 1 1.63-.27 4 4 0 0 1 1.35.24c.225.091.44.205.64.34.21.144.395.32.55.52l-1.27 1a1.79 1.79 0 0 0-.6-.46 2 2 0 0 0-.83-.16 2 2 0 0 0-1.56.69 2.352 2.352 0 0 0-.46.77 3.01 3.01 0 0 0-.16 1c-.003.34.05.678.16 1 .108.282.263.542.46.77.188.21.416.38.67.5a2 2 0 0 0 .84.18 1.87 1.87 0 0 0 .9-.21 1.78 1.78 0 0 0 .65-.6l1.38 1a2.82 2.82 0 0 1-1.21 1.05Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="off">
<path
d="M22.832 5.68a2.58 2.58 0 0 0-2.3-2.5c-1.81-.12-4.67-.18-7.53-.18-2.86 0-5.72.06-7.53.18a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c1.81.12 4.67.18 7.53.18 2.86 0 5.72-.06 7.53-.18a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-1.49 12.53a1.11 1.11 0 0 1-.91 1.11c-1.67.11-4.45.18-7.43.18-2.98 0-5.76-.07-7.43-.18a1.11 1.11 0 0 1-.91-1.11c-.21-4.137-.21-8.283 0-12.42a1.11 1.11 0 0 1 .91-1.11c1.67-.11 4.43-.18 7.43-.18s5.76.07 7.43.18a1.11 1.11 0 0 1 .91 1.11c.21 4.137.21 8.283 0 12.42ZM10.843 14a1.55 1.55 0 0 1-.76.18 1.57 1.57 0 0 1-.71-.18 1.69 1.69 0 0 1-.57-.42 2.099 2.099 0 0 1-.38-.58 2.47 2.47 0 0 1 0-1.64 2 2 0 0 1 .39-.66 1.73 1.73 0 0 1 .58-.42c.23-.103.479-.158.73-.16.241-.004.48.044.7.14.199.088.373.222.51.39l1.08-.89a2.179 2.179 0 0 0-.47-.44 2.81 2.81 0 0 0-.54-.32 2.91 2.91 0 0 0-.58-.15 2.71 2.71 0 0 0-.56 0 4.08 4.08 0 0 0-1.38.15 3.27 3.27 0 0 0-1.09.67 3.14 3.14 0 0 0-.71 1.06 3.62 3.62 0 0 0-.26 1.39 3.57 3.57 0 0 0 .26 1.38 3 3 0 0 0 .71 1.06c.316.293.687.52 1.09.67.443.16.91.238 1.38.23a3.2 3.2 0 0 0 1.28-.27c.401-.183.747-.47 1-.83l-1.17-.88a1.42 1.42 0 0 1-.53.52Zm6.62 0a1.58 1.58 0 0 1-.76.18 1.54 1.54 0 0 1-.7-.18 1.69 1.69 0 0 1-.57-.42 2.12 2.12 0 0 1-.43-.58 2.29 2.29 0 0 1 .39-2.3 1.84 1.84 0 0 1 1.32-.58c.241-.003.48.045.7.14.199.088.373.222.51.39l1.08-.92a2.43 2.43 0 0 0-.47-.44 3.22 3.22 0 0 0-.53-.29 2.999 2.999 0 0 0-.57-.15 2.87 2.87 0 0 0-.57 0 4.06 4.06 0 0 0-1.36.15 3.17 3.17 0 0 0-1.09.67 3 3 0 0 0-.72 1.06 3.62 3.62 0 0 0-.25 1.39 3.57 3.57 0 0 0 .25 1.38c.16.402.405.764.72 1.06a3.17 3.17 0 0 0 1.09.67c.44.16.904.237 1.37.23.441 0 .877-.092 1.28-.27a2.45 2.45 0 0 0 1-.83l-1.15-.85a1.49 1.49 0 0 1-.54.49Z"
/>
</svg>
</media-captions-button>
</template>
<template partial="PipButton">
<media-pip-button part="pip button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="enter">
<path
d="M22 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h6.75v-1.25h-6.5V4.25h17.5v6.5H23V4a1 1 0 0 0-1-1Zm0 10h-8a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1Zm-.5 6.5h-7v-5h7v5Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="exit">
<path
d="M22 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h6.75v-1.25h-6.5V4.25h17.5v6.5H23V4a1 1 0 0 0-1-1Zm0 10h-8a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1Zm-.5 6.5h-7v-5h7v5Z"
/>
</svg>
</media-pip-button>
</template>
<template partial="AirplayButton">
<media-airplay-button part="airplay button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="icon">
<path
d="M13.19 14.22a.25.25 0 0 0-.38 0l-5.46 6.37a.25.25 0 0 0 .19.41h10.92a.25.25 0 0 0 .19-.41l-5.46-6.37Z"
/>
<path
d="M22 3H4a1 1 0 0 0-1 1v13a1 1 0 0 0 1 1h2.94L8 16.75H4.25V4.25h17.5v12.5H18L19.06 18H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
</svg>
</media-airplay-button>
</template>
<template partial="CastButton">
<media-cast-button part="cast button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="enter">
<path d="M3 15.5V17c2.206 0 4 1.794 4 4h1.5A5.5 5.5 0 0 0 3 15.5Zm0 3V21h2.5A2.5 2.5 0 0 0 3 18.5Z" />
<path d="M3 12.5V14c3.86 0 7 3.14 7 7h1.5A8.5 8.5 0 0 0 3 12.5Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v6.984c.424 0 .84.035 1.25.086V4.25h17.5v15.5h-8.82c.051.41.086.826.086 1.25H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="exit">
<path d="M3 15.5V17c2.206 0 4 1.794 4 4h1.5A5.5 5.5 0 0 0 3 15.5Zm0 3V21h2.5A2.5 2.5 0 0 0 3 18.5Z" />
<path d="M3 12.5V14c3.86 0 7 3.14 7 7h1.5A8.5 8.5 0 0 0 3 12.5Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v6.984c.424 0 .84.035 1.25.086V4.25h17.5v15.5h-8.82c.051.41.086.826.086 1.25H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
<path d="M20.5 5.5h-15v5.811c3.52.906 6.283 3.67 7.189 7.19H20.5V5.5Z" />
</svg>
</media-cast-button>
</template>
<template partial="FullscreenButton">
<media-fullscreen-button
part="fullscreen button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="enter">
<path
d="M20.25 14.5a.76.76 0 0 0-.75.75v4.25h-4.25a.75.75 0 1 0 0 1.5h5a.76.76 0 0 0 .75-.75v-5a.76.76 0 0 0-.75-.75Zm0-11.5h-5a.76.76 0 0 0-.75.75.76.76 0 0 0 .75.75h4.25v4.25a.75.75 0 1 0 1.5 0v-5a.76.76 0 0 0-.75-.75ZM8.75 19.5H4.5v-4.25a.76.76 0 0 0-.75-.75.76.76 0 0 0-.75.75v5a.76.76 0 0 0 .75.75h5a.75.75 0 1 0 0-1.5Zm0-16.5h-5a.76.76 0 0 0-.75.75v5a.76.76 0 0 0 .75.75.76.76 0 0 0 .75-.75V4.5h4.25a.76.76 0 0 0 .75-.75.76.76 0 0 0-.75-.75Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="exit">
<path
d="M20.25 14.5h-5a.76.76 0 0 0-.75.75v5a.75.75 0 1 0 1.5 0V16h4.25a.75.75 0 1 0 0-1.5Zm-5-5h5a.75.75 0 1 0 0-1.5H16V3.75a.75.75 0 1 0-1.5 0v5a.76.76 0 0 0 .75.75Zm-6.5 5h-5a.75.75 0 1 0 0 1.5H8v4.25a.75.75 0 1 0 1.5 0v-5a.76.76 0 0 0-.75-.75Zm0-11.5a.76.76 0 0 0-.75.75V8H3.75a.75.75 0 0 0 0 1.5h5a.76.76 0 0 0 .75-.75v-5A.76.76 0 0 0 8.75 3Z"
/>
</svg>
</media-fullscreen-button>
</template>
<template partial="LiveButton">
<media-live-button
part="live seek-live button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<span slot="text">Live</span>
</media-live-button>
</template>
<template partial="TimeRange">
<media-time-range
part="time range"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
></media-time-range>
</template>
<template partial="VolumeRange">
<span class="volume-range-span">
<media-volume-range
part="volume range"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
></media-volume-range>
</span>
</template>
<!--
controlbarplace targets the place-self CSS property of the controlbar.
e.g. controlbarplace="center center" will center the controlbar.
-->
<media-controller
style="--_control-bar-place-self:{{controlbarplace ?? 'unset'}}"
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<media-loading-indicator slot="centered-chrome" noautohide></media-loading-indicator>
<template if="streamtype == 'on-demand'">
<media-control-bar slot="centered-chrome">
<div class="control-group">
{{>PlayButton}}
{{>SeekBackwardButton}}
{{>SeekForwardButton}}
<span class="volume-group">
{{>MuteButton}}
{{>VolumeRange}}
</span>
{{>CaptionsButton}}
{{>AirplayButton}}
{{>CastButton}}
{{>PipButton}}
{{>FullscreenButton}}
</div>
</media-control-bar>
{{>TimeRange}}
</template>
<template if="streamtype == 'live'">
<template if="!targetlivewindow">
<media-control-bar slot="centered-chrome">
{{>LiveButton}}
<div class="control-group">
<span class="volume-group">
{{>MuteButton}}
{{>VolumeRange}}
</span>
{{>CaptionsButton}}
{{>AirplayButton}}
{{>CastButton}}
{{>PipButton}}
{{>FullscreenButton}}
</div>
</media-control-bar>
</template>
<template if="targetlivewindow > 0">
<media-control-bar slot="centered-chrome">
{{>LiveButton}}
<div class="control-group">
{{>PlayButton}}
{{>SeekBackwardButton}}
{{>SeekForwardButton}}
<span class="volume-group">
{{>MuteButton}}
{{>VolumeRange}}
</span>
{{>CaptionsButton}}
{{>AirplayButton}}
{{>CastButton}}
{{>PipButton}}
{{>FullscreenButton}}
</div>
</media-control-bar>
{{>TimeRange}}
</template>
</template>
<slot></slot>
</media-controller>

View File

@@ -0,0 +1,69 @@
# Changelog
## [0.0.7](https://github.com/muxinc/player.style/compare/@player.style/minimal@0.0.6...@player.style/minimal@0.0.7) (2024-09-10)
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.3 to ^0.0.4
## [0.0.6](https://github.com/muxinc/player.style/compare/@player.style/minimal@0.0.5...@player.style/minimal@0.0.6) (2024-08-15)
### Bug Fixes
* improve color CSS vars & site color picker ([#49](https://github.com/muxinc/player.style/issues/49)) ([a8e8dc0](https://github.com/muxinc/player.style/commit/a8e8dc0898979e72d035af87233b2a0941fdcc7f))
* no render on preload none ([#38](https://github.com/muxinc/player.style/issues/38)) ([64dda58](https://github.com/muxinc/player.style/commit/64dda5825562da846edb33ddc7d4ba2548c08e00))
* remove unneeded package.json extra ([f869248](https://github.com/muxinc/player.style/commit/f86924841e9c04e68ac96c3c091eaf192f446772))
* upgrade to Media Chrome v4 ([#64](https://github.com/muxinc/player.style/issues/64)) ([be68af2](https://github.com/muxinc/player.style/commit/be68af2f9c3a6ff6674b9951f0b34f2bfdb042aa))
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.2 to ^0.0.3
## [0.0.5](https://github.com/muxinc/player.style/compare/@player.style/minimal@0.0.4...@player.style/minimal@0.0.5) (2024-06-17)
### Bug Fixes
* media theme types bug ([8dd42da](https://github.com/muxinc/player.style/commit/8dd42dab7f0536a49f2df5109f27c7285ad9ff48))
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.1 to ^0.0.2
## [0.0.4](https://github.com/muxinc/player.style/compare/@player.style/minimal@0.0.3...@player.style/minimal@0.0.4) (2024-06-17)
### Bug Fixes
* Changed Youtube theme name to YT ([#12](https://github.com/muxinc/player.style/issues/12)) ([e981669](https://github.com/muxinc/player.style/commit/e981669b170502e692eae355e904681b26b9552f))
## [0.0.3](https://github.com/muxinc/player.style/compare/@player.style/minimal@0.0.2...@player.style/minimal@0.0.3) (2024-06-14)
### Bug Fixes
* make subpackages publish-able ([f4208e8](https://github.com/muxinc/player.style/commit/f4208e89396241f64cce826a661bee9a6d45e76c))
## [0.0.2](https://github.com/muxinc/player.style/compare/@player.style/minimal-v0.0.1...@player.style/minimal@0.0.2) (2024-06-14)
### Features
* add collection, theme and about base pages ([8d96835](https://github.com/muxinc/player.style/commit/8d968357b5e1097fb75e925e6b0437da0df292b1))
* add packages restructure ([#2](https://github.com/muxinc/player.style/issues/2)) ([b23ddb0](https://github.com/muxinc/player.style/commit/b23ddb0fba3682b19b7d8e2912045ccbfbce6cb0))
* make theme work on entry page ([#1](https://github.com/muxinc/player.style/issues/1)) ([3f766ce](https://github.com/muxinc/player.style/commit/3f766ce271bbf6128e7fc8ef0475fa5c9eb895ae))
### Bug Fixes
* types and cleanup theme build ([#8](https://github.com/muxinc/player.style/issues/8)) ([21b9916](https://github.com/muxinc/player.style/commit/21b991621accfecba421f3cf1d2dbb0b98509d95))

View File

@@ -0,0 +1,13 @@
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
declare global {
interface HTMLElementTagNameMap {
'media-theme-minimal': MediaThemeMinimalElement;
}
}
declare class MediaThemeMinimalElement extends MediaThemeElement {
static template: HTMLTemplateElement;
}
export default MediaThemeMinimalElement;

View File

@@ -0,0 +1,314 @@
<style>
:host {
--_primary-color: var(--media-primary-color, #fff);
--_secondary-color: var(--media-secondary-color, rgb(0 0 0 / .75));
--media-icon-color: var(--_primary-color);
--media-range-thumb-background: var(--_primary-color);
--media-range-bar-color: var(--_primary-color);
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-range-track-border-radius: 3px;
--media-time-range-buffered-color: rgba(255, 255, 255, 0.4);
--media-range-track-background: rgba(255, 255, 255, 0.5);
--media-range-thumb-opacity: 0;
--media-preview-thumbnail-border-radius: 2px;
--media-tooltip-display: none;
color: var(--_primary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
:host {
--_secondary-color: color-mix(in srgb, var(--media-secondary-color, #000) 75%, transparent);
}
}
media-control-bar {
--media-control-padding: 2px;
background: var(--_secondary-color);
align-items: center;
height: 30px;
border-radius: 4px;
margin: 0 5px 5px;
padding-inline: 2px;
}
media-controller[breakpointsm] media-control-bar {
--media-control-padding: 4px;
height: 38px;
border-radius: 8px;
padding-inline: 5px;
}
media-controller[breakpointmd] media-control-bar {
height: 46px;
margin: 0 8px 8px;
}
media-controller[breakpointlg] media-control-bar,
media-controller[breakpointxl] media-control-bar {
padding-inline: 7px;
}
.live-controls-left {
margin-right: auto;
}
media-time-range,
media-live-button,
media-time-display,
media-text-display,
media-playback-rate-button[role='button'] {
color: inherit;
}
[disabled]:not(media-live-button) {
opacity: 60%;
cursor: not-allowed;
}
${/* Turn some buttons off by default */''}
media-seek-backward-button {
display: var(--media-control-display, var(--media-seek-backward-button-display, none));
}
media-seek-forward-button {
display: var(--media-control-display, var(--media-seek-forward-button-display, none));
}
media-pip-button {
display: var(--media-control-display, var(--media-pip-button-display, none));
}
</style>
<template partial="PlayButton">
<media-play-button part="play button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 24 24" slot="play">
<path d="m6.73 20.93 14.05-8.54a.46.46 0 0 0 0-.78L6.73 3.07a.48.48 0 0 0-.73.39v17.07a.48.48 0 0 0 .73.4Z" />
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="pause">
<path
d="M6 19.5a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v15ZM14.5 4a.5.5 0 0 0-.5.5v15a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5h-3Z"
/>
</svg>
</media-play-button>
</template>
<template partial="MuteButton">
<media-mute-button part="mute button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 24 24" slot="high">
<path
d="m11.14 4.86-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.21a.5.5 0 0 0-.86-.35Zm2.74-1.56v1.52A7.52 7.52 0 0 1 19.47 12a7.52 7.52 0 0 1-5.59 7.18v1.52A9 9 0 0 0 21 12a9 9 0 0 0-7.12-8.7Zm3.56 8.7a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="medium">
<path
d="m11.14 4.853-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.203a.5.5 0 0 0-.86-.35Zm6.3 7.14a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="low">
<path
d="m11.14 4.853-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.203a.5.5 0 0 0-.86-.35Zm6.3 7.14a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="off">
<path
d="m3 4.05 4.48 4.47-.33.33a.49.49 0 0 1-.36.15H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.48.48 0 0 0 .36.15.5.5 0 0 0 .5-.5v-5.75l4.67 4.66a7.71 7.71 0 0 1-2.79 1.47v1.52a9.32 9.32 0 0 0 3.87-1.91L20 21l1-1L4.06 3 3 4.05Zm5.36 5.36 2.39 2.39V17L8 14.26a1.74 1.74 0 0 0-1.24-.51H4.25v-3.5h2.54A1.74 1.74 0 0 0 8 9.74l.36-.33ZM19.47 12a7.19 7.19 0 0 1-.89 3.47l1.11 1.1A8.64 8.64 0 0 0 21 12a9 9 0 0 0-7.12-8.7v1.52A7.52 7.52 0 0 1 19.47 12ZM12 8.88V5.21a.5.5 0 0 0-.5-.5.48.48 0 0 0-.36.15L9.56 6.44 12 8.88ZM15.91 12a4.284 4.284 0 0 1-.07.72l1.22 1.22a5.2 5.2 0 0 0 .38-1.94 5.49 5.49 0 0 0-3.56-5.1v1.66A4 4 0 0 1 15.91 12Z"
/>
</svg>
</media-mute-button>
</template>
<template partial="CaptionsButton">
<media-captions-button part="captions button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="on">
<path
d="M22.832 5.68a2.58 2.58 0 0 0-2.3-2.5c-3.62-.24-11.44-.24-15.06 0a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c3.62.24 11.44.24 15.06 0a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-11.41 10.1a3.63 3.63 0 0 1-1.51.32 4.76 4.76 0 0 1-1.63-.27 4 4 0 0 1-1.28-.83 3.67 3.67 0 0 1-.84-1.26 4.23 4.23 0 0 1-.3-1.63 4.28 4.28 0 0 1 .3-1.64 3.53 3.53 0 0 1 .84-1.21 3.89 3.89 0 0 1 1.29-.8 4.76 4.76 0 0 1 1.63-.27 4.06 4.06 0 0 1 1.35.24c.225.091.44.205.64.34a2.7 2.7 0 0 1 .55.52l-1.27 1a1.79 1.79 0 0 0-.6-.46 2 2 0 0 0-.83-.16 2 2 0 0 0-1.56.69 2.35 2.35 0 0 0-.46.77 2.78 2.78 0 0 0-.16 1c-.009.34.046.68.16 1 .104.283.26.545.46.77.188.21.415.38.67.5a2 2 0 0 0 .84.18 1.87 1.87 0 0 0 .9-.21 1.78 1.78 0 0 0 .65-.6l1.38 1a2.88 2.88 0 0 1-1.22 1.01Zm7.52 0a3.63 3.63 0 0 1-1.51.32 4.76 4.76 0 0 1-1.63-.27 3.89 3.89 0 0 1-1.28-.83 3.55 3.55 0 0 1-.85-1.26 4.23 4.23 0 0 1-.3-1.63 4.28 4.28 0 0 1 .3-1.64 3.43 3.43 0 0 1 .85-1.25 3.75 3.75 0 0 1 1.28-.8 4.76 4.76 0 0 1 1.63-.27 4 4 0 0 1 1.35.24c.225.091.44.205.64.34.21.144.395.32.55.52l-1.27 1a1.79 1.79 0 0 0-.6-.46 2 2 0 0 0-.83-.16 2 2 0 0 0-1.56.69 2.352 2.352 0 0 0-.46.77 3.01 3.01 0 0 0-.16 1c-.003.34.05.678.16 1 .108.282.263.542.46.77.188.21.416.38.67.5a2 2 0 0 0 .84.18 1.87 1.87 0 0 0 .9-.21 1.78 1.78 0 0 0 .65-.6l1.38 1a2.82 2.82 0 0 1-1.21 1.05Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="off">
<path
d="M22.832 5.68a2.58 2.58 0 0 0-2.3-2.5c-1.81-.12-4.67-.18-7.53-.18-2.86 0-5.72.06-7.53.18a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c1.81.12 4.67.18 7.53.18 2.86 0 5.72-.06 7.53-.18a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-1.49 12.53a1.11 1.11 0 0 1-.91 1.11c-1.67.11-4.45.18-7.43.18-2.98 0-5.76-.07-7.43-.18a1.11 1.11 0 0 1-.91-1.11c-.21-4.137-.21-8.283 0-12.42a1.11 1.11 0 0 1 .91-1.11c1.67-.11 4.43-.18 7.43-.18s5.76.07 7.43.18a1.11 1.11 0 0 1 .91 1.11c.21 4.137.21 8.283 0 12.42ZM10.843 14a1.55 1.55 0 0 1-.76.18 1.57 1.57 0 0 1-.71-.18 1.69 1.69 0 0 1-.57-.42 2.099 2.099 0 0 1-.38-.58 2.47 2.47 0 0 1 0-1.64 2 2 0 0 1 .39-.66 1.73 1.73 0 0 1 .58-.42c.23-.103.479-.158.73-.16.241-.004.48.044.7.14.199.088.373.222.51.39l1.08-.89a2.179 2.179 0 0 0-.47-.44 2.81 2.81 0 0 0-.54-.32 2.91 2.91 0 0 0-.58-.15 2.71 2.71 0 0 0-.56 0 4.08 4.08 0 0 0-1.38.15 3.27 3.27 0 0 0-1.09.67 3.14 3.14 0 0 0-.71 1.06 3.62 3.62 0 0 0-.26 1.39 3.57 3.57 0 0 0 .26 1.38 3 3 0 0 0 .71 1.06c.316.293.687.52 1.09.67.443.16.91.238 1.38.23a3.2 3.2 0 0 0 1.28-.27c.401-.183.747-.47 1-.83l-1.17-.88a1.42 1.42 0 0 1-.53.52Zm6.62 0a1.58 1.58 0 0 1-.76.18 1.54 1.54 0 0 1-.7-.18 1.69 1.69 0 0 1-.57-.42 2.12 2.12 0 0 1-.43-.58 2.29 2.29 0 0 1 .39-2.3 1.84 1.84 0 0 1 1.32-.58c.241-.003.48.045.7.14.199.088.373.222.51.39l1.08-.92a2.43 2.43 0 0 0-.47-.44 3.22 3.22 0 0 0-.53-.29 2.999 2.999 0 0 0-.57-.15 2.87 2.87 0 0 0-.57 0 4.06 4.06 0 0 0-1.36.15 3.17 3.17 0 0 0-1.09.67 3 3 0 0 0-.72 1.06 3.62 3.62 0 0 0-.25 1.39 3.57 3.57 0 0 0 .25 1.38c.16.402.405.764.72 1.06a3.17 3.17 0 0 0 1.09.67c.44.16.904.237 1.37.23.441 0 .877-.092 1.28-.27a2.45 2.45 0 0 0 1-.83l-1.15-.85a1.49 1.49 0 0 1-.54.49Z"
/>
</svg>
</media-captions-button>
</template>
<template partial="FullscreenButton">
<media-fullscreen-button part="fullscreen button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 24 24" slot="enter">
<path
d="M20.25 14.5a.76.76 0 0 0-.75.75v4.25h-4.25a.75.75 0 1 0 0 1.5h5a.76.76 0 0 0 .75-.75v-5a.76.76 0 0 0-.75-.75Zm0-11.5h-5a.76.76 0 0 0-.75.75.76.76 0 0 0 .75.75h4.25v4.25a.75.75 0 1 0 1.5 0v-5a.76.76 0 0 0-.75-.75ZM8.75 19.5H4.5v-4.25a.76.76 0 0 0-.75-.75.76.76 0 0 0-.75.75v5a.76.76 0 0 0 .75.75h5a.75.75 0 1 0 0-1.5Zm0-16.5h-5a.76.76 0 0 0-.75.75v5a.76.76 0 0 0 .75.75.76.76 0 0 0 .75-.75V4.5h4.25a.76.76 0 0 0 .75-.75.76.76 0 0 0-.75-.75Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="exit">
<path
d="M20.25 14.5h-5a.76.76 0 0 0-.75.75v5a.75.75 0 1 0 1.5 0V16h4.25a.75.75 0 1 0 0-1.5Zm-5-5h5a.75.75 0 1 0 0-1.5H16V3.75a.75.75 0 1 0-1.5 0v5a.76.76 0 0 0 .75.75Zm-6.5 5h-5a.75.75 0 1 0 0 1.5H8v4.25a.75.75 0 1 0 1.5 0v-5a.76.76 0 0 0-.75-.75Zm0-11.5a.76.76 0 0 0-.75.75V8H3.75a.75.75 0 0 0 0 1.5h5a.76.76 0 0 0 .75-.75v-5A.76.76 0 0 0 8.75 3Z"
/>
</svg>
</media-fullscreen-button>
</template>
<template partial="LiveButton">
<media-live-button part="live seek-live button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<span slot="text" style="font-weight: normal">Live</span>
<svg
slot="indicator"
width="8"
height="8"
viewBox="0 0 8 8"
xmlns="http://www.w3.org/2000/svg"
style="width: 8px; height: 8px; margin-right: 2px"
>
<rect width="8" height="8" rx="2" />
</svg>
</media-live-button>
</template>
<template partial="PipButton">
<media-pip-button part="pip button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="enter">
<path
d="M22 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h6.75v-1.25h-6.5V4.25h17.5v6.5H23V4a1 1 0 0 0-1-1Zm0 10h-8a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1Zm-.5 6.5h-7v-5h7v5Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="exit">
<path
d="M22 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h6.75v-1.25h-6.5V4.25h17.5v6.5H23V4a1 1 0 0 0-1-1Zm0 10h-8a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1Zm-.5 6.5h-7v-5h7v5Z"
/>
</svg>
</media-pip-button>
</template>
<template partial="SeekBackwardButton">
<media-seek-backward-button
seekoffset="{{backwardseekoffset ?? 10}}"
part="seek-backward button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 22 24" slot="icon">
<path d="M11 6V3L5.37 7 11 10.94V8a5.54 5.54 0 0 1 1.9 10.48v2.12A7.5 7.5 0 0 0 11 6Z" />
<text class="value" transform="translate(2.5 21)" style="font-size: 8px; font-family: 'ArialMT', 'Arial'">
{{backwardseekoffset ?? 10}}
</text>
</svg>
</media-seek-backward-button>
</template>
<template partial="SeekForwardButton">
<media-seek-forward-button
seekoffset="{{forwardseekoffset ?? 10}}"
part="seek-forward button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 22 24" slot="icon">
<path d="M11 6V3l5.61 4L11 10.94V8a5.54 5.54 0 0 0-1.9 10.48v2.12A7.5 7.5 0 0 1 11 6Z" />
<text class="value" transform="translate(10 21)" style="font-size: 8px; font-family: 'ArialMT', 'Arial'">
{{forwardseekoffset ?? 10}}
</text>
</svg>
</media-seek-forward-button>
</template>
<template partial="AirplayButton">
<media-airplay-button part="airplay button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="icon">
<path d="M13.19 14.22a.25.25 0 0 0-.38 0l-5.46 6.37a.25.25 0 0 0 .19.41h10.92a.25.25 0 0 0 .19-.41l-5.46-6.37Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v13a1 1 0 0 0 1 1h2.94L8 16.75H4.25V4.25h17.5v12.5H18L19.06 18H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
</svg>
</media-airplay-button>
</template>
<template partial="CastButton">
<media-cast-button part="cast button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="enter">
<path d="M3 15.5V17c2.206 0 4 1.794 4 4h1.5A5.5 5.5 0 0 0 3 15.5Zm0 3V21h2.5A2.5 2.5 0 0 0 3 18.5Z" />
<path d="M3 12.5V14c3.86 0 7 3.14 7 7h1.5A8.5 8.5 0 0 0 3 12.5Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v6.984c.424 0 .84.035 1.25.086V4.25h17.5v15.5h-8.82c.051.41.086.826.086 1.25H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="exit">
<path d="M3 15.5V17c2.206 0 4 1.794 4 4h1.5A5.5 5.5 0 0 0 3 15.5Zm0 3V21h2.5A2.5 2.5 0 0 0 3 18.5Z" />
<path d="M3 12.5V14c3.86 0 7 3.14 7 7h1.5A8.5 8.5 0 0 0 3 12.5Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v6.984c.424 0 .84.035 1.25.086V4.25h17.5v15.5h-8.82c.051.41.086.826.086 1.25H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
<path d="M20.5 5.5h-15v5.811c3.52.906 6.283 3.67 7.189 7.19H20.5V5.5Z" />
</svg>
</media-cast-button>
</template>
<template partial="TimeRange">
<media-time-range part="time range" disabled="{{disabled}}" aria-disabled="{{disabled}}"></media-time-range>
</template>
<template partial="VolumeRange">
<media-volume-range part="volume range" disabled="{{disabled}}" aria-disabled="{{disabled}}"></media-volume-range>
</template>
<media-controller
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<media-loading-indicator slot="centered-chrome" noautohide></media-loading-indicator>
<template if="title">
<div slot="top-chrome">
<media-text-display>{{title}}</media-text-display>
</div>
</template>
<template if="streamtype == 'on-demand'">
<template if="!breakpointsm">
<media-control-bar>
{{>PlayButton}} {{>TimeRange}} {{>MuteButton}} {{>CaptionsButton}} {{>FullscreenButton}}
</media-control-bar>
</template>
<template if="breakpointsm">
<media-control-bar>
{{>PlayButton}} {{>SeekBackwardButton}} {{>SeekForwardButton}} {{>TimeRange}}
<template if="breakpointmd">
<media-time-display></media-time-display>
</template>
{{>MuteButton}} {{>VolumeRange}} {{>CaptionsButton}} {{>AirplayButton}} {{>CastButton}} {{>PipButton}}
{{>FullscreenButton}}
</media-control-bar>
</template>
</template>
<template if="streamtype == 'live'">
<media-control-bar>
<div class="live-controls-left">
{{>LiveButton}}
<template if="!targetlivewindow">
<template if="breakpointsm">
<media-time-display></media-time-display>
</template>
</template>
</div>
<template if="targetlivewindow > 0">
<template if="breakpointsm">{{>TimeRange}}</template>
</template>
<div class="live-controls-right">
<template if="targetlivewindow > 0"> {{>SeekBackwardButton}} {{>SeekForwardButton}} </template>
{{>MuteButton}} {{>VolumeRange}} {{>CaptionsButton}} {{>AirplayButton}} {{>CastButton}} {{>PipButton}}
{{>FullscreenButton}}
</div>
</media-control-bar>
</template>
<slot></slot>
</media-controller>

View File

@@ -0,0 +1,344 @@
/*
<media-theme-minimal>
<video
slot="media"
src="https://stream.mux.com/fXNzVtmtWuyz00xnSrJg4OJH6PyNo6D02UzmgeKGkP5YQ/high.mp4"
></video>
</media-theme-minimal>
*/
import 'media-chrome';
import { globalThis } from 'media-chrome/dist/utils/server-safe-globals.js';
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
import 'media-chrome/dist/menu/index.js';
const template = globalThis.document?.createElement?.('template');
if (template) {
template.innerHTML = /*html*/`
<style>
:host {
--_primary-color: var(--media-primary-color, #fff);
--_secondary-color: var(--media-secondary-color, rgb(0 0 0 / .75));
--media-icon-color: var(--_primary-color);
--media-range-thumb-background: var(--_primary-color);
--media-range-bar-color: var(--_primary-color);
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-range-track-border-radius: 3px;
--media-time-range-buffered-color: rgba(255, 255, 255, 0.4);
--media-range-track-background: rgba(255, 255, 255, 0.5);
--media-range-thumb-opacity: 0;
--media-preview-thumbnail-border-radius: 2px;
--media-tooltip-display: none;
color: var(--_primary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
:host {
--_secondary-color: color-mix(in srgb, var(--media-secondary-color, #000) 75%, transparent);
}
}
media-control-bar {
--media-control-padding: 2px;
background: var(--_secondary-color);
align-items: center;
height: 30px;
border-radius: 4px;
margin: 0 5px 5px;
padding-inline: 2px;
}
media-controller[breakpointsm] media-control-bar {
--media-control-padding: 4px;
height: 38px;
border-radius: 8px;
padding-inline: 5px;
}
media-controller[breakpointmd] media-control-bar {
height: 46px;
margin: 0 8px 8px;
}
media-controller[breakpointlg] media-control-bar,
media-controller[breakpointxl] media-control-bar {
padding-inline: 7px;
}
.live-controls-left {
margin-right: auto;
}
media-time-range,
media-live-button,
media-time-display,
media-text-display,
media-playback-rate-button[role='button'] {
color: inherit;
}
[disabled]:not(media-live-button) {
opacity: 60%;
cursor: not-allowed;
}
${/* Turn some buttons off by default */''}
media-seek-backward-button {
display: var(--media-control-display, var(--media-seek-backward-button-display, none));
}
media-seek-forward-button {
display: var(--media-control-display, var(--media-seek-forward-button-display, none));
}
media-pip-button {
display: var(--media-control-display, var(--media-pip-button-display, none));
}
</style>
<template partial="PlayButton">
<media-play-button part="play button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 24 24" slot="play">
<path d="m6.73 20.93 14.05-8.54a.46.46 0 0 0 0-.78L6.73 3.07a.48.48 0 0 0-.73.39v17.07a.48.48 0 0 0 .73.4Z" />
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="pause">
<path
d="M6 19.5a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v15ZM14.5 4a.5.5 0 0 0-.5.5v15a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5h-3Z"
/>
</svg>
</media-play-button>
</template>
<template partial="MuteButton">
<media-mute-button part="mute button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 24 24" slot="high">
<path
d="m11.14 4.86-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.21a.5.5 0 0 0-.86-.35Zm2.74-1.56v1.52A7.52 7.52 0 0 1 19.47 12a7.52 7.52 0 0 1-5.59 7.18v1.52A9 9 0 0 0 21 12a9 9 0 0 0-7.12-8.7Zm3.56 8.7a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="medium">
<path
d="m11.14 4.853-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.203a.5.5 0 0 0-.86-.35Zm6.3 7.14a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="low">
<path
d="m11.14 4.853-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.203a.5.5 0 0 0-.86-.35Zm6.3 7.14a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="off">
<path
d="m3 4.05 4.48 4.47-.33.33a.49.49 0 0 1-.36.15H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.48.48 0 0 0 .36.15.5.5 0 0 0 .5-.5v-5.75l4.67 4.66a7.71 7.71 0 0 1-2.79 1.47v1.52a9.32 9.32 0 0 0 3.87-1.91L20 21l1-1L4.06 3 3 4.05Zm5.36 5.36 2.39 2.39V17L8 14.26a1.74 1.74 0 0 0-1.24-.51H4.25v-3.5h2.54A1.74 1.74 0 0 0 8 9.74l.36-.33ZM19.47 12a7.19 7.19 0 0 1-.89 3.47l1.11 1.1A8.64 8.64 0 0 0 21 12a9 9 0 0 0-7.12-8.7v1.52A7.52 7.52 0 0 1 19.47 12ZM12 8.88V5.21a.5.5 0 0 0-.5-.5.48.48 0 0 0-.36.15L9.56 6.44 12 8.88ZM15.91 12a4.284 4.284 0 0 1-.07.72l1.22 1.22a5.2 5.2 0 0 0 .38-1.94 5.49 5.49 0 0 0-3.56-5.1v1.66A4 4 0 0 1 15.91 12Z"
/>
</svg>
</media-mute-button>
</template>
<template partial="CaptionsButton">
<media-captions-button part="captions button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="on">
<path
d="M22.832 5.68a2.58 2.58 0 0 0-2.3-2.5c-3.62-.24-11.44-.24-15.06 0a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c3.62.24 11.44.24 15.06 0a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-11.41 10.1a3.63 3.63 0 0 1-1.51.32 4.76 4.76 0 0 1-1.63-.27 4 4 0 0 1-1.28-.83 3.67 3.67 0 0 1-.84-1.26 4.23 4.23 0 0 1-.3-1.63 4.28 4.28 0 0 1 .3-1.64 3.53 3.53 0 0 1 .84-1.21 3.89 3.89 0 0 1 1.29-.8 4.76 4.76 0 0 1 1.63-.27 4.06 4.06 0 0 1 1.35.24c.225.091.44.205.64.34a2.7 2.7 0 0 1 .55.52l-1.27 1a1.79 1.79 0 0 0-.6-.46 2 2 0 0 0-.83-.16 2 2 0 0 0-1.56.69 2.35 2.35 0 0 0-.46.77 2.78 2.78 0 0 0-.16 1c-.009.34.046.68.16 1 .104.283.26.545.46.77.188.21.415.38.67.5a2 2 0 0 0 .84.18 1.87 1.87 0 0 0 .9-.21 1.78 1.78 0 0 0 .65-.6l1.38 1a2.88 2.88 0 0 1-1.22 1.01Zm7.52 0a3.63 3.63 0 0 1-1.51.32 4.76 4.76 0 0 1-1.63-.27 3.89 3.89 0 0 1-1.28-.83 3.55 3.55 0 0 1-.85-1.26 4.23 4.23 0 0 1-.3-1.63 4.28 4.28 0 0 1 .3-1.64 3.43 3.43 0 0 1 .85-1.25 3.75 3.75 0 0 1 1.28-.8 4.76 4.76 0 0 1 1.63-.27 4 4 0 0 1 1.35.24c.225.091.44.205.64.34.21.144.395.32.55.52l-1.27 1a1.79 1.79 0 0 0-.6-.46 2 2 0 0 0-.83-.16 2 2 0 0 0-1.56.69 2.352 2.352 0 0 0-.46.77 3.01 3.01 0 0 0-.16 1c-.003.34.05.678.16 1 .108.282.263.542.46.77.188.21.416.38.67.5a2 2 0 0 0 .84.18 1.87 1.87 0 0 0 .9-.21 1.78 1.78 0 0 0 .65-.6l1.38 1a2.82 2.82 0 0 1-1.21 1.05Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="off">
<path
d="M22.832 5.68a2.58 2.58 0 0 0-2.3-2.5c-1.81-.12-4.67-.18-7.53-.18-2.86 0-5.72.06-7.53.18a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c1.81.12 4.67.18 7.53.18 2.86 0 5.72-.06 7.53-.18a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-1.49 12.53a1.11 1.11 0 0 1-.91 1.11c-1.67.11-4.45.18-7.43.18-2.98 0-5.76-.07-7.43-.18a1.11 1.11 0 0 1-.91-1.11c-.21-4.137-.21-8.283 0-12.42a1.11 1.11 0 0 1 .91-1.11c1.67-.11 4.43-.18 7.43-.18s5.76.07 7.43.18a1.11 1.11 0 0 1 .91 1.11c.21 4.137.21 8.283 0 12.42ZM10.843 14a1.55 1.55 0 0 1-.76.18 1.57 1.57 0 0 1-.71-.18 1.69 1.69 0 0 1-.57-.42 2.099 2.099 0 0 1-.38-.58 2.47 2.47 0 0 1 0-1.64 2 2 0 0 1 .39-.66 1.73 1.73 0 0 1 .58-.42c.23-.103.479-.158.73-.16.241-.004.48.044.7.14.199.088.373.222.51.39l1.08-.89a2.179 2.179 0 0 0-.47-.44 2.81 2.81 0 0 0-.54-.32 2.91 2.91 0 0 0-.58-.15 2.71 2.71 0 0 0-.56 0 4.08 4.08 0 0 0-1.38.15 3.27 3.27 0 0 0-1.09.67 3.14 3.14 0 0 0-.71 1.06 3.62 3.62 0 0 0-.26 1.39 3.57 3.57 0 0 0 .26 1.38 3 3 0 0 0 .71 1.06c.316.293.687.52 1.09.67.443.16.91.238 1.38.23a3.2 3.2 0 0 0 1.28-.27c.401-.183.747-.47 1-.83l-1.17-.88a1.42 1.42 0 0 1-.53.52Zm6.62 0a1.58 1.58 0 0 1-.76.18 1.54 1.54 0 0 1-.7-.18 1.69 1.69 0 0 1-.57-.42 2.12 2.12 0 0 1-.43-.58 2.29 2.29 0 0 1 .39-2.3 1.84 1.84 0 0 1 1.32-.58c.241-.003.48.045.7.14.199.088.373.222.51.39l1.08-.92a2.43 2.43 0 0 0-.47-.44 3.22 3.22 0 0 0-.53-.29 2.999 2.999 0 0 0-.57-.15 2.87 2.87 0 0 0-.57 0 4.06 4.06 0 0 0-1.36.15 3.17 3.17 0 0 0-1.09.67 3 3 0 0 0-.72 1.06 3.62 3.62 0 0 0-.25 1.39 3.57 3.57 0 0 0 .25 1.38c.16.402.405.764.72 1.06a3.17 3.17 0 0 0 1.09.67c.44.16.904.237 1.37.23.441 0 .877-.092 1.28-.27a2.45 2.45 0 0 0 1-.83l-1.15-.85a1.49 1.49 0 0 1-.54.49Z"
/>
</svg>
</media-captions-button>
</template>
<template partial="FullscreenButton">
<media-fullscreen-button part="fullscreen button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 24 24" slot="enter">
<path
d="M20.25 14.5a.76.76 0 0 0-.75.75v4.25h-4.25a.75.75 0 1 0 0 1.5h5a.76.76 0 0 0 .75-.75v-5a.76.76 0 0 0-.75-.75Zm0-11.5h-5a.76.76 0 0 0-.75.75.76.76 0 0 0 .75.75h4.25v4.25a.75.75 0 1 0 1.5 0v-5a.76.76 0 0 0-.75-.75ZM8.75 19.5H4.5v-4.25a.76.76 0 0 0-.75-.75.76.76 0 0 0-.75.75v5a.76.76 0 0 0 .75.75h5a.75.75 0 1 0 0-1.5Zm0-16.5h-5a.76.76 0 0 0-.75.75v5a.76.76 0 0 0 .75.75.76.76 0 0 0 .75-.75V4.5h4.25a.76.76 0 0 0 .75-.75.76.76 0 0 0-.75-.75Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="exit">
<path
d="M20.25 14.5h-5a.76.76 0 0 0-.75.75v5a.75.75 0 1 0 1.5 0V16h4.25a.75.75 0 1 0 0-1.5Zm-5-5h5a.75.75 0 1 0 0-1.5H16V3.75a.75.75 0 1 0-1.5 0v5a.76.76 0 0 0 .75.75Zm-6.5 5h-5a.75.75 0 1 0 0 1.5H8v4.25a.75.75 0 1 0 1.5 0v-5a.76.76 0 0 0-.75-.75Zm0-11.5a.76.76 0 0 0-.75.75V8H3.75a.75.75 0 0 0 0 1.5h5a.76.76 0 0 0 .75-.75v-5A.76.76 0 0 0 8.75 3Z"
/>
</svg>
</media-fullscreen-button>
</template>
<template partial="LiveButton">
<media-live-button part="live seek-live button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<span slot="text" style="font-weight: normal">Live</span>
<svg
slot="indicator"
width="8"
height="8"
viewBox="0 0 8 8"
xmlns="http://www.w3.org/2000/svg"
style="width: 8px; height: 8px; margin-right: 2px"
>
<rect width="8" height="8" rx="2" />
</svg>
</media-live-button>
</template>
<template partial="PipButton">
<media-pip-button part="pip button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="enter">
<path
d="M22 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h6.75v-1.25h-6.5V4.25h17.5v6.5H23V4a1 1 0 0 0-1-1Zm0 10h-8a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1Zm-.5 6.5h-7v-5h7v5Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="exit">
<path
d="M22 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h6.75v-1.25h-6.5V4.25h17.5v6.5H23V4a1 1 0 0 0-1-1Zm0 10h-8a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1Zm-.5 6.5h-7v-5h7v5Z"
/>
</svg>
</media-pip-button>
</template>
<template partial="SeekBackwardButton">
<media-seek-backward-button
seekoffset="{{backwardseekoffset ?? 10}}"
part="seek-backward button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 22 24" slot="icon">
<path d="M11 6V3L5.37 7 11 10.94V8a5.54 5.54 0 0 1 1.9 10.48v2.12A7.5 7.5 0 0 0 11 6Z" />
<text class="value" transform="translate(2.5 21)" style="font-size: 8px; font-family: 'ArialMT', 'Arial'">
{{backwardseekoffset ?? 10}}
</text>
</svg>
</media-seek-backward-button>
</template>
<template partial="SeekForwardButton">
<media-seek-forward-button
seekoffset="{{forwardseekoffset ?? 10}}"
part="seek-forward button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 22 24" slot="icon">
<path d="M11 6V3l5.61 4L11 10.94V8a5.54 5.54 0 0 0-1.9 10.48v2.12A7.5 7.5 0 0 1 11 6Z" />
<text class="value" transform="translate(10 21)" style="font-size: 8px; font-family: 'ArialMT', 'Arial'">
{{forwardseekoffset ?? 10}}
</text>
</svg>
</media-seek-forward-button>
</template>
<template partial="AirplayButton">
<media-airplay-button part="airplay button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="icon">
<path d="M13.19 14.22a.25.25 0 0 0-.38 0l-5.46 6.37a.25.25 0 0 0 .19.41h10.92a.25.25 0 0 0 .19-.41l-5.46-6.37Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v13a1 1 0 0 0 1 1h2.94L8 16.75H4.25V4.25h17.5v12.5H18L19.06 18H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
</svg>
</media-airplay-button>
</template>
<template partial="CastButton">
<media-cast-button part="cast button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="enter">
<path d="M3 15.5V17c2.206 0 4 1.794 4 4h1.5A5.5 5.5 0 0 0 3 15.5Zm0 3V21h2.5A2.5 2.5 0 0 0 3 18.5Z" />
<path d="M3 12.5V14c3.86 0 7 3.14 7 7h1.5A8.5 8.5 0 0 0 3 12.5Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v6.984c.424 0 .84.035 1.25.086V4.25h17.5v15.5h-8.82c.051.41.086.826.086 1.25H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="exit">
<path d="M3 15.5V17c2.206 0 4 1.794 4 4h1.5A5.5 5.5 0 0 0 3 15.5Zm0 3V21h2.5A2.5 2.5 0 0 0 3 18.5Z" />
<path d="M3 12.5V14c3.86 0 7 3.14 7 7h1.5A8.5 8.5 0 0 0 3 12.5Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v6.984c.424 0 .84.035 1.25.086V4.25h17.5v15.5h-8.82c.051.41.086.826.086 1.25H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
<path d="M20.5 5.5h-15v5.811c3.52.906 6.283 3.67 7.189 7.19H20.5V5.5Z" />
</svg>
</media-cast-button>
</template>
<template partial="TimeRange">
<media-time-range part="time range" disabled="{{disabled}}" aria-disabled="{{disabled}}"></media-time-range>
</template>
<template partial="VolumeRange">
<media-volume-range part="volume range" disabled="{{disabled}}" aria-disabled="{{disabled}}"></media-volume-range>
</template>
<media-controller
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<media-loading-indicator slot="centered-chrome" noautohide></media-loading-indicator>
<template if="title">
<div slot="top-chrome">
<media-text-display>{{title}}</media-text-display>
</div>
</template>
<template if="streamtype == 'on-demand'">
<template if="!breakpointsm">
<media-control-bar>
{{>PlayButton}} {{>TimeRange}} {{>MuteButton}} {{>CaptionsButton}} {{>FullscreenButton}}
</media-control-bar>
</template>
<template if="breakpointsm">
<media-control-bar>
{{>PlayButton}} {{>SeekBackwardButton}} {{>SeekForwardButton}} {{>TimeRange}}
<template if="breakpointmd">
<media-time-display></media-time-display>
</template>
{{>MuteButton}} {{>VolumeRange}} {{>CaptionsButton}} {{>AirplayButton}} {{>CastButton}} {{>PipButton}}
{{>FullscreenButton}}
</media-control-bar>
</template>
</template>
<template if="streamtype == 'live'">
<media-control-bar>
<div class="live-controls-left">
{{>LiveButton}}
<template if="!targetlivewindow">
<template if="breakpointsm">
<media-time-display></media-time-display>
</template>
</template>
</div>
<template if="targetlivewindow > 0">
<template if="breakpointsm">{{>TimeRange}}</template>
</template>
<div class="live-controls-right">
<template if="targetlivewindow > 0"> {{>SeekBackwardButton}} {{>SeekForwardButton}} </template>
{{>MuteButton}} {{>VolumeRange}} {{>CaptionsButton}} {{>AirplayButton}} {{>CastButton}} {{>PipButton}}
{{>FullscreenButton}}
</div>
</media-control-bar>
</template>
<slot></slot>
</media-controller>
`;
}
class MediaThemeMinimalElement extends MediaThemeElement {
static template = template;
}
if (globalThis.customElements && !globalThis.customElements.get('media-theme-minimal')) {
globalThis.customElements.define('media-theme-minimal', MediaThemeMinimalElement);
}
export default MediaThemeMinimalElement;

View File

@@ -0,0 +1,7 @@
import MediaThemeMinimalElement from './media-theme.js';
declare const MediaThemeMinimal: React.ForwardRefExoticComponent<
React.DetailedHTMLProps<React.HTMLAttributes<MediaThemeMinimalElement>, MediaThemeMinimalElement>
>;
export default MediaThemeMinimal;

View File

@@ -0,0 +1,94 @@
'use client';
import React from 'react';
import Element from './media-theme.js';
export default React.forwardRef((allProps, ref) => {
let { children, suppressHydrationWarning, ...props } = allProps;
const elementRef = React.useRef(null);
for (let name in props) {
if (name[0] === 'o' && name[1] === 'n') {
const useCapture = name.endsWith('Capture');
const eventName = name.slice(2, useCapture ? name.length - 7 : undefined).toLowerCase();
const callback = props[name];
React.useEffect(() => {
const eventTarget = elementRef?.current;
if (!eventTarget || typeof callback !== 'function') return;
eventTarget.addEventListener(eventName, callback, useCapture);
return () => {
eventTarget.removeEventListener(eventName, callback, useCapture);
};
}, [elementRef?.current, callback]);
}
}
const attrs = propsToAttrs(props);
// Only render the custom element template HTML on the server..
// The custom element will render itself on the client.
if (typeof window === 'undefined' && Element?.getTemplateHTML && Element?.shadowRootOptions) {
const { mode, delegatesFocus } = Element.shadowRootOptions;
const templateShadowRoot = React.createElement('template', {
shadowrootmode: mode,
shadowrootdelegatesfocus: delegatesFocus,
dangerouslySetInnerHTML: {
__html: Element.getTemplateHTML(attrs),
},
});
children = [templateShadowRoot, children];
}
return React.createElement('media-theme-minimal', {
...attrs,
ref: React.useCallback(
(node) => {
elementRef.current = node;
if (typeof ref === 'function') {
ref(node);
} else if (ref !== null) {
ref.current = node;
}
},
[ref]
),
children,
suppressHydrationWarning,
});
});
const ReactPropToAttrNameMap = {
className: 'class',
classname: 'class',
htmlFor: 'for',
viewBox: 'viewBox',
};
function propsToAttrs(props = {}) {
let attrs = {};
for (let [propName, propValue] of Object.entries(props)) {
let attrName = toAttrName(propName, propValue);
if (attrName) attrs[attrName] = toAttrValue(propValue);
}
return attrs;
}
function toAttrName(propName, propValue) {
if (ReactPropToAttrNameMap[propName]) return ReactPropToAttrNameMap[propName];
if (typeof propValue == 'undefined') return undefined;
if (typeof propValue === 'boolean' && !propValue) return undefined;
if (propName.startsWith('on') && typeof propValue === 'function') return undefined;
if (/[A-Z]/.test(propName)) return propName.toLowerCase();
return propName;
}
function toAttrValue(propValue) {
if (typeof propValue === 'boolean') return '';
if (Array.isArray(propValue)) return propValue.join(' ');
return propValue;
}

View File

@@ -0,0 +1,35 @@
{
"name": "@player.style/minimal",
"version": "0.0.7",
"description": "This theme pares down the Mux Player experience to the bare bones controls viewers need, ideal for those that want a simpler player experience.",
"author": "@muxinc",
"license": "MIT",
"homepage": "https://github.com/muxinc/player.style#readme",
"bugs": {
"url": "https://github.com/muxinc/player.style/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/muxinc/player.style.git",
"directory": "themes/minimal"
},
"files": [
"dist"
],
"type": "module",
"main": "dist/media-theme.js",
"exports": {
".": "./dist/media-theme.js",
"./react": "./dist/react.js"
},
"scripts": {
"clean": "rimraf dist",
"build": "build-theme"
},
"peerDependencies": {
"media-chrome": ">=1.0.0"
},
"devDependencies": {
"build-theme": "^0.0.4"
}
}

View File

@@ -0,0 +1,314 @@
<style>
:host {
--_primary-color: var(--media-primary-color, #fff);
--_secondary-color: var(--media-secondary-color, rgb(0 0 0 / .75));
--media-icon-color: var(--_primary-color);
--media-range-thumb-background: var(--_primary-color);
--media-range-bar-color: var(--_primary-color);
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-range-track-border-radius: 3px;
--media-time-range-buffered-color: rgba(255, 255, 255, 0.4);
--media-range-track-background: rgba(255, 255, 255, 0.5);
--media-range-thumb-opacity: 0;
--media-preview-thumbnail-border-radius: 2px;
--media-tooltip-display: none;
color: var(--_primary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
:host {
--_secondary-color: color-mix(in srgb, var(--media-secondary-color, #000) 75%, transparent);
}
}
media-control-bar {
--media-control-padding: 2px;
background: var(--_secondary-color);
align-items: center;
height: 30px;
border-radius: 4px;
margin: 0 5px 5px;
padding-inline: 2px;
}
media-controller[breakpointsm] media-control-bar {
--media-control-padding: 4px;
height: 38px;
border-radius: 8px;
padding-inline: 5px;
}
media-controller[breakpointmd] media-control-bar {
height: 46px;
margin: 0 8px 8px;
}
media-controller[breakpointlg] media-control-bar,
media-controller[breakpointxl] media-control-bar {
padding-inline: 7px;
}
.live-controls-left {
margin-right: auto;
}
media-time-range,
media-live-button,
media-time-display,
media-text-display,
media-playback-rate-button[role='button'] {
color: inherit;
}
[disabled]:not(media-live-button) {
opacity: 60%;
cursor: not-allowed;
}
${/* Turn some buttons off by default */''}
media-seek-backward-button {
display: var(--media-control-display, var(--media-seek-backward-button-display, none));
}
media-seek-forward-button {
display: var(--media-control-display, var(--media-seek-forward-button-display, none));
}
media-pip-button {
display: var(--media-control-display, var(--media-pip-button-display, none));
}
</style>
<template partial="PlayButton">
<media-play-button part="play button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 24 24" slot="play">
<path d="m6.73 20.93 14.05-8.54a.46.46 0 0 0 0-.78L6.73 3.07a.48.48 0 0 0-.73.39v17.07a.48.48 0 0 0 .73.4Z" />
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="pause">
<path
d="M6 19.5a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v15ZM14.5 4a.5.5 0 0 0-.5.5v15a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5h-3Z"
/>
</svg>
</media-play-button>
</template>
<template partial="MuteButton">
<media-mute-button part="mute button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 24 24" slot="high">
<path
d="m11.14 4.86-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.21a.5.5 0 0 0-.86-.35Zm2.74-1.56v1.52A7.52 7.52 0 0 1 19.47 12a7.52 7.52 0 0 1-5.59 7.18v1.52A9 9 0 0 0 21 12a9 9 0 0 0-7.12-8.7Zm3.56 8.7a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="medium">
<path
d="m11.14 4.853-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.203a.5.5 0 0 0-.86-.35Zm6.3 7.14a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="low">
<path
d="m11.14 4.853-4 4a.49.49 0 0 1-.35.14H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.5.5 0 0 0 .85-.36V5.203a.5.5 0 0 0-.86-.35Zm6.3 7.14a5.49 5.49 0 0 0-3.56-5.1v1.66a3.93 3.93 0 0 1 0 6.88v1.66a5.49 5.49 0 0 0 3.56-5.1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="off">
<path
d="m3 4.05 4.48 4.47-.33.33a.49.49 0 0 1-.36.15H3.25a.25.25 0 0 0-.25.25v5.5a.25.25 0 0 0 .25.25h3.54a.49.49 0 0 1 .36.15l4 4a.48.48 0 0 0 .36.15.5.5 0 0 0 .5-.5v-5.75l4.67 4.66a7.71 7.71 0 0 1-2.79 1.47v1.52a9.32 9.32 0 0 0 3.87-1.91L20 21l1-1L4.06 3 3 4.05Zm5.36 5.36 2.39 2.39V17L8 14.26a1.74 1.74 0 0 0-1.24-.51H4.25v-3.5h2.54A1.74 1.74 0 0 0 8 9.74l.36-.33ZM19.47 12a7.19 7.19 0 0 1-.89 3.47l1.11 1.1A8.64 8.64 0 0 0 21 12a9 9 0 0 0-7.12-8.7v1.52A7.52 7.52 0 0 1 19.47 12ZM12 8.88V5.21a.5.5 0 0 0-.5-.5.48.48 0 0 0-.36.15L9.56 6.44 12 8.88ZM15.91 12a4.284 4.284 0 0 1-.07.72l1.22 1.22a5.2 5.2 0 0 0 .38-1.94 5.49 5.49 0 0 0-3.56-5.1v1.66A4 4 0 0 1 15.91 12Z"
/>
</svg>
</media-mute-button>
</template>
<template partial="CaptionsButton">
<media-captions-button part="captions button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="on">
<path
d="M22.832 5.68a2.58 2.58 0 0 0-2.3-2.5c-3.62-.24-11.44-.24-15.06 0a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c3.62.24 11.44.24 15.06 0a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-11.41 10.1a3.63 3.63 0 0 1-1.51.32 4.76 4.76 0 0 1-1.63-.27 4 4 0 0 1-1.28-.83 3.67 3.67 0 0 1-.84-1.26 4.23 4.23 0 0 1-.3-1.63 4.28 4.28 0 0 1 .3-1.64 3.53 3.53 0 0 1 .84-1.21 3.89 3.89 0 0 1 1.29-.8 4.76 4.76 0 0 1 1.63-.27 4.06 4.06 0 0 1 1.35.24c.225.091.44.205.64.34a2.7 2.7 0 0 1 .55.52l-1.27 1a1.79 1.79 0 0 0-.6-.46 2 2 0 0 0-.83-.16 2 2 0 0 0-1.56.69 2.35 2.35 0 0 0-.46.77 2.78 2.78 0 0 0-.16 1c-.009.34.046.68.16 1 .104.283.26.545.46.77.188.21.415.38.67.5a2 2 0 0 0 .84.18 1.87 1.87 0 0 0 .9-.21 1.78 1.78 0 0 0 .65-.6l1.38 1a2.88 2.88 0 0 1-1.22 1.01Zm7.52 0a3.63 3.63 0 0 1-1.51.32 4.76 4.76 0 0 1-1.63-.27 3.89 3.89 0 0 1-1.28-.83 3.55 3.55 0 0 1-.85-1.26 4.23 4.23 0 0 1-.3-1.63 4.28 4.28 0 0 1 .3-1.64 3.43 3.43 0 0 1 .85-1.25 3.75 3.75 0 0 1 1.28-.8 4.76 4.76 0 0 1 1.63-.27 4 4 0 0 1 1.35.24c.225.091.44.205.64.34.21.144.395.32.55.52l-1.27 1a1.79 1.79 0 0 0-.6-.46 2 2 0 0 0-.83-.16 2 2 0 0 0-1.56.69 2.352 2.352 0 0 0-.46.77 3.01 3.01 0 0 0-.16 1c-.003.34.05.678.16 1 .108.282.263.542.46.77.188.21.416.38.67.5a2 2 0 0 0 .84.18 1.87 1.87 0 0 0 .9-.21 1.78 1.78 0 0 0 .65-.6l1.38 1a2.82 2.82 0 0 1-1.21 1.05Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="off">
<path
d="M22.832 5.68a2.58 2.58 0 0 0-2.3-2.5c-1.81-.12-4.67-.18-7.53-.18-2.86 0-5.72.06-7.53.18a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c1.81.12 4.67.18 7.53.18 2.86 0 5.72-.06 7.53-.18a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-1.49 12.53a1.11 1.11 0 0 1-.91 1.11c-1.67.11-4.45.18-7.43.18-2.98 0-5.76-.07-7.43-.18a1.11 1.11 0 0 1-.91-1.11c-.21-4.137-.21-8.283 0-12.42a1.11 1.11 0 0 1 .91-1.11c1.67-.11 4.43-.18 7.43-.18s5.76.07 7.43.18a1.11 1.11 0 0 1 .91 1.11c.21 4.137.21 8.283 0 12.42ZM10.843 14a1.55 1.55 0 0 1-.76.18 1.57 1.57 0 0 1-.71-.18 1.69 1.69 0 0 1-.57-.42 2.099 2.099 0 0 1-.38-.58 2.47 2.47 0 0 1 0-1.64 2 2 0 0 1 .39-.66 1.73 1.73 0 0 1 .58-.42c.23-.103.479-.158.73-.16.241-.004.48.044.7.14.199.088.373.222.51.39l1.08-.89a2.179 2.179 0 0 0-.47-.44 2.81 2.81 0 0 0-.54-.32 2.91 2.91 0 0 0-.58-.15 2.71 2.71 0 0 0-.56 0 4.08 4.08 0 0 0-1.38.15 3.27 3.27 0 0 0-1.09.67 3.14 3.14 0 0 0-.71 1.06 3.62 3.62 0 0 0-.26 1.39 3.57 3.57 0 0 0 .26 1.38 3 3 0 0 0 .71 1.06c.316.293.687.52 1.09.67.443.16.91.238 1.38.23a3.2 3.2 0 0 0 1.28-.27c.401-.183.747-.47 1-.83l-1.17-.88a1.42 1.42 0 0 1-.53.52Zm6.62 0a1.58 1.58 0 0 1-.76.18 1.54 1.54 0 0 1-.7-.18 1.69 1.69 0 0 1-.57-.42 2.12 2.12 0 0 1-.43-.58 2.29 2.29 0 0 1 .39-2.3 1.84 1.84 0 0 1 1.32-.58c.241-.003.48.045.7.14.199.088.373.222.51.39l1.08-.92a2.43 2.43 0 0 0-.47-.44 3.22 3.22 0 0 0-.53-.29 2.999 2.999 0 0 0-.57-.15 2.87 2.87 0 0 0-.57 0 4.06 4.06 0 0 0-1.36.15 3.17 3.17 0 0 0-1.09.67 3 3 0 0 0-.72 1.06 3.62 3.62 0 0 0-.25 1.39 3.57 3.57 0 0 0 .25 1.38c.16.402.405.764.72 1.06a3.17 3.17 0 0 0 1.09.67c.44.16.904.237 1.37.23.441 0 .877-.092 1.28-.27a2.45 2.45 0 0 0 1-.83l-1.15-.85a1.49 1.49 0 0 1-.54.49Z"
/>
</svg>
</media-captions-button>
</template>
<template partial="FullscreenButton">
<media-fullscreen-button part="fullscreen button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 24 24" slot="enter">
<path
d="M20.25 14.5a.76.76 0 0 0-.75.75v4.25h-4.25a.75.75 0 1 0 0 1.5h5a.76.76 0 0 0 .75-.75v-5a.76.76 0 0 0-.75-.75Zm0-11.5h-5a.76.76 0 0 0-.75.75.76.76 0 0 0 .75.75h4.25v4.25a.75.75 0 1 0 1.5 0v-5a.76.76 0 0 0-.75-.75ZM8.75 19.5H4.5v-4.25a.76.76 0 0 0-.75-.75.76.76 0 0 0-.75.75v5a.76.76 0 0 0 .75.75h5a.75.75 0 1 0 0-1.5Zm0-16.5h-5a.76.76 0 0 0-.75.75v5a.76.76 0 0 0 .75.75.76.76 0 0 0 .75-.75V4.5h4.25a.76.76 0 0 0 .75-.75.76.76 0 0 0-.75-.75Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 24 24" slot="exit">
<path
d="M20.25 14.5h-5a.76.76 0 0 0-.75.75v5a.75.75 0 1 0 1.5 0V16h4.25a.75.75 0 1 0 0-1.5Zm-5-5h5a.75.75 0 1 0 0-1.5H16V3.75a.75.75 0 1 0-1.5 0v5a.76.76 0 0 0 .75.75Zm-6.5 5h-5a.75.75 0 1 0 0 1.5H8v4.25a.75.75 0 1 0 1.5 0v-5a.76.76 0 0 0-.75-.75Zm0-11.5a.76.76 0 0 0-.75.75V8H3.75a.75.75 0 0 0 0 1.5h5a.76.76 0 0 0 .75-.75v-5A.76.76 0 0 0 8.75 3Z"
/>
</svg>
</media-fullscreen-button>
</template>
<template partial="LiveButton">
<media-live-button part="live seek-live button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<span slot="text" style="font-weight: normal">Live</span>
<svg
slot="indicator"
width="8"
height="8"
viewBox="0 0 8 8"
xmlns="http://www.w3.org/2000/svg"
style="width: 8px; height: 8px; margin-right: 2px"
>
<rect width="8" height="8" rx="2" />
</svg>
</media-live-button>
</template>
<template partial="PipButton">
<media-pip-button part="pip button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="enter">
<path
d="M22 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h6.75v-1.25h-6.5V4.25h17.5v6.5H23V4a1 1 0 0 0-1-1Zm0 10h-8a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1Zm-.5 6.5h-7v-5h7v5Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="exit">
<path
d="M22 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h6.75v-1.25h-6.5V4.25h17.5v6.5H23V4a1 1 0 0 0-1-1Zm0 10h-8a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1Zm-.5 6.5h-7v-5h7v5Z"
/>
</svg>
</media-pip-button>
</template>
<template partial="SeekBackwardButton">
<media-seek-backward-button
seekoffset="{{backwardseekoffset ?? 10}}"
part="seek-backward button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 22 24" slot="icon">
<path d="M11 6V3L5.37 7 11 10.94V8a5.54 5.54 0 0 1 1.9 10.48v2.12A7.5 7.5 0 0 0 11 6Z" />
<text class="value" transform="translate(2.5 21)" style="font-size: 8px; font-family: 'ArialMT', 'Arial'">
{{backwardseekoffset ?? 10}}
</text>
</svg>
</media-seek-backward-button>
</template>
<template partial="SeekForwardButton">
<media-seek-forward-button
seekoffset="{{forwardseekoffset ?? 10}}"
part="seek-forward button"
disabled="{{disabled}}"
aria-disabled="{{disabled}}"
>
<svg aria-hidden="true" viewBox="0 0 22 24" slot="icon">
<path d="M11 6V3l5.61 4L11 10.94V8a5.54 5.54 0 0 0-1.9 10.48v2.12A7.5 7.5 0 0 1 11 6Z" />
<text class="value" transform="translate(10 21)" style="font-size: 8px; font-family: 'ArialMT', 'Arial'">
{{forwardseekoffset ?? 10}}
</text>
</svg>
</media-seek-forward-button>
</template>
<template partial="AirplayButton">
<media-airplay-button part="airplay button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="icon">
<path d="M13.19 14.22a.25.25 0 0 0-.38 0l-5.46 6.37a.25.25 0 0 0 .19.41h10.92a.25.25 0 0 0 .19-.41l-5.46-6.37Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v13a1 1 0 0 0 1 1h2.94L8 16.75H4.25V4.25h17.5v12.5H18L19.06 18H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
</svg>
</media-airplay-button>
</template>
<template partial="CastButton">
<media-cast-button part="cast button" disabled="{{disabled}}" aria-disabled="{{disabled}}">
<svg aria-hidden="true" viewBox="0 0 26 24" slot="enter">
<path d="M3 15.5V17c2.206 0 4 1.794 4 4h1.5A5.5 5.5 0 0 0 3 15.5Zm0 3V21h2.5A2.5 2.5 0 0 0 3 18.5Z" />
<path d="M3 12.5V14c3.86 0 7 3.14 7 7h1.5A8.5 8.5 0 0 0 3 12.5Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v6.984c.424 0 .84.035 1.25.086V4.25h17.5v15.5h-8.82c.051.41.086.826.086 1.25H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
</svg>
<svg aria-hidden="true" viewBox="0 0 26 24" slot="exit">
<path d="M3 15.5V17c2.206 0 4 1.794 4 4h1.5A5.5 5.5 0 0 0 3 15.5Zm0 3V21h2.5A2.5 2.5 0 0 0 3 18.5Z" />
<path d="M3 12.5V14c3.86 0 7 3.14 7 7h1.5A8.5 8.5 0 0 0 3 12.5Z" />
<path
d="M22 3H4a1 1 0 0 0-1 1v6.984c.424 0 .84.035 1.25.086V4.25h17.5v15.5h-8.82c.051.41.086.826.086 1.25H22a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Z"
/>
<path d="M20.5 5.5h-15v5.811c3.52.906 6.283 3.67 7.189 7.19H20.5V5.5Z" />
</svg>
</media-cast-button>
</template>
<template partial="TimeRange">
<media-time-range part="time range" disabled="{{disabled}}" aria-disabled="{{disabled}}"></media-time-range>
</template>
<template partial="VolumeRange">
<media-volume-range part="volume range" disabled="{{disabled}}" aria-disabled="{{disabled}}"></media-volume-range>
</template>
<media-controller
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<media-loading-indicator slot="centered-chrome" noautohide></media-loading-indicator>
<template if="title">
<div slot="top-chrome">
<media-text-display>{{title}}</media-text-display>
</div>
</template>
<template if="streamtype == 'on-demand'">
<template if="!breakpointsm">
<media-control-bar>
{{>PlayButton}} {{>TimeRange}} {{>MuteButton}} {{>CaptionsButton}} {{>FullscreenButton}}
</media-control-bar>
</template>
<template if="breakpointsm">
<media-control-bar>
{{>PlayButton}} {{>SeekBackwardButton}} {{>SeekForwardButton}} {{>TimeRange}}
<template if="breakpointmd">
<media-time-display></media-time-display>
</template>
{{>MuteButton}} {{>VolumeRange}} {{>CaptionsButton}} {{>AirplayButton}} {{>CastButton}} {{>PipButton}}
{{>FullscreenButton}}
</media-control-bar>
</template>
</template>
<template if="streamtype == 'live'">
<media-control-bar>
<div class="live-controls-left">
{{>LiveButton}}
<template if="!targetlivewindow">
<template if="breakpointsm">
<media-time-display></media-time-display>
</template>
</template>
</div>
<template if="targetlivewindow > 0">
<template if="breakpointsm">{{>TimeRange}}</template>
</template>
<div class="live-controls-right">
<template if="targetlivewindow > 0"> {{>SeekBackwardButton}} {{>SeekForwardButton}} </template>
{{>MuteButton}} {{>VolumeRange}} {{>CaptionsButton}} {{>AirplayButton}} {{>CastButton}} {{>PipButton}}
{{>FullscreenButton}}
</div>
</media-control-bar>
</template>
<slot></slot>
</media-controller>

View File

@@ -0,0 +1,20 @@
# Changelog
## [0.0.2](https://github.com/muxinc/player.style/compare/@player.style/sutro-audio-v0.0.1...@player.style/sutro-audio@0.0.2) (2024-09-10)
### Features
* add Sutro audio theme ([#65](https://github.com/muxinc/player.style/issues/65)) ([1ec5d61](https://github.com/muxinc/player.style/commit/1ec5d61b223138b1f668ec1d593189e2717a7279))
### Bug Fixes
* mobile overflow. hide duration on mobile ([#87](https://github.com/muxinc/player.style/issues/87)) ([47cf00c](https://github.com/muxinc/player.style/commit/47cf00c0c11e08a2e90098ef43d29ed6cf1e8fbc)), closes [#78](https://github.com/muxinc/player.style/issues/78)
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.3 to ^0.0.4

View File

@@ -0,0 +1,13 @@
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
declare global {
interface HTMLElementTagNameMap {
'media-theme-sutro-audio': MediaThemeSutroAudioElement;
}
}
declare class MediaThemeSutroAudioElement extends MediaThemeElement {
static template: HTMLTemplateElement;
}
export default MediaThemeSutroAudioElement;

View File

@@ -0,0 +1,529 @@
<!-- Sutro Audio -->
<style>
:host {
--media-font-family: Roboto, helvetica neue, segoe ui, arial, sans-serif;
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-tooltip-display: none;
display: block;
width: 100%;
height: 100%;
}
media-controller {
--base: 20px;
--media-range-track-height: calc(0.125 * var(--base));
--media-control-height: calc(2 * var(--base));
-webkit-font-smoothing: antialiased;
border-radius: 16px;
overflow: hidden;
background: var(--media-secondary-color, #17507B);
font-size: calc(0.75 * var(--base));
font-family: Roboto, Arial, sans-serif;
}
media-controller[breakpointmd] {
--base: 20px;
min-height: 84px;
}
.info,
media-control-bar {
transition: opacity 0.3s ease-in-out;
}
media-controller:has(media-time-range[dragging]) :is(.info, media-control-bar) {
opacity: 0.4;
}
.media-button {
--media-control-hover-background: rgba(255, 255, 255, 0.12);
border-radius: 8px;
position: relative;
padding: 0;
}
.media-button svg {
fill: none;
stroke: var(--media-primary-color, #fff);
stroke-width: 1;
stroke-linecap: round;
stroke-linejoin: round;
}
.bg-shape1,
.bg-shape2 {
position: absolute;
width: 50%;
height: 100%;
max-height: 132px;
position: absolute;
top: 50%;
transform: translateY(-50%);
filter: blur(80px);
mix-blend-mode: plus-lighter;
opacity: 0.24;
}
.bg-shape2 {
right: 0;
}
</style>
<media-controller
audio
breakpoints="md:480"
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<svg class="bg-shape1" viewBox="0 0 193 115">
<path fill="#fff" d="M50.117 51.13c-40.5-6.5-28 13.5-44 30.5-32.5 51.5 75 32.001 77 13.5 2-18.5 45-19.5 86-3.5 41 16.001 16.5-21 12.5-68s-37-14.5-66.5 16.5-24.5 17.5-65 11Z"/>
</svg>
<svg class="bg-shape2" viewBox="0 0 178 138">
<path fill="#fff" d="M26.386 103.374C-14.708 79.891-.175 60.583 18.869 34.491c43.6-58.446 66.15-36.529 139.819 20.352 73.668 56.88-88.202 102.802-73.668 74.623 14.533-28.18-17.54-2.61-58.634-26.092Z"/>
</svg>
<style>
.controls {
position: relative;
z-index: 1;
box-sizing: border-box;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 16px 16px 6px;
}
[breakpointmd] .controls {
min-height: 84px;
display: grid;
align-items: center;
grid-template-columns: repeat(3, 1fr);
padding: 16px;
}
.info {
display: grid;
align-items: end;
margin-bottom: 16px;
}
.info div {
grid-area: 1 / 1;
}
[breakpointmd] .info {
display: flex;
align-items: center;
margin-bottom: 0;
}
.info-text {
position: relative;
padding: 16px;
}
.info h1,
.info h2 {
font-family: var(--media-font-family);
line-height: 1.2;
margin: 0;
font-weight: 400;
color: var(--media-primary-color, #fff);
}
.title {
font-size: 14px;
}
.byline {
font-size: 14px;
opacity: 0.6;
}
.info-poster {
position: relative;
width: 100%;
aspect-ratio: 1;
border-radius: 6px;
overflow: hidden;
box-shadow:
rgba(0, 0, 0, 0) 0px 0px 0px 0px,
rgba(0, 0, 0, 0) 0px 0px 0px 0px,
rgba(0, 0, 0, 0.1) 0px 10px 15px -3px,
rgba(0, 0, 0, 0.1) 0px 4px 6px -4px;
}
[breakpointmd] .info-poster {
width: 52px;
}
slot[name='poster']::slotted(*) {
object-fit: cover;
aspect-ratio: 1;
}
.poster-gradient {
--gradient-steps: hsl(0 0% 0% / 0) 0%, hsl(0 0% 0% / 0.013) 8.1%, hsl(0 0% 0% / 0.049) 15.5%,
hsl(0 0% 0% / 0.104) 22.5%, hsl(0 0% 0% / 0.175) 29%, hsl(0 0% 0% / 0.259) 35.3%,
hsl(0 0% 0% / 0.352) 41.2%, hsl(0 0% 0% / 0.45) 47.1%, hsl(0 0% 0% / 0.55) 52.9%,
hsl(0 0% 0% / 0.648) 58.8%, hsl(0 0% 0% / 0.741) 64.7%, hsl(0 0% 0% / 0.825) 71%,
hsl(0 0% 0% / 0.896) 77.5%, hsl(0 0% 0% / 0.951) 84.5%, hsl(0 0% 0% / 0.987) 91.9%,
hsl(0 0% 0%) 100%;
position: absolute;
bottom: 0;
width: 100%;
height: 100px;
background: linear-gradient(to bottom, var(--gradient-steps));
}
[breakpointmd] .poster-gradient {
display: none;
}
</style>
<div class="controls">
<div class="info">
<div class="info-poster">
<slot name="poster"></slot>
<div class="poster-gradient"></div>
</div>
<div class="info-text">
<template if="mediatitle">
<h1 class="title">{{mediatitle}}</h1>
</template>
<template if="mediabyline">
<h2 class="byline">{{mediabyline}}</h2>
</template>
</div>
</div>
<!-- Control Bar -->
<style>
media-control-bar {
margin: auto;
}
</style>
<media-control-bar>
<!-- Playback Rate -->
<media-playback-rate-button class="media-button"></media-playback-rate-button>
<!-- Seek Backward -->
<media-seek-backward-button class="media-button" seekoffset="10">
<svg
slot="icon"
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
fill="none"
viewBox="0 0 32 32"
>
<path d="m10 13 3-3" />
<path
stroke="none"
fill="currentColor"
d="m11.88 16.08-.95 5.793H9.72l.76-4.631h-.033L9 18.074l.179-1.087 1.564-.908h1.137ZM14.12 22c-.48 0-.874-.119-1.18-.356-.308-.24-.518-.585-.63-1.036-.11-.45-.112-.993-.008-1.626.106-.632.288-1.17.545-1.616.259-.445.58-.783.96-1.015A2.441 2.441 0 0 1 15.101 16c.477 0 .87.117 1.177.35.307.235.517.573.631 1.016.116.444.121.982.017 1.616-.104.635-.286 1.178-.545 1.629-.259.449-.58.793-.964 1.033a2.412 2.412 0 0 1-1.296.356Zm.168-1.016c.33 0 .619-.167.867-.5.247-.334.426-.835.536-1.502.072-.438.088-.803.047-1.095-.039-.294-.127-.515-.265-.662a.698.698 0 0 0-.534-.22c-.325 0-.614.165-.866.497-.25.33-.428.823-.536 1.48-.073.445-.089.816-.048 1.114.041.296.13.519.269.668.138.147.314.22.53.22Z"
/>
<path
d="M19.277 22h2.017c.39 0 .706-.432.706-.964v-7.072c0-.532-.316-.964-.706-.964H10"
/>
</svg>
</media-seek-backward-button>
<!-- Play/Pause -->
<style>
@keyframes bounce-scale-play {
0% {
transform: scale(0.75, 0.75);
}
50% {
transform: scale(115%, 115%);
}
100% {
transform: scale(1, 1);
}
}
media-play-button #icon-play {
opacity: 0;
transform-box: view-box;
transform-origin: center center;
transform: scale(0.5, 0.5);
transition: all 0.5s;
}
media-play-button[mediapaused] #icon-play {
opacity: 1;
transform: scale(1, 1);
animation: 0.35s bounce-scale-play ease-in-out;
}
@keyframes bounce-pause-left {
0% {
font-size: 10px;
}
50% {
font-size: 3px;
}
100% {
font-size: 4px;
}
}
@keyframes bounce-pause-right {
0% {
font-size: 10px;
transform: translateX(-8px);
}
50% {
font-size: 3px;
transform: translateX(1px);
}
100% {
font-size: 4px;
transform: translateX(0);
}
}
media-play-button #pause-left,
media-play-button #pause-right {
/* Using font-size to animate height because using scale was resulting in unexpected positioning */
font-size: 4px;
opacity: 1;
transform: translateX(0);
transform-box: view-box;
}
media-play-button:not([mediapaused]) #pause-left {
animation: 0.3s bounce-pause-left ease-out;
}
media-play-button:not([mediapaused]) #pause-right {
animation: 0.3s bounce-pause-right ease-out;
}
media-play-button[mediapaused] #pause-left,
media-play-button[mediapaused] #pause-right {
opacity: 0;
font-size: 10px;
}
media-play-button[mediapaused] #pause-right {
transform-origin: right center;
transform: translateX(-8px);
}
</style>
<media-play-button mediapaused class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<g>
<path
id="icon-play"
d="M20.7131 14.6976C21.7208 15.2735 21.7208 16.7265 20.7131 17.3024L12.7442 21.856C11.7442 22.4274 10.5 21.7054 10.5 20.5536L10.5 11.4464C10.5 10.2946 11.7442 9.57257 12.7442 10.144L20.7131 14.6976Z"
/>
</g>
<g id="icon-pause">
<rect id="pause-left" x="10.5" width="1em" y="10.5" height="11" rx="0.5" />
<rect id="pause-right" x="17.5" width="1em" y="10.5" height="11" rx="0.5" />
</g>
</svg>
</media-play-button>
<!-- Seek Forward -->
<media-seek-forward-button class="media-button" seekoffset="10">
<svg slot="icon" viewBox="0 0 32 32">
<path d="m22 13-3-3" />
<path
stroke="none"
fill="currentColor"
d="m17.88 16.08-.95 5.793h-1.21l.76-4.631h-.033L15 18.074l.179-1.087 1.564-.908h1.137ZM20.12 22c-.48 0-.874-.119-1.18-.356-.308-.24-.518-.585-.63-1.036-.11-.45-.112-.993-.008-1.626.106-.632.288-1.17.545-1.616.259-.445.58-.783.96-1.015A2.441 2.441 0 0 1 21.101 16c.477 0 .87.117 1.177.35.307.235.517.573.631 1.016.116.444.121.982.017 1.616-.104.635-.286 1.178-.545 1.629-.259.449-.58.793-.964 1.033a2.412 2.412 0 0 1-1.296.356Zm.168-1.016c.33 0 .619-.167.866-.5.248-.334.427-.835.537-1.502.073-.438.088-.803.047-1.095-.039-.294-.127-.515-.265-.662a.698.698 0 0 0-.534-.22c-.326 0-.614.165-.866.497-.25.33-.428.823-.536 1.48-.073.445-.088.816-.048 1.114.041.296.13.519.269.668.137.147.314.22.53.22Z"
/>
<path
d="M12.723 22h-2.017c-.39 0-.706-.432-.706-.964v-7.072c0-.532.316-.964.706-.964H22"
/>
</svg>
</media-seek-forward-button>
<!-- Volume/Mute -->
<style>
media-mute-button {
position: relative;
z-index: 1;
}
media-mute-button .muted-path {
transition: clip-path 0.2s ease-out;
}
media-mute-button #muted-path-2 {
transition-delay: 0.2s;
}
media-mute-button .muted-path {
clip-path: inset(0);
}
media-mute-button:not([mediavolumelevel='off']) #muted-path-1 {
clip-path: inset(0 0 100% 0);
}
media-mute-button:not([mediavolumelevel='off']) #muted-path-2 {
clip-path: inset(0 0 100% 0);
}
media-mute-button .muted-path {
opacity: 0;
}
media-mute-button[mediavolumelevel='off'] .muted-path {
opacity: 1;
}
media-mute-button .vol-path {
opacity: 1;
transition: opacity 0.4s;
}
media-mute-button[mediavolumelevel='off'] .vol-path {
opacity: 0;
}
media-mute-button[mediavolumelevel='low'] #vol-high-path,
media-mute-button[mediavolumelevel='medium'] #vol-high-path {
opacity: 0;
}
</style>
<media-mute-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<g id="vol-paths">
<path
id="speaker-path"
d="M16.5 20.486v-8.972c0-1.537-2.037-2.08-2.802-.745l-1.026 1.79a2.5 2.5 0 0 1-.8.85l-1.194.78A1.5 1.5 0 0 0 10 15.446v1.11c0 .506.255.978.678 1.255l1.194.782a2.5 2.5 0 0 1 .8.849l1.026 1.79c.765 1.334 2.802.792 2.802-.745Z"
/>
<path
id="vol-low-path"
class="vol-path"
d="M18.5 18C19.6046 18 20.5 17.1046 20.5 16C20.5 14.8954 19.6046 14 18.5 14"
/>
<path
id="vol-high-path"
class="vol-path"
d="M18 21C20.7614 21 23 18.7614 23 16C23 13.2386 20.7614 11 18 11"
/>
<path id="muted-path-1" class="muted-path" d="M23 18L19 14" />
<path id="muted-path-2" class="muted-path" d="M23 14L19 18" />
</g>
</svg>
</media-mute-button>
</media-control-bar>
<!-- Time Display -->
<style>
.times {
display: flex;
gap: 3px;
font-size: calc(0.7 * var(--base));
}
.time-display {
padding: 0;
line-height: 1;
}
[breakpointmd] .times {
display: block;
}
[breakpointmd] .time-display {
display: block;
text-align: right;
line-height: 1.2;
}
[breakpointmd] media-duration-display {
opacity: 0.6;
}
.small-time-range {
width: 100%;
height: calc(2 * var(--base));
border-radius: calc(0.25 * var(--base));
--media-range-track-transition: height 0.2s linear;
--media-range-track-backdrop-filter: invert(10%) blur(5px) brightness(110%);
--media-range-track-background: rgba(255, 255, 255, 0.2);
--media-range-track-pointer-background: rgba(255, 255, 255, 0.5);
--media-range-track-border-radius: calc(0.25 * var(--base));
--media-time-range-buffered-color: rgba(255, 255, 255, 0.4);
--media-range-bar-color: rgb(255, 255, 255);
--media-range-thumb-background: #fff;
--media-range-thumb-transition: opacity 0.1s linear;
--media-range-thumb-height: 12px;
--media-range-thumb-width: 12px;
--media-range-thumb-border-radius: 12px;
}
[breakpointmd] .small-time-range {
display: none;
}
</style>
<div class="times">
<media-time-display class="time-display"></media-time-display>
<media-time-range class="small-time-range">
<span slot="preview"></span>
</media-time-range>
<media-duration-display class="time-display"></media-duration-display>
</div>
</div>
<!-- Time Range / Progress Bar -->
<style>
.big-time-range {
--media-range-track-height: 4px;
--media-range-track-transition: height 0.1s linear;
--media-range-track-background: rgba(255, 255, 255, 0.25);
--media-range-track-pointer-background: rgba(255, 255, 255, 0.5);
--media-time-range-buffered-color: rgba(255, 255, 255, 0.3);
--media-range-track-box-shadow: 0 -1px 0 rgba(255, 255, 255, 0.07);
--media-range-padding-left: 0;
--media-range-padding-right: 0;
--media-preview-time-background: var(--_secondary-color);
--media-preview-box-margin: 0 0 3px;
--media-range-thumb-transform: translateY(-3px);
--media-range-thumb-height: 12px;
--media-range-thumb-width: 6px;
--media-range-thumb-border-radius: 2px;
display: none;
position: absolute;
left: 15px;
width: calc(100% - 30px);
height: 10px;
bottom: -3px;
}
[breakpointmd] .big-time-range {
display: block;
}
media-preview-time-display {
font-size: calc(0.65 * var(--base));
line-height: 1;
}
</style>
<media-time-range class="big-time-range">
<media-preview-time-display slot="preview"></media-preview-time-display>
</media-time-range>
</media-controller>

View File

@@ -0,0 +1,559 @@
/*
<media-theme-sutro-audio>
<video
slot="media"
src="https://stream.mux.com/fXNzVtmtWuyz00xnSrJg4OJH6PyNo6D02UzmgeKGkP5YQ/high.mp4"
></video>
</media-theme-sutro-audio>
*/
import 'media-chrome';
import { globalThis } from 'media-chrome/dist/utils/server-safe-globals.js';
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
import 'media-chrome/dist/menu/index.js';
const template = globalThis.document?.createElement?.('template');
if (template) {
template.innerHTML = /*html*/`
<!-- Sutro Audio -->
<style>
:host {
--media-font-family: Roboto, helvetica neue, segoe ui, arial, sans-serif;
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-tooltip-display: none;
display: block;
width: 100%;
height: 100%;
}
media-controller {
--base: 20px;
--media-range-track-height: calc(0.125 * var(--base));
--media-control-height: calc(2 * var(--base));
-webkit-font-smoothing: antialiased;
border-radius: 16px;
overflow: hidden;
background: var(--media-secondary-color, #17507B);
font-size: calc(0.75 * var(--base));
font-family: Roboto, Arial, sans-serif;
}
media-controller[breakpointmd] {
--base: 20px;
min-height: 84px;
}
.info,
media-control-bar {
transition: opacity 0.3s ease-in-out;
}
media-controller:has(media-time-range[dragging]) :is(.info, media-control-bar) {
opacity: 0.4;
}
.media-button {
--media-control-hover-background: rgba(255, 255, 255, 0.12);
border-radius: 8px;
position: relative;
padding: 0;
}
.media-button svg {
fill: none;
stroke: var(--media-primary-color, #fff);
stroke-width: 1;
stroke-linecap: round;
stroke-linejoin: round;
}
.bg-shape1,
.bg-shape2 {
position: absolute;
width: 50%;
height: 100%;
max-height: 132px;
position: absolute;
top: 50%;
transform: translateY(-50%);
filter: blur(80px);
mix-blend-mode: plus-lighter;
opacity: 0.24;
}
.bg-shape2 {
right: 0;
}
</style>
<media-controller
audio
breakpoints="md:480"
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<svg class="bg-shape1" viewBox="0 0 193 115">
<path fill="#fff" d="M50.117 51.13c-40.5-6.5-28 13.5-44 30.5-32.5 51.5 75 32.001 77 13.5 2-18.5 45-19.5 86-3.5 41 16.001 16.5-21 12.5-68s-37-14.5-66.5 16.5-24.5 17.5-65 11Z"/>
</svg>
<svg class="bg-shape2" viewBox="0 0 178 138">
<path fill="#fff" d="M26.386 103.374C-14.708 79.891-.175 60.583 18.869 34.491c43.6-58.446 66.15-36.529 139.819 20.352 73.668 56.88-88.202 102.802-73.668 74.623 14.533-28.18-17.54-2.61-58.634-26.092Z"/>
</svg>
<style>
.controls {
position: relative;
z-index: 1;
box-sizing: border-box;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 16px 16px 6px;
}
[breakpointmd] .controls {
min-height: 84px;
display: grid;
align-items: center;
grid-template-columns: repeat(3, 1fr);
padding: 16px;
}
.info {
display: grid;
align-items: end;
margin-bottom: 16px;
}
.info div {
grid-area: 1 / 1;
}
[breakpointmd] .info {
display: flex;
align-items: center;
margin-bottom: 0;
}
.info-text {
position: relative;
padding: 16px;
}
.info h1,
.info h2 {
font-family: var(--media-font-family);
line-height: 1.2;
margin: 0;
font-weight: 400;
color: var(--media-primary-color, #fff);
}
.title {
font-size: 14px;
}
.byline {
font-size: 14px;
opacity: 0.6;
}
.info-poster {
position: relative;
width: 100%;
aspect-ratio: 1;
border-radius: 6px;
overflow: hidden;
box-shadow:
rgba(0, 0, 0, 0) 0px 0px 0px 0px,
rgba(0, 0, 0, 0) 0px 0px 0px 0px,
rgba(0, 0, 0, 0.1) 0px 10px 15px -3px,
rgba(0, 0, 0, 0.1) 0px 4px 6px -4px;
}
[breakpointmd] .info-poster {
width: 52px;
}
slot[name='poster']::slotted(*) {
object-fit: cover;
aspect-ratio: 1;
}
.poster-gradient {
--gradient-steps: hsl(0 0% 0% / 0) 0%, hsl(0 0% 0% / 0.013) 8.1%, hsl(0 0% 0% / 0.049) 15.5%,
hsl(0 0% 0% / 0.104) 22.5%, hsl(0 0% 0% / 0.175) 29%, hsl(0 0% 0% / 0.259) 35.3%,
hsl(0 0% 0% / 0.352) 41.2%, hsl(0 0% 0% / 0.45) 47.1%, hsl(0 0% 0% / 0.55) 52.9%,
hsl(0 0% 0% / 0.648) 58.8%, hsl(0 0% 0% / 0.741) 64.7%, hsl(0 0% 0% / 0.825) 71%,
hsl(0 0% 0% / 0.896) 77.5%, hsl(0 0% 0% / 0.951) 84.5%, hsl(0 0% 0% / 0.987) 91.9%,
hsl(0 0% 0%) 100%;
position: absolute;
bottom: 0;
width: 100%;
height: 100px;
background: linear-gradient(to bottom, var(--gradient-steps));
}
[breakpointmd] .poster-gradient {
display: none;
}
</style>
<div class="controls">
<div class="info">
<div class="info-poster">
<slot name="poster"></slot>
<div class="poster-gradient"></div>
</div>
<div class="info-text">
<template if="mediatitle">
<h1 class="title">{{mediatitle}}</h1>
</template>
<template if="mediabyline">
<h2 class="byline">{{mediabyline}}</h2>
</template>
</div>
</div>
<!-- Control Bar -->
<style>
media-control-bar {
margin: auto;
}
</style>
<media-control-bar>
<!-- Playback Rate -->
<media-playback-rate-button class="media-button"></media-playback-rate-button>
<!-- Seek Backward -->
<media-seek-backward-button class="media-button" seekoffset="10">
<svg
slot="icon"
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
fill="none"
viewBox="0 0 32 32"
>
<path d="m10 13 3-3" />
<path
stroke="none"
fill="currentColor"
d="m11.88 16.08-.95 5.793H9.72l.76-4.631h-.033L9 18.074l.179-1.087 1.564-.908h1.137ZM14.12 22c-.48 0-.874-.119-1.18-.356-.308-.24-.518-.585-.63-1.036-.11-.45-.112-.993-.008-1.626.106-.632.288-1.17.545-1.616.259-.445.58-.783.96-1.015A2.441 2.441 0 0 1 15.101 16c.477 0 .87.117 1.177.35.307.235.517.573.631 1.016.116.444.121.982.017 1.616-.104.635-.286 1.178-.545 1.629-.259.449-.58.793-.964 1.033a2.412 2.412 0 0 1-1.296.356Zm.168-1.016c.33 0 .619-.167.867-.5.247-.334.426-.835.536-1.502.072-.438.088-.803.047-1.095-.039-.294-.127-.515-.265-.662a.698.698 0 0 0-.534-.22c-.325 0-.614.165-.866.497-.25.33-.428.823-.536 1.48-.073.445-.089.816-.048 1.114.041.296.13.519.269.668.138.147.314.22.53.22Z"
/>
<path
d="M19.277 22h2.017c.39 0 .706-.432.706-.964v-7.072c0-.532-.316-.964-.706-.964H10"
/>
</svg>
</media-seek-backward-button>
<!-- Play/Pause -->
<style>
@keyframes bounce-scale-play {
0% {
transform: scale(0.75, 0.75);
}
50% {
transform: scale(115%, 115%);
}
100% {
transform: scale(1, 1);
}
}
media-play-button #icon-play {
opacity: 0;
transform-box: view-box;
transform-origin: center center;
transform: scale(0.5, 0.5);
transition: all 0.5s;
}
media-play-button[mediapaused] #icon-play {
opacity: 1;
transform: scale(1, 1);
animation: 0.35s bounce-scale-play ease-in-out;
}
@keyframes bounce-pause-left {
0% {
font-size: 10px;
}
50% {
font-size: 3px;
}
100% {
font-size: 4px;
}
}
@keyframes bounce-pause-right {
0% {
font-size: 10px;
transform: translateX(-8px);
}
50% {
font-size: 3px;
transform: translateX(1px);
}
100% {
font-size: 4px;
transform: translateX(0);
}
}
media-play-button #pause-left,
media-play-button #pause-right {
/* Using font-size to animate height because using scale was resulting in unexpected positioning */
font-size: 4px;
opacity: 1;
transform: translateX(0);
transform-box: view-box;
}
media-play-button:not([mediapaused]) #pause-left {
animation: 0.3s bounce-pause-left ease-out;
}
media-play-button:not([mediapaused]) #pause-right {
animation: 0.3s bounce-pause-right ease-out;
}
media-play-button[mediapaused] #pause-left,
media-play-button[mediapaused] #pause-right {
opacity: 0;
font-size: 10px;
}
media-play-button[mediapaused] #pause-right {
transform-origin: right center;
transform: translateX(-8px);
}
</style>
<media-play-button mediapaused class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<g>
<path
id="icon-play"
d="M20.7131 14.6976C21.7208 15.2735 21.7208 16.7265 20.7131 17.3024L12.7442 21.856C11.7442 22.4274 10.5 21.7054 10.5 20.5536L10.5 11.4464C10.5 10.2946 11.7442 9.57257 12.7442 10.144L20.7131 14.6976Z"
/>
</g>
<g id="icon-pause">
<rect id="pause-left" x="10.5" width="1em" y="10.5" height="11" rx="0.5" />
<rect id="pause-right" x="17.5" width="1em" y="10.5" height="11" rx="0.5" />
</g>
</svg>
</media-play-button>
<!-- Seek Forward -->
<media-seek-forward-button class="media-button" seekoffset="10">
<svg slot="icon" viewBox="0 0 32 32">
<path d="m22 13-3-3" />
<path
stroke="none"
fill="currentColor"
d="m17.88 16.08-.95 5.793h-1.21l.76-4.631h-.033L15 18.074l.179-1.087 1.564-.908h1.137ZM20.12 22c-.48 0-.874-.119-1.18-.356-.308-.24-.518-.585-.63-1.036-.11-.45-.112-.993-.008-1.626.106-.632.288-1.17.545-1.616.259-.445.58-.783.96-1.015A2.441 2.441 0 0 1 21.101 16c.477 0 .87.117 1.177.35.307.235.517.573.631 1.016.116.444.121.982.017 1.616-.104.635-.286 1.178-.545 1.629-.259.449-.58.793-.964 1.033a2.412 2.412 0 0 1-1.296.356Zm.168-1.016c.33 0 .619-.167.866-.5.248-.334.427-.835.537-1.502.073-.438.088-.803.047-1.095-.039-.294-.127-.515-.265-.662a.698.698 0 0 0-.534-.22c-.326 0-.614.165-.866.497-.25.33-.428.823-.536 1.48-.073.445-.088.816-.048 1.114.041.296.13.519.269.668.137.147.314.22.53.22Z"
/>
<path
d="M12.723 22h-2.017c-.39 0-.706-.432-.706-.964v-7.072c0-.532.316-.964.706-.964H22"
/>
</svg>
</media-seek-forward-button>
<!-- Volume/Mute -->
<style>
media-mute-button {
position: relative;
z-index: 1;
}
media-mute-button .muted-path {
transition: clip-path 0.2s ease-out;
}
media-mute-button #muted-path-2 {
transition-delay: 0.2s;
}
media-mute-button .muted-path {
clip-path: inset(0);
}
media-mute-button:not([mediavolumelevel='off']) #muted-path-1 {
clip-path: inset(0 0 100% 0);
}
media-mute-button:not([mediavolumelevel='off']) #muted-path-2 {
clip-path: inset(0 0 100% 0);
}
media-mute-button .muted-path {
opacity: 0;
}
media-mute-button[mediavolumelevel='off'] .muted-path {
opacity: 1;
}
media-mute-button .vol-path {
opacity: 1;
transition: opacity 0.4s;
}
media-mute-button[mediavolumelevel='off'] .vol-path {
opacity: 0;
}
media-mute-button[mediavolumelevel='low'] #vol-high-path,
media-mute-button[mediavolumelevel='medium'] #vol-high-path {
opacity: 0;
}
</style>
<media-mute-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<g id="vol-paths">
<path
id="speaker-path"
d="M16.5 20.486v-8.972c0-1.537-2.037-2.08-2.802-.745l-1.026 1.79a2.5 2.5 0 0 1-.8.85l-1.194.78A1.5 1.5 0 0 0 10 15.446v1.11c0 .506.255.978.678 1.255l1.194.782a2.5 2.5 0 0 1 .8.849l1.026 1.79c.765 1.334 2.802.792 2.802-.745Z"
/>
<path
id="vol-low-path"
class="vol-path"
d="M18.5 18C19.6046 18 20.5 17.1046 20.5 16C20.5 14.8954 19.6046 14 18.5 14"
/>
<path
id="vol-high-path"
class="vol-path"
d="M18 21C20.7614 21 23 18.7614 23 16C23 13.2386 20.7614 11 18 11"
/>
<path id="muted-path-1" class="muted-path" d="M23 18L19 14" />
<path id="muted-path-2" class="muted-path" d="M23 14L19 18" />
</g>
</svg>
</media-mute-button>
</media-control-bar>
<!-- Time Display -->
<style>
.times {
display: flex;
gap: 3px;
font-size: calc(0.7 * var(--base));
}
.time-display {
padding: 0;
line-height: 1;
}
[breakpointmd] .times {
display: block;
}
[breakpointmd] .time-display {
display: block;
text-align: right;
line-height: 1.2;
}
[breakpointmd] media-duration-display {
opacity: 0.6;
}
.small-time-range {
width: 100%;
height: calc(2 * var(--base));
border-radius: calc(0.25 * var(--base));
--media-range-track-transition: height 0.2s linear;
--media-range-track-backdrop-filter: invert(10%) blur(5px) brightness(110%);
--media-range-track-background: rgba(255, 255, 255, 0.2);
--media-range-track-pointer-background: rgba(255, 255, 255, 0.5);
--media-range-track-border-radius: calc(0.25 * var(--base));
--media-time-range-buffered-color: rgba(255, 255, 255, 0.4);
--media-range-bar-color: rgb(255, 255, 255);
--media-range-thumb-background: #fff;
--media-range-thumb-transition: opacity 0.1s linear;
--media-range-thumb-height: 12px;
--media-range-thumb-width: 12px;
--media-range-thumb-border-radius: 12px;
}
[breakpointmd] .small-time-range {
display: none;
}
</style>
<div class="times">
<media-time-display class="time-display"></media-time-display>
<media-time-range class="small-time-range">
<span slot="preview"></span>
</media-time-range>
<media-duration-display class="time-display"></media-duration-display>
</div>
</div>
<!-- Time Range / Progress Bar -->
<style>
.big-time-range {
--media-range-track-height: 4px;
--media-range-track-transition: height 0.1s linear;
--media-range-track-background: rgba(255, 255, 255, 0.25);
--media-range-track-pointer-background: rgba(255, 255, 255, 0.5);
--media-time-range-buffered-color: rgba(255, 255, 255, 0.3);
--media-range-track-box-shadow: 0 -1px 0 rgba(255, 255, 255, 0.07);
--media-range-padding-left: 0;
--media-range-padding-right: 0;
--media-preview-time-background: var(--_secondary-color);
--media-preview-box-margin: 0 0 3px;
--media-range-thumb-transform: translateY(-3px);
--media-range-thumb-height: 12px;
--media-range-thumb-width: 6px;
--media-range-thumb-border-radius: 2px;
display: none;
position: absolute;
left: 15px;
width: calc(100% - 30px);
height: 10px;
bottom: -3px;
}
[breakpointmd] .big-time-range {
display: block;
}
media-preview-time-display {
font-size: calc(0.65 * var(--base));
line-height: 1;
}
</style>
<media-time-range class="big-time-range">
<media-preview-time-display slot="preview"></media-preview-time-display>
</media-time-range>
</media-controller>
`;
}
class MediaThemeSutroAudioElement extends MediaThemeElement {
static template = template;
}
if (globalThis.customElements && !globalThis.customElements.get('media-theme-sutro-audio')) {
globalThis.customElements.define('media-theme-sutro-audio', MediaThemeSutroAudioElement);
}
export default MediaThemeSutroAudioElement;

View File

@@ -0,0 +1,7 @@
import MediaThemeSutroAudioElement from './media-theme.js';
declare const MediaThemeSutroAudio: React.ForwardRefExoticComponent<
React.DetailedHTMLProps<React.HTMLAttributes<MediaThemeSutroAudioElement>, MediaThemeSutroAudioElement>
>;
export default MediaThemeSutroAudio;

View File

@@ -0,0 +1,94 @@
'use client';
import React from 'react';
import Element from './media-theme.js';
export default React.forwardRef((allProps, ref) => {
let { children, suppressHydrationWarning, ...props } = allProps;
const elementRef = React.useRef(null);
for (let name in props) {
if (name[0] === 'o' && name[1] === 'n') {
const useCapture = name.endsWith('Capture');
const eventName = name.slice(2, useCapture ? name.length - 7 : undefined).toLowerCase();
const callback = props[name];
React.useEffect(() => {
const eventTarget = elementRef?.current;
if (!eventTarget || typeof callback !== 'function') return;
eventTarget.addEventListener(eventName, callback, useCapture);
return () => {
eventTarget.removeEventListener(eventName, callback, useCapture);
};
}, [elementRef?.current, callback]);
}
}
const attrs = propsToAttrs(props);
// Only render the custom element template HTML on the server..
// The custom element will render itself on the client.
if (typeof window === 'undefined' && Element?.getTemplateHTML && Element?.shadowRootOptions) {
const { mode, delegatesFocus } = Element.shadowRootOptions;
const templateShadowRoot = React.createElement('template', {
shadowrootmode: mode,
shadowrootdelegatesfocus: delegatesFocus,
dangerouslySetInnerHTML: {
__html: Element.getTemplateHTML(attrs),
},
});
children = [templateShadowRoot, children];
}
return React.createElement('media-theme-sutro-audio', {
...attrs,
ref: React.useCallback(
(node) => {
elementRef.current = node;
if (typeof ref === 'function') {
ref(node);
} else if (ref !== null) {
ref.current = node;
}
},
[ref]
),
children,
suppressHydrationWarning,
});
});
const ReactPropToAttrNameMap = {
className: 'class',
classname: 'class',
htmlFor: 'for',
viewBox: 'viewBox',
};
function propsToAttrs(props = {}) {
let attrs = {};
for (let [propName, propValue] of Object.entries(props)) {
let attrName = toAttrName(propName, propValue);
if (attrName) attrs[attrName] = toAttrValue(propValue);
}
return attrs;
}
function toAttrName(propName, propValue) {
if (ReactPropToAttrNameMap[propName]) return ReactPropToAttrNameMap[propName];
if (typeof propValue == 'undefined') return undefined;
if (typeof propValue === 'boolean' && !propValue) return undefined;
if (propName.startsWith('on') && typeof propValue === 'function') return undefined;
if (/[A-Z]/.test(propName)) return propName.toLowerCase();
return propName;
}
function toAttrValue(propValue) {
if (typeof propValue === 'boolean') return '';
if (Array.isArray(propValue)) return propValue.join(' ');
return propValue;
}

View File

@@ -0,0 +1,35 @@
{
"name": "@player.style/sutro-audio",
"version": "0.0.2",
"description": "A sleek and modern theme lovingly named after our favorite SF TV antenna, which is neither sleek nor modern.",
"author": "@muxinc",
"license": "MIT",
"homepage": "https://github.com/muxinc/player.style#readme",
"bugs": {
"url": "https://github.com/muxinc/player.style/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/muxinc/player.style.git",
"directory": "themes/sutro-audio"
},
"files": [
"dist"
],
"type": "module",
"main": "dist/media-theme.js",
"exports": {
".": "./dist/media-theme.js",
"./react": "./dist/react.js"
},
"scripts": {
"clean": "rimraf dist",
"build": "build-theme"
},
"peerDependencies": {
"media-chrome": ">=1.0.0"
},
"devDependencies": {
"build-theme": "^0.0.4"
}
}

View File

@@ -0,0 +1,529 @@
<!-- Sutro Audio -->
<style>
:host {
--media-font-family: Roboto, helvetica neue, segoe ui, arial, sans-serif;
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-tooltip-display: none;
display: block;
width: 100%;
height: 100%;
}
media-controller {
--base: 20px;
--media-range-track-height: calc(0.125 * var(--base));
--media-control-height: calc(2 * var(--base));
-webkit-font-smoothing: antialiased;
border-radius: 16px;
overflow: hidden;
background: var(--media-secondary-color, #17507B);
font-size: calc(0.75 * var(--base));
font-family: Roboto, Arial, sans-serif;
}
media-controller[breakpointmd] {
--base: 20px;
min-height: 84px;
}
.info,
media-control-bar {
transition: opacity 0.3s ease-in-out;
}
media-controller:has(media-time-range[dragging]) :is(.info, media-control-bar) {
opacity: 0.4;
}
.media-button {
--media-control-hover-background: rgba(255, 255, 255, 0.12);
border-radius: 8px;
position: relative;
padding: 0;
}
.media-button svg {
fill: none;
stroke: var(--media-primary-color, #fff);
stroke-width: 1;
stroke-linecap: round;
stroke-linejoin: round;
}
.bg-shape1,
.bg-shape2 {
position: absolute;
width: 50%;
height: 100%;
max-height: 132px;
position: absolute;
top: 50%;
transform: translateY(-50%);
filter: blur(80px);
mix-blend-mode: plus-lighter;
opacity: 0.24;
}
.bg-shape2 {
right: 0;
}
</style>
<media-controller
audio
breakpoints="md:480"
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<svg class="bg-shape1" viewBox="0 0 193 115">
<path fill="#fff" d="M50.117 51.13c-40.5-6.5-28 13.5-44 30.5-32.5 51.5 75 32.001 77 13.5 2-18.5 45-19.5 86-3.5 41 16.001 16.5-21 12.5-68s-37-14.5-66.5 16.5-24.5 17.5-65 11Z"/>
</svg>
<svg class="bg-shape2" viewBox="0 0 178 138">
<path fill="#fff" d="M26.386 103.374C-14.708 79.891-.175 60.583 18.869 34.491c43.6-58.446 66.15-36.529 139.819 20.352 73.668 56.88-88.202 102.802-73.668 74.623 14.533-28.18-17.54-2.61-58.634-26.092Z"/>
</svg>
<style>
.controls {
position: relative;
z-index: 1;
box-sizing: border-box;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 16px 16px 6px;
}
[breakpointmd] .controls {
min-height: 84px;
display: grid;
align-items: center;
grid-template-columns: repeat(3, 1fr);
padding: 16px;
}
.info {
display: grid;
align-items: end;
margin-bottom: 16px;
}
.info div {
grid-area: 1 / 1;
}
[breakpointmd] .info {
display: flex;
align-items: center;
margin-bottom: 0;
}
.info-text {
position: relative;
padding: 16px;
}
.info h1,
.info h2 {
font-family: var(--media-font-family);
line-height: 1.2;
margin: 0;
font-weight: 400;
color: var(--media-primary-color, #fff);
}
.title {
font-size: 14px;
}
.byline {
font-size: 14px;
opacity: 0.6;
}
.info-poster {
position: relative;
width: 100%;
aspect-ratio: 1;
border-radius: 6px;
overflow: hidden;
box-shadow:
rgba(0, 0, 0, 0) 0px 0px 0px 0px,
rgba(0, 0, 0, 0) 0px 0px 0px 0px,
rgba(0, 0, 0, 0.1) 0px 10px 15px -3px,
rgba(0, 0, 0, 0.1) 0px 4px 6px -4px;
}
[breakpointmd] .info-poster {
width: 52px;
}
slot[name='poster']::slotted(*) {
object-fit: cover;
aspect-ratio: 1;
}
.poster-gradient {
--gradient-steps: hsl(0 0% 0% / 0) 0%, hsl(0 0% 0% / 0.013) 8.1%, hsl(0 0% 0% / 0.049) 15.5%,
hsl(0 0% 0% / 0.104) 22.5%, hsl(0 0% 0% / 0.175) 29%, hsl(0 0% 0% / 0.259) 35.3%,
hsl(0 0% 0% / 0.352) 41.2%, hsl(0 0% 0% / 0.45) 47.1%, hsl(0 0% 0% / 0.55) 52.9%,
hsl(0 0% 0% / 0.648) 58.8%, hsl(0 0% 0% / 0.741) 64.7%, hsl(0 0% 0% / 0.825) 71%,
hsl(0 0% 0% / 0.896) 77.5%, hsl(0 0% 0% / 0.951) 84.5%, hsl(0 0% 0% / 0.987) 91.9%,
hsl(0 0% 0%) 100%;
position: absolute;
bottom: 0;
width: 100%;
height: 100px;
background: linear-gradient(to bottom, var(--gradient-steps));
}
[breakpointmd] .poster-gradient {
display: none;
}
</style>
<div class="controls">
<div class="info">
<div class="info-poster">
<slot name="poster"></slot>
<div class="poster-gradient"></div>
</div>
<div class="info-text">
<template if="mediatitle">
<h1 class="title">{{mediatitle}}</h1>
</template>
<template if="mediabyline">
<h2 class="byline">{{mediabyline}}</h2>
</template>
</div>
</div>
<!-- Control Bar -->
<style>
media-control-bar {
margin: auto;
}
</style>
<media-control-bar>
<!-- Playback Rate -->
<media-playback-rate-button class="media-button"></media-playback-rate-button>
<!-- Seek Backward -->
<media-seek-backward-button class="media-button" seekoffset="10">
<svg
slot="icon"
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
fill="none"
viewBox="0 0 32 32"
>
<path d="m10 13 3-3" />
<path
stroke="none"
fill="currentColor"
d="m11.88 16.08-.95 5.793H9.72l.76-4.631h-.033L9 18.074l.179-1.087 1.564-.908h1.137ZM14.12 22c-.48 0-.874-.119-1.18-.356-.308-.24-.518-.585-.63-1.036-.11-.45-.112-.993-.008-1.626.106-.632.288-1.17.545-1.616.259-.445.58-.783.96-1.015A2.441 2.441 0 0 1 15.101 16c.477 0 .87.117 1.177.35.307.235.517.573.631 1.016.116.444.121.982.017 1.616-.104.635-.286 1.178-.545 1.629-.259.449-.58.793-.964 1.033a2.412 2.412 0 0 1-1.296.356Zm.168-1.016c.33 0 .619-.167.867-.5.247-.334.426-.835.536-1.502.072-.438.088-.803.047-1.095-.039-.294-.127-.515-.265-.662a.698.698 0 0 0-.534-.22c-.325 0-.614.165-.866.497-.25.33-.428.823-.536 1.48-.073.445-.089.816-.048 1.114.041.296.13.519.269.668.138.147.314.22.53.22Z"
/>
<path
d="M19.277 22h2.017c.39 0 .706-.432.706-.964v-7.072c0-.532-.316-.964-.706-.964H10"
/>
</svg>
</media-seek-backward-button>
<!-- Play/Pause -->
<style>
@keyframes bounce-scale-play {
0% {
transform: scale(0.75, 0.75);
}
50% {
transform: scale(115%, 115%);
}
100% {
transform: scale(1, 1);
}
}
media-play-button #icon-play {
opacity: 0;
transform-box: view-box;
transform-origin: center center;
transform: scale(0.5, 0.5);
transition: all 0.5s;
}
media-play-button[mediapaused] #icon-play {
opacity: 1;
transform: scale(1, 1);
animation: 0.35s bounce-scale-play ease-in-out;
}
@keyframes bounce-pause-left {
0% {
font-size: 10px;
}
50% {
font-size: 3px;
}
100% {
font-size: 4px;
}
}
@keyframes bounce-pause-right {
0% {
font-size: 10px;
transform: translateX(-8px);
}
50% {
font-size: 3px;
transform: translateX(1px);
}
100% {
font-size: 4px;
transform: translateX(0);
}
}
media-play-button #pause-left,
media-play-button #pause-right {
/* Using font-size to animate height because using scale was resulting in unexpected positioning */
font-size: 4px;
opacity: 1;
transform: translateX(0);
transform-box: view-box;
}
media-play-button:not([mediapaused]) #pause-left {
animation: 0.3s bounce-pause-left ease-out;
}
media-play-button:not([mediapaused]) #pause-right {
animation: 0.3s bounce-pause-right ease-out;
}
media-play-button[mediapaused] #pause-left,
media-play-button[mediapaused] #pause-right {
opacity: 0;
font-size: 10px;
}
media-play-button[mediapaused] #pause-right {
transform-origin: right center;
transform: translateX(-8px);
}
</style>
<media-play-button mediapaused class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<g>
<path
id="icon-play"
d="M20.7131 14.6976C21.7208 15.2735 21.7208 16.7265 20.7131 17.3024L12.7442 21.856C11.7442 22.4274 10.5 21.7054 10.5 20.5536L10.5 11.4464C10.5 10.2946 11.7442 9.57257 12.7442 10.144L20.7131 14.6976Z"
/>
</g>
<g id="icon-pause">
<rect id="pause-left" x="10.5" width="1em" y="10.5" height="11" rx="0.5" />
<rect id="pause-right" x="17.5" width="1em" y="10.5" height="11" rx="0.5" />
</g>
</svg>
</media-play-button>
<!-- Seek Forward -->
<media-seek-forward-button class="media-button" seekoffset="10">
<svg slot="icon" viewBox="0 0 32 32">
<path d="m22 13-3-3" />
<path
stroke="none"
fill="currentColor"
d="m17.88 16.08-.95 5.793h-1.21l.76-4.631h-.033L15 18.074l.179-1.087 1.564-.908h1.137ZM20.12 22c-.48 0-.874-.119-1.18-.356-.308-.24-.518-.585-.63-1.036-.11-.45-.112-.993-.008-1.626.106-.632.288-1.17.545-1.616.259-.445.58-.783.96-1.015A2.441 2.441 0 0 1 21.101 16c.477 0 .87.117 1.177.35.307.235.517.573.631 1.016.116.444.121.982.017 1.616-.104.635-.286 1.178-.545 1.629-.259.449-.58.793-.964 1.033a2.412 2.412 0 0 1-1.296.356Zm.168-1.016c.33 0 .619-.167.866-.5.248-.334.427-.835.537-1.502.073-.438.088-.803.047-1.095-.039-.294-.127-.515-.265-.662a.698.698 0 0 0-.534-.22c-.326 0-.614.165-.866.497-.25.33-.428.823-.536 1.48-.073.445-.088.816-.048 1.114.041.296.13.519.269.668.137.147.314.22.53.22Z"
/>
<path
d="M12.723 22h-2.017c-.39 0-.706-.432-.706-.964v-7.072c0-.532.316-.964.706-.964H22"
/>
</svg>
</media-seek-forward-button>
<!-- Volume/Mute -->
<style>
media-mute-button {
position: relative;
z-index: 1;
}
media-mute-button .muted-path {
transition: clip-path 0.2s ease-out;
}
media-mute-button #muted-path-2 {
transition-delay: 0.2s;
}
media-mute-button .muted-path {
clip-path: inset(0);
}
media-mute-button:not([mediavolumelevel='off']) #muted-path-1 {
clip-path: inset(0 0 100% 0);
}
media-mute-button:not([mediavolumelevel='off']) #muted-path-2 {
clip-path: inset(0 0 100% 0);
}
media-mute-button .muted-path {
opacity: 0;
}
media-mute-button[mediavolumelevel='off'] .muted-path {
opacity: 1;
}
media-mute-button .vol-path {
opacity: 1;
transition: opacity 0.4s;
}
media-mute-button[mediavolumelevel='off'] .vol-path {
opacity: 0;
}
media-mute-button[mediavolumelevel='low'] #vol-high-path,
media-mute-button[mediavolumelevel='medium'] #vol-high-path {
opacity: 0;
}
</style>
<media-mute-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<g id="vol-paths">
<path
id="speaker-path"
d="M16.5 20.486v-8.972c0-1.537-2.037-2.08-2.802-.745l-1.026 1.79a2.5 2.5 0 0 1-.8.85l-1.194.78A1.5 1.5 0 0 0 10 15.446v1.11c0 .506.255.978.678 1.255l1.194.782a2.5 2.5 0 0 1 .8.849l1.026 1.79c.765 1.334 2.802.792 2.802-.745Z"
/>
<path
id="vol-low-path"
class="vol-path"
d="M18.5 18C19.6046 18 20.5 17.1046 20.5 16C20.5 14.8954 19.6046 14 18.5 14"
/>
<path
id="vol-high-path"
class="vol-path"
d="M18 21C20.7614 21 23 18.7614 23 16C23 13.2386 20.7614 11 18 11"
/>
<path id="muted-path-1" class="muted-path" d="M23 18L19 14" />
<path id="muted-path-2" class="muted-path" d="M23 14L19 18" />
</g>
</svg>
</media-mute-button>
</media-control-bar>
<!-- Time Display -->
<style>
.times {
display: flex;
gap: 3px;
font-size: calc(0.7 * var(--base));
}
.time-display {
padding: 0;
line-height: 1;
}
[breakpointmd] .times {
display: block;
}
[breakpointmd] .time-display {
display: block;
text-align: right;
line-height: 1.2;
}
[breakpointmd] media-duration-display {
opacity: 0.6;
}
.small-time-range {
width: 100%;
height: calc(2 * var(--base));
border-radius: calc(0.25 * var(--base));
--media-range-track-transition: height 0.2s linear;
--media-range-track-backdrop-filter: invert(10%) blur(5px) brightness(110%);
--media-range-track-background: rgba(255, 255, 255, 0.2);
--media-range-track-pointer-background: rgba(255, 255, 255, 0.5);
--media-range-track-border-radius: calc(0.25 * var(--base));
--media-time-range-buffered-color: rgba(255, 255, 255, 0.4);
--media-range-bar-color: rgb(255, 255, 255);
--media-range-thumb-background: #fff;
--media-range-thumb-transition: opacity 0.1s linear;
--media-range-thumb-height: 12px;
--media-range-thumb-width: 12px;
--media-range-thumb-border-radius: 12px;
}
[breakpointmd] .small-time-range {
display: none;
}
</style>
<div class="times">
<media-time-display class="time-display"></media-time-display>
<media-time-range class="small-time-range">
<span slot="preview"></span>
</media-time-range>
<media-duration-display class="time-display"></media-duration-display>
</div>
</div>
<!-- Time Range / Progress Bar -->
<style>
.big-time-range {
--media-range-track-height: 4px;
--media-range-track-transition: height 0.1s linear;
--media-range-track-background: rgba(255, 255, 255, 0.25);
--media-range-track-pointer-background: rgba(255, 255, 255, 0.5);
--media-time-range-buffered-color: rgba(255, 255, 255, 0.3);
--media-range-track-box-shadow: 0 -1px 0 rgba(255, 255, 255, 0.07);
--media-range-padding-left: 0;
--media-range-padding-right: 0;
--media-preview-time-background: var(--_secondary-color);
--media-preview-box-margin: 0 0 3px;
--media-range-thumb-transform: translateY(-3px);
--media-range-thumb-height: 12px;
--media-range-thumb-width: 6px;
--media-range-thumb-border-radius: 2px;
display: none;
position: absolute;
left: 15px;
width: calc(100% - 30px);
height: 10px;
bottom: -3px;
}
[breakpointmd] .big-time-range {
display: block;
}
media-preview-time-display {
font-size: calc(0.65 * var(--base));
line-height: 1;
}
</style>
<media-time-range class="big-time-range">
<media-preview-time-display slot="preview"></media-preview-time-display>
</media-time-range>
</media-controller>

View File

@@ -0,0 +1,30 @@
# Changelog
## [0.0.3](https://github.com/muxinc/player.style/compare/@player.style/sutro@0.0.2...@player.style/sutro@0.0.3) (2024-09-10)
### Bug Fixes
* custom colors + hide empty settings menu item ([#85](https://github.com/muxinc/player.style/issues/85)) ([d2815b3](https://github.com/muxinc/player.style/commit/d2815b34b023e7e5829326528fc51c895f42fca7))
* mobile overflow. hide duration on mobile ([#87](https://github.com/muxinc/player.style/issues/87)) ([47cf00c](https://github.com/muxinc/player.style/commit/47cf00c0c11e08a2e90098ef43d29ed6cf1e8fbc)), closes [#78](https://github.com/muxinc/player.style/issues/78)
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.3 to ^0.0.4
## [0.0.2](https://github.com/muxinc/player.style/compare/@player.style/sutro-v0.0.1...@player.style/sutro@0.0.2) (2024-08-15)
### Bug Fixes
* upgrade to Media Chrome v4 ([#64](https://github.com/muxinc/player.style/issues/64)) ([be68af2](https://github.com/muxinc/player.style/commit/be68af2f9c3a6ff6674b9951f0b34f2bfdb042aa))
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.2 to ^0.0.3

View File

@@ -0,0 +1,13 @@
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
declare global {
interface HTMLElementTagNameMap {
'media-theme-sutro': MediaThemeSutroElement;
}
}
declare class MediaThemeSutroElement extends MediaThemeElement {
static template: HTMLTemplateElement;
}
export default MediaThemeSutroElement;

View File

@@ -0,0 +1,763 @@
<!-- Sutro -->
<style>
:host {
--_primary-color: var(--media-primary-color, #fff);
--_secondary-color: var(--media-secondary-color, transparent);
--_accent-color: var(--media-accent-color, #fff);
}
media-controller {
--base: 18px;
font-size: calc(0.75 * var(--base));
font-family: Roboto, Arial, sans-serif;
--media-font-family: Roboto, helvetica neue, segoe ui, arial, sans-serif;
-webkit-font-smoothing: antialiased;
--media-primary-color: #fff;
--media-secondary-color: transparent;
--media-menu-background: rgba(28, 28, 28, 0.6);
--media-text-color: var(--_primary-color);
--media-control-hover-background: var(--media-secondary-color);
--media-range-track-height: calc(0.125 * var(--base));
--media-range-thumb-height: var(--base);
--media-range-thumb-width: var(--base);
--media-range-thumb-border-radius: var(--base);
--media-control-height: calc(2 * var(--base));
--media-tooltip-display: none;
}
media-controller[breakpointmd] {
--base: 20px;
}
/* The biggest size controller is tied to going fullscreen
instead of a player width */
media-controller[mediaisfullscreen] {
--base: 24px;
}
.media-button {
--media-control-hover-background: var(--_secondary-color);
position: relative;
padding: 0;
opacity: 0.9;
transition: opacity 0.1s cubic-bezier(0.4, 0, 1, 1);
}
.media-button svg {
fill: none;
stroke: var(--_primary-color);
stroke-width: 1;
stroke-linecap: 'round';
stroke-linejoin: 'round';
}
svg .svg-shadow {
stroke: #000;
stroke-opacity: 0.15;
stroke-width: 2px;
fill: none;
}
</style>
<media-controller
breakpoints="md:480"
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<!-- Controls Gradient -->
<style>
.media-gradient-bottom {
--gradient-steps: hsl(0 0% 0% / 0) 0%, hsl(0 0% 0% / 0.013) 8.1%, hsl(0 0% 0% / 0.049) 15.5%,
hsl(0 0% 0% / 0.104) 22.5%, hsl(0 0% 0% / 0.175) 29%, hsl(0 0% 0% / 0.259) 35.3%, hsl(0 0% 0% / 0.352) 41.2%,
hsl(0 0% 0% / 0.45) 47.1%, hsl(0 0% 0% / 0.55) 52.9%, hsl(0 0% 0% / 0.648) 58.8%, hsl(0 0% 0% / 0.741) 64.7%,
hsl(0 0% 0% / 0.825) 71%, hsl(0 0% 0% / 0.896) 77.5%, hsl(0 0% 0% / 0.951) 84.5%, hsl(0 0% 0% / 0.987) 91.9%,
hsl(0 0% 0%) 100%;
position: absolute;
bottom: 0;
opacity: 0.7;
width: 100%;
height: calc(8 * var(--base));
background: linear-gradient(to bottom, var(--gradient-steps));
pointer-events: none;
}
</style>
<div class="media-gradient-bottom"></div>
<!-- Settings Menu -->
<style>
media-settings-menu {
--media-menu-icon-height: 20px;
--media-menu-item-icon-height: 20px;
--media-settings-menu-min-width: calc(10 * var(--base));
--media-menu-transform-in: translateY(0) scale(1);
--media-menu-transform-out: translateY(20px) rotate(3deg) scale(1);
padding-block: calc(0.15 * var(--base));
margin-right: 10px;
margin-bottom: 17px;
border-radius: 8px;
z-index: 2;
user-select: none;
}
media-settings-menu-item,
[role='menu']::part(menu-item) {
--media-icon-color: var(--_primary-color);
margin-inline: calc(0.45 * var(--base));
height: calc(1.6 * var(--base));
font-size: calc(0.7 * var(--base));
font-weight: 400;
padding: 0;
padding-left: calc(0.4 * var(--base));
padding-right: calc(0.1 * var(--base));
border-radius: 6px;
text-shadow: none;
}
[slot='submenu']::part(back button) {
font-size: calc(0.7 * var(--base));
}
media-settings-menu-item:hover {
--media-icon-color: #000;
color: #000;
background-color: #fff;
}
media-settings-menu-item:hover [slot='submenu']::part(menu-item),
[slot='submenu']::part(back indicator) {
--media-icon-color: var(--_primary-color);
}
media-settings-menu-item:hover [slot='submenu']::part(menu-item):hover {
--media-icon-color: #000;
color: #000;
background-color: #fff;
}
media-settings-menu-item[submenusize='0'] {
display: none;
}
/* Also hide if only `Auto` is added. */
.quality-settings[submenusize='1'] {
display: none;
}
</style>
<media-settings-menu hidden anchor="auto">
<media-settings-menu-item>
Playback Speed
<media-playback-rate-menu slot="submenu" hidden>
<div slot="title">Playback Speed</div>
</media-playback-rate-menu>
</media-settings-menu-item>
<media-settings-menu-item class="quality-settings">
Quality
<media-rendition-menu slot="submenu" hidden>
<div slot="title">Quality</div>
</media-rendition-menu>
</media-settings-menu-item>
<media-settings-menu-item>
Subtitles/CC
<media-captions-menu slot="submenu" hidden>
<div slot="title">Subtitles/CC</div>
</media-captions-menu>
</media-settings-menu-item>
</media-settings-menu>
<!-- Control Bar -->
<style>
media-control-bar {
position: absolute;
height: calc(2 * var(--base));
line-height: calc(2 * var(--base));
bottom: var(--base);
left: var(--base);
right: var(--base);
}
</style>
<media-control-bar>
<!-- Play/Pause -->
<style>
@keyframes bounce-scale-play {
0% {
transform: scale(0.75, 0.75);
}
50% {
transform: scale(115%, 115%);
}
100% {
transform: scale(1, 1);
}
}
.media-button {
border-radius: 25%;
backdrop-filter: blur(10px) invert(15%) brightness(80%) opacity(0);
-webkit-backdrop-filter: blur(10px) invert(15%) brightness(80%) opacity(0);
transition: backdrop-filter 0.3s, -webkit-backdrop-filter 0.3s, box-shadow 0.3s;
}
.media-button:hover {
/* background-color: rgba(0, 0, 0, 0.05); */
box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 5px;
/* hue-rotate(120deg) */
backdrop-filter: blur(10px) invert(15%) brightness(80%) opacity(1);
-webkit-backdrop-filter: blur(10px) invert(15%) brightness(80%) opacity(1);
transition: backdrop-filter 0.3s, -webkit-backdrop-filter 0.3s;
}
media-play-button #icon-play {
opacity: 0;
transform-box: view-box;
transform-origin: center center;
transform: scale(0.5, 0.5);
transition: all 0.5s;
}
media-play-button[mediapaused] #icon-play {
opacity: 1;
transform: scale(1, 1);
animation: 0.35s bounce-scale-play ease-in-out;
}
@keyframes bounce-pause-left {
0% {
font-size: 10px;
}
50% {
font-size: 3px;
}
100% {
font-size: 4px;
}
}
@keyframes bounce-pause-right {
0% {
font-size: 10px;
transform: translateX(-8px);
}
50% {
font-size: 3px;
transform: translateX(1px);
}
100% {
font-size: 4px;
transform: translateX(0);
}
}
media-play-button #pause-left,
media-play-button #pause-right {
/* Using font-size to animate height because using scale was resulting in unexpected positioning */
font-size: 4px;
opacity: 1;
transform: translateX(0);
transform-box: view-box;
}
media-play-button:not([mediapaused]) #pause-left {
animation: 0.3s bounce-pause-left ease-out;
}
media-play-button:not([mediapaused]) #pause-right {
animation: 0.3s bounce-pause-right ease-out;
}
media-play-button[mediapaused] #pause-left,
media-play-button[mediapaused] #pause-right {
opacity: 0;
font-size: 10px;
}
media-play-button[mediapaused] #pause-right {
transform-origin: right center;
transform: translateX(-8px);
}
</style>
<media-play-button mediapaused class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<!-- <use class="svg-shadow" xlink:href="#icon-play"></use> -->
<g>
<path
id="icon-play"
d="M20.7131 14.6976C21.7208 15.2735 21.7208 16.7265 20.7131 17.3024L12.7442 21.856C11.7442 22.4274 10.5 21.7054 10.5 20.5536L10.5 11.4464C10.5 10.2946 11.7442 9.57257 12.7442 10.144L20.7131 14.6976Z"
/>
</g>
<!-- <use class="svg-shadow" xlink:href="#icon-pause"></use> -->
<g id="icon-pause">
<rect id="pause-left" x="10.5" width="1em" y="10.5" height="11" rx="0.5" />
<rect id="pause-right" x="17.5" width="1em" y="10.5" height="11" rx="0.5" />
</g>
</svg>
</media-play-button>
<!-- Volume/Mute -->
<style>
media-mute-button {
position: relative;
z-index: 1;
}
media-mute-button .muted-path {
transition: clip-path 0.2s ease-out;
}
media-mute-button #muted-path-2 {
transition-delay: 0.2s;
}
media-mute-button .muted-path {
clip-path: inset(0);
}
media-mute-button:not([mediavolumelevel='off']) #muted-path-1 {
clip-path: inset(0 0 100% 0);
}
media-mute-button:not([mediavolumelevel='off']) #muted-path-2 {
clip-path: inset(0 0 100% 0);
}
media-mute-button .muted-path {
opacity: 0;
}
media-mute-button[mediavolumelevel='off'] .muted-path {
opacity: 1;
}
media-mute-button .vol-path {
opacity: 1;
transition: opacity 0.4s;
}
media-mute-button[mediavolumelevel='off'] .vol-path {
opacity: 0;
}
media-mute-button[mediavolumelevel='low'] #vol-high-path,
media-mute-button[mediavolumelevel='medium'] #vol-high-path {
opacity: 0;
}
media-volume-range {
--media-range-track-background: rgba(255, 255, 255, 0.2);
--media-range-thumb-opacity: 0;
}
@keyframes volume-in {
0% {
visibility: hidden;
opacity: 0;
transform: translateY(50%) rotate(1deg);
}
50% {
visibility: visible;
opacity: 1;
transform: rotate(-2deg);
}
100% {
visibility: visible;
opacity: 1;
transform: translateY(0) rotate(0deg);
}
}
@keyframes volume-out {
0% {
visibility: visible;
opacity: 1;
transform: translateY(0) rotate(0deg);
}
50% {
opacity: 1;
transform: rotate(0deg);
}
100% {
visibility: hidden;
opacity: 0;
transform: translateY(50%) rotate(1deg);
}
}
.media-volume-range-wrapper {
opacity: 0;
visibility: hidden;
position: absolute;
top: -100%;
left: calc(2 * var(--base));
width: calc(10 * var(--base));
height: calc(2.5 * var(--base));
transform-origin: center left;
}
media-volume-range {
/*
Hide range and animation until mediavolume attribute is set.
`visibility` didn't work, hovering over media-volume-range-wrapper
caused it to show. Should require mute-button:hover.
*/
opacity: 0;
transition: opacity 0s 1s;
width: calc(10 * var(--base));
height: var(--base);
padding: 0;
border-radius: calc(0.25 * var(--base));
overflow: hidden;
background: rgba(0, 0, 0, 0.2);
--media-range-bar-color: var(--media-accent-color);
--media-range-padding-left: 0;
--media-range-padding-right: 0;
--media-range-track-width: calc(10 * var(--base));
--media-range-track-height: var(--base);
--media-range-track-border-radius: calc(0.25 * var(--base));
--media-range-track-backdrop-filter: blur(10px) brightness(80%);
/* This makes zero volume still show some of the bar.
I can't make the bar have curved corners otherwise though. */
--media-range-thumb-width: var(--base);
--media-range-thumb-border-radius: calc(0.25 * var(--base));
/* The Sutro design has a gradient like this, but not sure I like it */
/* --media-range-thumb-box-shadow: 10px 0px 20px rgba(255, 255, 255, 0.5); */
}
media-volume-range[mediavolume] {
opacity: 1;
}
[keyboardcontrol] media-volume-range:focus {
/* TODO: This appears to be creating a think outline */
outline: 1px solid rgba(27, 127, 204, 0.9);
}
media-mute-button:hover + .media-volume-range-wrapper,
media-mute-button:focus + .media-volume-range-wrapper,
media-mute-button:focus-within + .media-volume-range-wrapper,
.media-volume-range-wrapper:hover,
.media-volume-range-wrapper:focus,
.media-volume-range-wrapper:focus-within {
animation: 0.3s volume-in forwards ease-out;
}
.media-volume-range-wrapper:not(:hover, :focus-within) {
animation: 0.3s volume-out ease-out;
}
/* When keyboard navigating the volume range and wrapper need to always be visible
otherwise focus state can't land on it. This is ok when keyboard navigating because
the hovering issues aren't a concern, unless you happen to be keyboard AND mouse navigating.
*/
[keyboardcontrol] .media-volume-range-wrapper,
[keyboardcontrol] .media-volume-range-wrapper:focus-within,
[keyboardcontrol] .media-volume-range-wrapper:focus-within media-volume-range {
visibility: visible;
}
</style>
<media-mute-button class="media-button">
<use class="svg-shadow" xlink:href="#vol-paths"></use>
<svg slot="icon" viewBox="0 0 32 32">
<g id="vol-paths">
<path
id="speaker-path"
d="M16.5 20.486v-8.972c0-1.537-2.037-2.08-2.802-.745l-1.026 1.79a2.5 2.5 0 0 1-.8.85l-1.194.78A1.5 1.5 0 0 0 10 15.446v1.11c0 .506.255.978.678 1.255l1.194.782a2.5 2.5 0 0 1 .8.849l1.026 1.79c.765 1.334 2.802.792 2.802-.745Z"
/>
<path
id="vol-low-path"
class="vol-path"
d="M18.5 18C19.6046 18 20.5 17.1046 20.5 16C20.5 14.8954 19.6046 14 18.5 14"
/>
<path
id="vol-high-path"
class="vol-path"
d="M18 21C20.7614 21 23 18.7614 23 16C23 13.2386 20.7614 11 18 11"
/>
<path id="muted-path-1" class="muted-path" d="M23 18L19 14" />
<path id="muted-path-2" class="muted-path" d="M23 14L19 18" />
</g>
</svg>
</media-mute-button>
<div class="media-volume-range-wrapper">
<media-volume-range></media-volume-range>
</div>
<!-- Time Display -->
<style>
media-time-display {
position: relative;
z-index: 1;
padding: calc(0.5 * var(--base));
font-size: calc(0.7 * var(--base));
border-radius: calc(0.5 * var(--base));
}
media-controller[breakpointmd] media-time-display:not([showduration]) {
display: none;
}
media-controller:not([breakpointmd]) media-time-display[showduration] {
display: none;
}
</style>
<media-time-display></media-time-display>
<media-time-display showduration></media-time-display>
<!-- Time Range / Progress Bar -->
<style>
media-time-range {
height: calc(2 * var(--base));
border-radius: calc(0.25 * var(--base));
--media-range-track-transition: height 0.2s linear;
--media-range-track-backdrop-filter: invert(10%) blur(5px) brightness(110%);
--media-range-track-background: rgba(255, 255, 255, 0.2);
--media-range-track-pointer-background: rgba(255, 255, 255, 0.5);
--media-range-track-border-radius: calc(0.25 * var(--base));
--media-time-range-buffered-color: rgba(255, 255, 255, 0.4);
--media-range-bar-color: var(--media-accent-color);
--media-range-thumb-background: var(--media-accent-color);
--media-range-thumb-transition: opacity 0.1s linear;
--media-range-thumb-opacity: 0;
--media-preview-thumbnail-border: calc(0.125 * var(--base)) solid #fff;
--media-preview-thumbnail-border-radius: calc(0.5 * var(--base));
--media-preview-thumbnail-min-width: calc(8 * var(--base));
--media-preview-thumbnail-max-width: calc(10 * var(--base));
--media-preview-thumbnail-min-height: calc(5 * var(--base));
--media-preview-thumbnail-max-height: calc(7 * var(--base));
--media-preview-time-margin: 0 0 -15px;
}
media-time-range:hover {
--media-range-thumb-opacity: 1;
--media-range-track-height: calc(0.25 * var(--base));
}
media-preview-time-display {
font-size: calc(0.7 * var(--base));
line-height: 1.6;
}
</style>
<media-time-range>
<media-preview-thumbnail slot="preview"></media-preview-thumbnail>
<media-preview-time-display slot="preview"></media-preview-time-display>
</media-time-range>
<!-- Subtitles/CC Button -->
<style>
media-captions-button {
position: relative;
}
media-controller:not([breakpointmd]) media-captions-button {
display: none;
}
media-captions-button svg :is(path, rect) {
stroke: none;
fill: var(--_primary-color);
}
/* Disble the captions button when no subtitles are available */
media-captions-button:not([mediasubtitleslist]) svg {
opacity: 0.3;
}
media-captions-button #cc-underline {
opacity: 1;
}
media-captions-button[mediasubtitleslist][aria-checked='true'] #cc-underline {
opacity: 1;
}
media-captions-button #cc-underline {
transition: clip-path 0.15s ease-out;
}
media-captions-button #cc-underline {
clip-path: inset(0 100% 0 0);
}
media-captions-button[aria-checked='true'] #cc-underline {
clip-path: inset(0 0 0 0);
}
</style>
<media-captions-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#cc-icon"></use>
<g id="cc-icon">
<path
class="cc-c"
d="M15.6634 14.3574H14.5636C14.4985 14.0523 14.3847 13.7842 14.2221 13.5532C14.0624 13.3222 13.8673 13.1283 13.6367 12.9715C13.409 12.8118 13.1562 12.692 12.8783 12.6122C12.6004 12.5323 12.3107 12.4924 12.0091 12.4924C11.4592 12.4924 10.961 12.6264 10.5146 12.8945C10.0711 13.1625 9.71776 13.5575 9.45463 14.0794C9.19445 14.6012 9.06436 15.2414 9.06436 16C9.06436 16.7586 9.19445 17.3988 9.45463 17.9206C9.71776 18.4425 10.0711 18.8375 10.5146 19.1055C10.961 19.3736 11.4592 19.5076 12.0091 19.5076C12.3107 19.5076 12.6004 19.4677 12.8783 19.3878C13.1562 19.308 13.409 19.1896 13.6367 19.0328C13.8673 18.8731 14.0624 18.6778 14.2221 18.4468C14.3847 18.2129 14.4985 17.9449 14.5636 17.6426H15.6634C15.5806 18.0903 15.4298 18.491 15.2111 18.8446C14.9923 19.1982 14.7203 19.499 14.3951 19.7471C14.0698 19.9924 13.7047 20.1792 13.2996 20.3075C12.8976 20.4358 12.4674 20.5 12.0091 20.5C11.2345 20.5 10.5456 20.3175 9.94246 19.9525C9.33932 19.5875 8.8648 19.0684 8.51888 18.3954C8.17296 17.7224 8 16.924 8 16C8 15.076 8.17296 14.2776 8.51888 13.6046C8.8648 12.9316 9.33932 12.4125 9.94246 12.0475C10.5456 11.6825 11.2345 11.5 12.0091 11.5C12.4674 11.5 12.8976 11.5642 13.2996 11.6925C13.7047 11.8208 14.0698 12.009 14.3951 12.2571C14.7203 12.5024 14.9923 12.8018 15.2111 13.1554C15.4298 13.5062 15.5806 13.9068 15.6634 14.3574Z"
/>
<path
class="cc-c"
d="M24 14.3574H22.9002C22.8351 14.0523 22.7213 13.7842 22.5587 13.5532C22.399 13.3222 22.2039 13.1283 21.9733 12.9715C21.7456 12.8118 21.4928 12.692 21.2149 12.6122C20.937 12.5323 20.6473 12.4924 20.3457 12.4924C19.7958 12.4924 19.2976 12.6264 18.8511 12.8945C18.4077 13.1625 18.0543 13.5575 17.7912 14.0794C17.531 14.6012 17.4009 15.2414 17.4009 16C17.4009 16.7586 17.531 17.3988 17.7912 17.9206C18.0543 18.4425 18.4077 18.8375 18.8511 19.1055C19.2976 19.3736 19.7958 19.5076 20.3457 19.5076C20.6473 19.5076 20.937 19.4677 21.2149 19.3878C21.4928 19.308 21.7456 19.1896 21.9733 19.0328C22.2039 18.8731 22.399 18.6778 22.5587 18.4468C22.7213 18.2129 22.8351 17.9449 22.9002 17.6426H24C23.9172 18.0903 23.7664 18.491 23.5476 18.8446C23.3289 19.1982 23.0569 19.499 22.7316 19.7471C22.4064 19.9924 22.0413 20.1792 21.6362 20.3075C21.2341 20.4358 20.804 20.5 20.3457 20.5C19.5711 20.5 18.8822 20.3175 18.279 19.9525C17.6759 19.5875 17.2014 19.0684 16.8555 18.3954C16.5095 17.7224 16.3366 16.924 16.3366 16C16.3366 15.076 16.5095 14.2776 16.8555 13.6046C17.2014 12.9316 17.6759 12.4125 18.279 12.0475C18.8822 11.6825 19.5711 11.5 20.3457 11.5C20.804 11.5 21.2341 11.5642 21.6362 11.6925C22.0413 11.8208 22.4064 12.009 22.7316 12.2571C23.0569 12.5024 23.3289 12.8018 23.5476 13.1554C23.7664 13.5062 23.9172 13.9068 24 14.3574Z"
/>
<rect id="cc-underline" x="8" y="23" width="16" height="1" rx="0.5" />
</g>
</svg>
</media-captions-button>
<!-- Settings Menu Button -->
<style>
media-settings-menu-button svg {
transition: transform 0.1s cubic-bezier(0.4, 0, 1, 1);
transform: rotateZ(0deg);
}
media-settings-menu-button[aria-expanded='true'] svg {
transform: rotateZ(30deg);
}
</style>
<media-settings-menu-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#settings-icon"></use>
<g id="settings-icon">
<path
d="M16 18C17.1046 18 18 17.1046 18 16C18 14.8954 17.1046 14 16 14C14.8954 14 14 14.8954 14 16C14 17.1046 14.8954 18 16 18Z"
/>
<path
d="M21.0176 13.0362L20.9715 12.9531C20.8445 12.7239 20.7797 12.4629 20.784 12.1982L20.8049 10.8997C20.8092 10.6343 20.675 10.3874 20.4545 10.2549L18.5385 9.10362C18.3186 8.97143 18.0472 8.9738 17.8293 9.10981L16.7658 9.77382C16.5485 9.90953 16.2999 9.98121 16.0465 9.98121H15.9543C15.7004 9.98121 15.4513 9.90922 15.2336 9.77295L14.1652 9.10413C13.9467 8.96728 13.674 8.96518 13.4535 9.09864L11.5436 10.2545C11.3242 10.3873 11.1908 10.6336 11.1951 10.8981L11.216 12.1982C11.2203 12.4629 11.1555 12.7239 11.0285 12.9531L10.9831 13.0351C10.856 13.2645 10.6715 13.4535 10.4493 13.5819L9.36075 14.2109C9.13763 14.3398 8.99942 14.5851 9 14.8511L9.00501 17.152C9.00559 17.4163 9.1432 17.6597 9.36476 17.7883L10.4481 18.4167C10.671 18.546 10.8559 18.7364 10.9826 18.9673L11.0313 19.0559C11.1565 19.284 11.2203 19.5431 11.2161 19.8059L11.1951 21.1003C11.1908 21.3657 11.325 21.6126 11.5456 21.7452L13.4615 22.8964C13.6814 23.0286 13.9528 23.0262 14.1707 22.8902L15.2342 22.2262C15.4515 22.0905 15.7001 22.0188 15.9535 22.0188H16.0457C16.2996 22.0188 16.5487 22.0908 16.7664 22.227L17.8348 22.8959C18.0534 23.0327 18.326 23.0348 18.5465 22.9014L20.4564 21.7455C20.6758 21.6127 20.8092 21.3664 20.8049 21.1019L20.784 19.8018C20.7797 19.5371 20.8445 19.2761 20.9715 19.0469L21.0169 18.9649C21.144 18.7355 21.3285 18.5465 21.5507 18.4181L22.6393 17.7891C22.8624 17.6602 23.0006 17.4149 23 17.1489L22.995 14.848C22.9944 14.5837 22.8568 14.3403 22.6352 14.2117L21.5493 13.5818C21.328 13.4534 21.1442 13.2649 21.0176 13.0362Z"
/>
</g>
</svg>
</media-settings-menu-button>
<!-- PIP/Mini Player Button -->
<style>
media-controller:not([breakpointmd]) media-pip-button {
display: none;
}
</style>
<media-pip-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#pip-icon"></use>
<g id="pip-icon">
<path
d="M12 22H9.77778C9.34822 22 9 21.6162 9 21.1429V10.8571C9 10.3838 9.34822 10 9.77778 10L22.2222 10C22.6518 10 23 10.3838 23 10.8571V12.5714"
/>
<path
d="M15 21.5714V16.4286C15 16.1919 15.199 16 15.4444 16H22.5556C22.801 16 23 16.1919 23 16.4286V17V21.5714C23 21.8081 22.801 22 22.5556 22H20.3333H17.6667H15.4444C15.199 22 15 21.8081 15 21.5714Z"
/>
</g>
</svg>
</media-pip-button>
<!-- Cast Button -->
<media-cast-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#cast-icon"></use>
<g id="cast-icon">
<path
d="M18.5 21.833h4.167c.46 0 .833-.373.833-.833V11a.833.833 0 0 0-.833-.833H9.333A.833.833 0 0 0 8.5 11v1.111m0 8.056c.92 0 1.667.746 1.667 1.666M8.5 17.667a4.167 4.167 0 0 1 4.167 4.166"
/>
<path d="M8.5 15.167a6.667 6.667 0 0 1 6.667 6.666" />
</g>
</svg>
</media-cast-button>
<!-- Fullscreen Button -->
<style>
/* Having trouble getting @property to work in the shadow dom
to clean this up. Like https://codepen.io/luwes/pen/oNRyZyx */
media-fullscreen-button .fs-arrow {
translate: 0% 0%;
}
media-fullscreen-button:hover .fs-arrow {
animation: 0.35s up-left-bounce cubic-bezier(0.34, 1.56, 0.64, 1);
}
media-fullscreen-button:hover #fs-enter-top,
media-fullscreen-button:hover #fs-exit-bottom {
animation-name: up-right-bounce;
}
media-fullscreen-button:hover #fs-enter-bottom,
media-fullscreen-button:hover #fs-exit-top {
animation-name: down-left-bounce;
}
@keyframes up-left-bounce {
0% {
translate: 0 0;
}
50% {
translate: -4% -4%;
}
}
@keyframes up-right-bounce {
0% {
translate: 0 0;
}
50% {
translate: 4% -4%;
}
}
@keyframes down-left-bounce {
0% {
translate: 0 0;
}
50% {
translate: -4% 4%;
}
}
@keyframes down-right-bounce {
0% {
translate: 0 0;
}
50% {
translate: 4% 4%;
}
}
</style>
<media-fullscreen-button class="media-button">
<svg slot="enter" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#fs-enter-paths"></use>
<g id="fs-enter-paths">
<g id="fs-enter-top" class="fs-arrow">
<path d="M18 10H22V14" />
<path d="M22 10L18 14" />
</g>
<g id="fs-enter-bottom" class="fs-arrow">
<path d="M14 22L10 22V18" />
<path d="M10 22L14 18" />
</g>
</g>
</svg>
<svg slot="exit" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#fs-exit-paths"></use>
<g id="fs-exit-paths">
<g id="fs-exit-top" class="fs-arrow">
<path d="M22 14H18V10" />
<path d="M22 10L18 14" />
</g>
<g id="fs-exit-bottom" class="fs-arrow">
<path d="M10 18L14 18V22" />
<path d="M14 18L10 22" />
</g>
</g>
</svg>
</media-fullscreen-button>
</media-control-bar>
</media-controller>

View File

@@ -0,0 +1,793 @@
/*
<media-theme-sutro>
<video
slot="media"
src="https://stream.mux.com/fXNzVtmtWuyz00xnSrJg4OJH6PyNo6D02UzmgeKGkP5YQ/high.mp4"
></video>
</media-theme-sutro>
*/
import 'media-chrome';
import { globalThis } from 'media-chrome/dist/utils/server-safe-globals.js';
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
import 'media-chrome/dist/menu/index.js';
const template = globalThis.document?.createElement?.('template');
if (template) {
template.innerHTML = /*html*/`
<!-- Sutro -->
<style>
:host {
--_primary-color: var(--media-primary-color, #fff);
--_secondary-color: var(--media-secondary-color, transparent);
--_accent-color: var(--media-accent-color, #fff);
}
media-controller {
--base: 18px;
font-size: calc(0.75 * var(--base));
font-family: Roboto, Arial, sans-serif;
--media-font-family: Roboto, helvetica neue, segoe ui, arial, sans-serif;
-webkit-font-smoothing: antialiased;
--media-primary-color: #fff;
--media-secondary-color: transparent;
--media-menu-background: rgba(28, 28, 28, 0.6);
--media-text-color: var(--_primary-color);
--media-control-hover-background: var(--media-secondary-color);
--media-range-track-height: calc(0.125 * var(--base));
--media-range-thumb-height: var(--base);
--media-range-thumb-width: var(--base);
--media-range-thumb-border-radius: var(--base);
--media-control-height: calc(2 * var(--base));
--media-tooltip-display: none;
}
media-controller[breakpointmd] {
--base: 20px;
}
/* The biggest size controller is tied to going fullscreen
instead of a player width */
media-controller[mediaisfullscreen] {
--base: 24px;
}
.media-button {
--media-control-hover-background: var(--_secondary-color);
position: relative;
padding: 0;
opacity: 0.9;
transition: opacity 0.1s cubic-bezier(0.4, 0, 1, 1);
}
.media-button svg {
fill: none;
stroke: var(--_primary-color);
stroke-width: 1;
stroke-linecap: 'round';
stroke-linejoin: 'round';
}
svg .svg-shadow {
stroke: #000;
stroke-opacity: 0.15;
stroke-width: 2px;
fill: none;
}
</style>
<media-controller
breakpoints="md:480"
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<!-- Controls Gradient -->
<style>
.media-gradient-bottom {
--gradient-steps: hsl(0 0% 0% / 0) 0%, hsl(0 0% 0% / 0.013) 8.1%, hsl(0 0% 0% / 0.049) 15.5%,
hsl(0 0% 0% / 0.104) 22.5%, hsl(0 0% 0% / 0.175) 29%, hsl(0 0% 0% / 0.259) 35.3%, hsl(0 0% 0% / 0.352) 41.2%,
hsl(0 0% 0% / 0.45) 47.1%, hsl(0 0% 0% / 0.55) 52.9%, hsl(0 0% 0% / 0.648) 58.8%, hsl(0 0% 0% / 0.741) 64.7%,
hsl(0 0% 0% / 0.825) 71%, hsl(0 0% 0% / 0.896) 77.5%, hsl(0 0% 0% / 0.951) 84.5%, hsl(0 0% 0% / 0.987) 91.9%,
hsl(0 0% 0%) 100%;
position: absolute;
bottom: 0;
opacity: 0.7;
width: 100%;
height: calc(8 * var(--base));
background: linear-gradient(to bottom, var(--gradient-steps));
pointer-events: none;
}
</style>
<div class="media-gradient-bottom"></div>
<!-- Settings Menu -->
<style>
media-settings-menu {
--media-menu-icon-height: 20px;
--media-menu-item-icon-height: 20px;
--media-settings-menu-min-width: calc(10 * var(--base));
--media-menu-transform-in: translateY(0) scale(1);
--media-menu-transform-out: translateY(20px) rotate(3deg) scale(1);
padding-block: calc(0.15 * var(--base));
margin-right: 10px;
margin-bottom: 17px;
border-radius: 8px;
z-index: 2;
user-select: none;
}
media-settings-menu-item,
[role='menu']::part(menu-item) {
--media-icon-color: var(--_primary-color);
margin-inline: calc(0.45 * var(--base));
height: calc(1.6 * var(--base));
font-size: calc(0.7 * var(--base));
font-weight: 400;
padding: 0;
padding-left: calc(0.4 * var(--base));
padding-right: calc(0.1 * var(--base));
border-radius: 6px;
text-shadow: none;
}
[slot='submenu']::part(back button) {
font-size: calc(0.7 * var(--base));
}
media-settings-menu-item:hover {
--media-icon-color: #000;
color: #000;
background-color: #fff;
}
media-settings-menu-item:hover [slot='submenu']::part(menu-item),
[slot='submenu']::part(back indicator) {
--media-icon-color: var(--_primary-color);
}
media-settings-menu-item:hover [slot='submenu']::part(menu-item):hover {
--media-icon-color: #000;
color: #000;
background-color: #fff;
}
media-settings-menu-item[submenusize='0'] {
display: none;
}
/* Also hide if only `Auto` is added. */
.quality-settings[submenusize='1'] {
display: none;
}
</style>
<media-settings-menu hidden anchor="auto">
<media-settings-menu-item>
Playback Speed
<media-playback-rate-menu slot="submenu" hidden>
<div slot="title">Playback Speed</div>
</media-playback-rate-menu>
</media-settings-menu-item>
<media-settings-menu-item class="quality-settings">
Quality
<media-rendition-menu slot="submenu" hidden>
<div slot="title">Quality</div>
</media-rendition-menu>
</media-settings-menu-item>
<media-settings-menu-item>
Subtitles/CC
<media-captions-menu slot="submenu" hidden>
<div slot="title">Subtitles/CC</div>
</media-captions-menu>
</media-settings-menu-item>
</media-settings-menu>
<!-- Control Bar -->
<style>
media-control-bar {
position: absolute;
height: calc(2 * var(--base));
line-height: calc(2 * var(--base));
bottom: var(--base);
left: var(--base);
right: var(--base);
}
</style>
<media-control-bar>
<!-- Play/Pause -->
<style>
@keyframes bounce-scale-play {
0% {
transform: scale(0.75, 0.75);
}
50% {
transform: scale(115%, 115%);
}
100% {
transform: scale(1, 1);
}
}
.media-button {
border-radius: 25%;
backdrop-filter: blur(10px) invert(15%) brightness(80%) opacity(0);
-webkit-backdrop-filter: blur(10px) invert(15%) brightness(80%) opacity(0);
transition: backdrop-filter 0.3s, -webkit-backdrop-filter 0.3s, box-shadow 0.3s;
}
.media-button:hover {
/* background-color: rgba(0, 0, 0, 0.05); */
box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 5px;
/* hue-rotate(120deg) */
backdrop-filter: blur(10px) invert(15%) brightness(80%) opacity(1);
-webkit-backdrop-filter: blur(10px) invert(15%) brightness(80%) opacity(1);
transition: backdrop-filter 0.3s, -webkit-backdrop-filter 0.3s;
}
media-play-button #icon-play {
opacity: 0;
transform-box: view-box;
transform-origin: center center;
transform: scale(0.5, 0.5);
transition: all 0.5s;
}
media-play-button[mediapaused] #icon-play {
opacity: 1;
transform: scale(1, 1);
animation: 0.35s bounce-scale-play ease-in-out;
}
@keyframes bounce-pause-left {
0% {
font-size: 10px;
}
50% {
font-size: 3px;
}
100% {
font-size: 4px;
}
}
@keyframes bounce-pause-right {
0% {
font-size: 10px;
transform: translateX(-8px);
}
50% {
font-size: 3px;
transform: translateX(1px);
}
100% {
font-size: 4px;
transform: translateX(0);
}
}
media-play-button #pause-left,
media-play-button #pause-right {
/* Using font-size to animate height because using scale was resulting in unexpected positioning */
font-size: 4px;
opacity: 1;
transform: translateX(0);
transform-box: view-box;
}
media-play-button:not([mediapaused]) #pause-left {
animation: 0.3s bounce-pause-left ease-out;
}
media-play-button:not([mediapaused]) #pause-right {
animation: 0.3s bounce-pause-right ease-out;
}
media-play-button[mediapaused] #pause-left,
media-play-button[mediapaused] #pause-right {
opacity: 0;
font-size: 10px;
}
media-play-button[mediapaused] #pause-right {
transform-origin: right center;
transform: translateX(-8px);
}
</style>
<media-play-button mediapaused class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<!-- <use class="svg-shadow" xlink:href="#icon-play"></use> -->
<g>
<path
id="icon-play"
d="M20.7131 14.6976C21.7208 15.2735 21.7208 16.7265 20.7131 17.3024L12.7442 21.856C11.7442 22.4274 10.5 21.7054 10.5 20.5536L10.5 11.4464C10.5 10.2946 11.7442 9.57257 12.7442 10.144L20.7131 14.6976Z"
/>
</g>
<!-- <use class="svg-shadow" xlink:href="#icon-pause"></use> -->
<g id="icon-pause">
<rect id="pause-left" x="10.5" width="1em" y="10.5" height="11" rx="0.5" />
<rect id="pause-right" x="17.5" width="1em" y="10.5" height="11" rx="0.5" />
</g>
</svg>
</media-play-button>
<!-- Volume/Mute -->
<style>
media-mute-button {
position: relative;
z-index: 1;
}
media-mute-button .muted-path {
transition: clip-path 0.2s ease-out;
}
media-mute-button #muted-path-2 {
transition-delay: 0.2s;
}
media-mute-button .muted-path {
clip-path: inset(0);
}
media-mute-button:not([mediavolumelevel='off']) #muted-path-1 {
clip-path: inset(0 0 100% 0);
}
media-mute-button:not([mediavolumelevel='off']) #muted-path-2 {
clip-path: inset(0 0 100% 0);
}
media-mute-button .muted-path {
opacity: 0;
}
media-mute-button[mediavolumelevel='off'] .muted-path {
opacity: 1;
}
media-mute-button .vol-path {
opacity: 1;
transition: opacity 0.4s;
}
media-mute-button[mediavolumelevel='off'] .vol-path {
opacity: 0;
}
media-mute-button[mediavolumelevel='low'] #vol-high-path,
media-mute-button[mediavolumelevel='medium'] #vol-high-path {
opacity: 0;
}
media-volume-range {
--media-range-track-background: rgba(255, 255, 255, 0.2);
--media-range-thumb-opacity: 0;
}
@keyframes volume-in {
0% {
visibility: hidden;
opacity: 0;
transform: translateY(50%) rotate(1deg);
}
50% {
visibility: visible;
opacity: 1;
transform: rotate(-2deg);
}
100% {
visibility: visible;
opacity: 1;
transform: translateY(0) rotate(0deg);
}
}
@keyframes volume-out {
0% {
visibility: visible;
opacity: 1;
transform: translateY(0) rotate(0deg);
}
50% {
opacity: 1;
transform: rotate(0deg);
}
100% {
visibility: hidden;
opacity: 0;
transform: translateY(50%) rotate(1deg);
}
}
.media-volume-range-wrapper {
opacity: 0;
visibility: hidden;
position: absolute;
top: -100%;
left: calc(2 * var(--base));
width: calc(10 * var(--base));
height: calc(2.5 * var(--base));
transform-origin: center left;
}
media-volume-range {
/*
Hide range and animation until mediavolume attribute is set.
`visibility` didn't work, hovering over media-volume-range-wrapper
caused it to show. Should require mute-button:hover.
*/
opacity: 0;
transition: opacity 0s 1s;
width: calc(10 * var(--base));
height: var(--base);
padding: 0;
border-radius: calc(0.25 * var(--base));
overflow: hidden;
background: rgba(0, 0, 0, 0.2);
--media-range-bar-color: var(--media-accent-color);
--media-range-padding-left: 0;
--media-range-padding-right: 0;
--media-range-track-width: calc(10 * var(--base));
--media-range-track-height: var(--base);
--media-range-track-border-radius: calc(0.25 * var(--base));
--media-range-track-backdrop-filter: blur(10px) brightness(80%);
/* This makes zero volume still show some of the bar.
I can't make the bar have curved corners otherwise though. */
--media-range-thumb-width: var(--base);
--media-range-thumb-border-radius: calc(0.25 * var(--base));
/* The Sutro design has a gradient like this, but not sure I like it */
/* --media-range-thumb-box-shadow: 10px 0px 20px rgba(255, 255, 255, 0.5); */
}
media-volume-range[mediavolume] {
opacity: 1;
}
[keyboardcontrol] media-volume-range:focus {
/* TODO: This appears to be creating a think outline */
outline: 1px solid rgba(27, 127, 204, 0.9);
}
media-mute-button:hover + .media-volume-range-wrapper,
media-mute-button:focus + .media-volume-range-wrapper,
media-mute-button:focus-within + .media-volume-range-wrapper,
.media-volume-range-wrapper:hover,
.media-volume-range-wrapper:focus,
.media-volume-range-wrapper:focus-within {
animation: 0.3s volume-in forwards ease-out;
}
.media-volume-range-wrapper:not(:hover, :focus-within) {
animation: 0.3s volume-out ease-out;
}
/* When keyboard navigating the volume range and wrapper need to always be visible
otherwise focus state can't land on it. This is ok when keyboard navigating because
the hovering issues aren't a concern, unless you happen to be keyboard AND mouse navigating.
*/
[keyboardcontrol] .media-volume-range-wrapper,
[keyboardcontrol] .media-volume-range-wrapper:focus-within,
[keyboardcontrol] .media-volume-range-wrapper:focus-within media-volume-range {
visibility: visible;
}
</style>
<media-mute-button class="media-button">
<use class="svg-shadow" xlink:href="#vol-paths"></use>
<svg slot="icon" viewBox="0 0 32 32">
<g id="vol-paths">
<path
id="speaker-path"
d="M16.5 20.486v-8.972c0-1.537-2.037-2.08-2.802-.745l-1.026 1.79a2.5 2.5 0 0 1-.8.85l-1.194.78A1.5 1.5 0 0 0 10 15.446v1.11c0 .506.255.978.678 1.255l1.194.782a2.5 2.5 0 0 1 .8.849l1.026 1.79c.765 1.334 2.802.792 2.802-.745Z"
/>
<path
id="vol-low-path"
class="vol-path"
d="M18.5 18C19.6046 18 20.5 17.1046 20.5 16C20.5 14.8954 19.6046 14 18.5 14"
/>
<path
id="vol-high-path"
class="vol-path"
d="M18 21C20.7614 21 23 18.7614 23 16C23 13.2386 20.7614 11 18 11"
/>
<path id="muted-path-1" class="muted-path" d="M23 18L19 14" />
<path id="muted-path-2" class="muted-path" d="M23 14L19 18" />
</g>
</svg>
</media-mute-button>
<div class="media-volume-range-wrapper">
<media-volume-range></media-volume-range>
</div>
<!-- Time Display -->
<style>
media-time-display {
position: relative;
z-index: 1;
padding: calc(0.5 * var(--base));
font-size: calc(0.7 * var(--base));
border-radius: calc(0.5 * var(--base));
}
media-controller[breakpointmd] media-time-display:not([showduration]) {
display: none;
}
media-controller:not([breakpointmd]) media-time-display[showduration] {
display: none;
}
</style>
<media-time-display></media-time-display>
<media-time-display showduration></media-time-display>
<!-- Time Range / Progress Bar -->
<style>
media-time-range {
height: calc(2 * var(--base));
border-radius: calc(0.25 * var(--base));
--media-range-track-transition: height 0.2s linear;
--media-range-track-backdrop-filter: invert(10%) blur(5px) brightness(110%);
--media-range-track-background: rgba(255, 255, 255, 0.2);
--media-range-track-pointer-background: rgba(255, 255, 255, 0.5);
--media-range-track-border-radius: calc(0.25 * var(--base));
--media-time-range-buffered-color: rgba(255, 255, 255, 0.4);
--media-range-bar-color: var(--media-accent-color);
--media-range-thumb-background: var(--media-accent-color);
--media-range-thumb-transition: opacity 0.1s linear;
--media-range-thumb-opacity: 0;
--media-preview-thumbnail-border: calc(0.125 * var(--base)) solid #fff;
--media-preview-thumbnail-border-radius: calc(0.5 * var(--base));
--media-preview-thumbnail-min-width: calc(8 * var(--base));
--media-preview-thumbnail-max-width: calc(10 * var(--base));
--media-preview-thumbnail-min-height: calc(5 * var(--base));
--media-preview-thumbnail-max-height: calc(7 * var(--base));
--media-preview-time-margin: 0 0 -15px;
}
media-time-range:hover {
--media-range-thumb-opacity: 1;
--media-range-track-height: calc(0.25 * var(--base));
}
media-preview-time-display {
font-size: calc(0.7 * var(--base));
line-height: 1.6;
}
</style>
<media-time-range>
<media-preview-thumbnail slot="preview"></media-preview-thumbnail>
<media-preview-time-display slot="preview"></media-preview-time-display>
</media-time-range>
<!-- Subtitles/CC Button -->
<style>
media-captions-button {
position: relative;
}
media-controller:not([breakpointmd]) media-captions-button {
display: none;
}
media-captions-button svg :is(path, rect) {
stroke: none;
fill: var(--_primary-color);
}
/* Disble the captions button when no subtitles are available */
media-captions-button:not([mediasubtitleslist]) svg {
opacity: 0.3;
}
media-captions-button #cc-underline {
opacity: 1;
}
media-captions-button[mediasubtitleslist][aria-checked='true'] #cc-underline {
opacity: 1;
}
media-captions-button #cc-underline {
transition: clip-path 0.15s ease-out;
}
media-captions-button #cc-underline {
clip-path: inset(0 100% 0 0);
}
media-captions-button[aria-checked='true'] #cc-underline {
clip-path: inset(0 0 0 0);
}
</style>
<media-captions-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#cc-icon"></use>
<g id="cc-icon">
<path
class="cc-c"
d="M15.6634 14.3574H14.5636C14.4985 14.0523 14.3847 13.7842 14.2221 13.5532C14.0624 13.3222 13.8673 13.1283 13.6367 12.9715C13.409 12.8118 13.1562 12.692 12.8783 12.6122C12.6004 12.5323 12.3107 12.4924 12.0091 12.4924C11.4592 12.4924 10.961 12.6264 10.5146 12.8945C10.0711 13.1625 9.71776 13.5575 9.45463 14.0794C9.19445 14.6012 9.06436 15.2414 9.06436 16C9.06436 16.7586 9.19445 17.3988 9.45463 17.9206C9.71776 18.4425 10.0711 18.8375 10.5146 19.1055C10.961 19.3736 11.4592 19.5076 12.0091 19.5076C12.3107 19.5076 12.6004 19.4677 12.8783 19.3878C13.1562 19.308 13.409 19.1896 13.6367 19.0328C13.8673 18.8731 14.0624 18.6778 14.2221 18.4468C14.3847 18.2129 14.4985 17.9449 14.5636 17.6426H15.6634C15.5806 18.0903 15.4298 18.491 15.2111 18.8446C14.9923 19.1982 14.7203 19.499 14.3951 19.7471C14.0698 19.9924 13.7047 20.1792 13.2996 20.3075C12.8976 20.4358 12.4674 20.5 12.0091 20.5C11.2345 20.5 10.5456 20.3175 9.94246 19.9525C9.33932 19.5875 8.8648 19.0684 8.51888 18.3954C8.17296 17.7224 8 16.924 8 16C8 15.076 8.17296 14.2776 8.51888 13.6046C8.8648 12.9316 9.33932 12.4125 9.94246 12.0475C10.5456 11.6825 11.2345 11.5 12.0091 11.5C12.4674 11.5 12.8976 11.5642 13.2996 11.6925C13.7047 11.8208 14.0698 12.009 14.3951 12.2571C14.7203 12.5024 14.9923 12.8018 15.2111 13.1554C15.4298 13.5062 15.5806 13.9068 15.6634 14.3574Z"
/>
<path
class="cc-c"
d="M24 14.3574H22.9002C22.8351 14.0523 22.7213 13.7842 22.5587 13.5532C22.399 13.3222 22.2039 13.1283 21.9733 12.9715C21.7456 12.8118 21.4928 12.692 21.2149 12.6122C20.937 12.5323 20.6473 12.4924 20.3457 12.4924C19.7958 12.4924 19.2976 12.6264 18.8511 12.8945C18.4077 13.1625 18.0543 13.5575 17.7912 14.0794C17.531 14.6012 17.4009 15.2414 17.4009 16C17.4009 16.7586 17.531 17.3988 17.7912 17.9206C18.0543 18.4425 18.4077 18.8375 18.8511 19.1055C19.2976 19.3736 19.7958 19.5076 20.3457 19.5076C20.6473 19.5076 20.937 19.4677 21.2149 19.3878C21.4928 19.308 21.7456 19.1896 21.9733 19.0328C22.2039 18.8731 22.399 18.6778 22.5587 18.4468C22.7213 18.2129 22.8351 17.9449 22.9002 17.6426H24C23.9172 18.0903 23.7664 18.491 23.5476 18.8446C23.3289 19.1982 23.0569 19.499 22.7316 19.7471C22.4064 19.9924 22.0413 20.1792 21.6362 20.3075C21.2341 20.4358 20.804 20.5 20.3457 20.5C19.5711 20.5 18.8822 20.3175 18.279 19.9525C17.6759 19.5875 17.2014 19.0684 16.8555 18.3954C16.5095 17.7224 16.3366 16.924 16.3366 16C16.3366 15.076 16.5095 14.2776 16.8555 13.6046C17.2014 12.9316 17.6759 12.4125 18.279 12.0475C18.8822 11.6825 19.5711 11.5 20.3457 11.5C20.804 11.5 21.2341 11.5642 21.6362 11.6925C22.0413 11.8208 22.4064 12.009 22.7316 12.2571C23.0569 12.5024 23.3289 12.8018 23.5476 13.1554C23.7664 13.5062 23.9172 13.9068 24 14.3574Z"
/>
<rect id="cc-underline" x="8" y="23" width="16" height="1" rx="0.5" />
</g>
</svg>
</media-captions-button>
<!-- Settings Menu Button -->
<style>
media-settings-menu-button svg {
transition: transform 0.1s cubic-bezier(0.4, 0, 1, 1);
transform: rotateZ(0deg);
}
media-settings-menu-button[aria-expanded='true'] svg {
transform: rotateZ(30deg);
}
</style>
<media-settings-menu-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#settings-icon"></use>
<g id="settings-icon">
<path
d="M16 18C17.1046 18 18 17.1046 18 16C18 14.8954 17.1046 14 16 14C14.8954 14 14 14.8954 14 16C14 17.1046 14.8954 18 16 18Z"
/>
<path
d="M21.0176 13.0362L20.9715 12.9531C20.8445 12.7239 20.7797 12.4629 20.784 12.1982L20.8049 10.8997C20.8092 10.6343 20.675 10.3874 20.4545 10.2549L18.5385 9.10362C18.3186 8.97143 18.0472 8.9738 17.8293 9.10981L16.7658 9.77382C16.5485 9.90953 16.2999 9.98121 16.0465 9.98121H15.9543C15.7004 9.98121 15.4513 9.90922 15.2336 9.77295L14.1652 9.10413C13.9467 8.96728 13.674 8.96518 13.4535 9.09864L11.5436 10.2545C11.3242 10.3873 11.1908 10.6336 11.1951 10.8981L11.216 12.1982C11.2203 12.4629 11.1555 12.7239 11.0285 12.9531L10.9831 13.0351C10.856 13.2645 10.6715 13.4535 10.4493 13.5819L9.36075 14.2109C9.13763 14.3398 8.99942 14.5851 9 14.8511L9.00501 17.152C9.00559 17.4163 9.1432 17.6597 9.36476 17.7883L10.4481 18.4167C10.671 18.546 10.8559 18.7364 10.9826 18.9673L11.0313 19.0559C11.1565 19.284 11.2203 19.5431 11.2161 19.8059L11.1951 21.1003C11.1908 21.3657 11.325 21.6126 11.5456 21.7452L13.4615 22.8964C13.6814 23.0286 13.9528 23.0262 14.1707 22.8902L15.2342 22.2262C15.4515 22.0905 15.7001 22.0188 15.9535 22.0188H16.0457C16.2996 22.0188 16.5487 22.0908 16.7664 22.227L17.8348 22.8959C18.0534 23.0327 18.326 23.0348 18.5465 22.9014L20.4564 21.7455C20.6758 21.6127 20.8092 21.3664 20.8049 21.1019L20.784 19.8018C20.7797 19.5371 20.8445 19.2761 20.9715 19.0469L21.0169 18.9649C21.144 18.7355 21.3285 18.5465 21.5507 18.4181L22.6393 17.7891C22.8624 17.6602 23.0006 17.4149 23 17.1489L22.995 14.848C22.9944 14.5837 22.8568 14.3403 22.6352 14.2117L21.5493 13.5818C21.328 13.4534 21.1442 13.2649 21.0176 13.0362Z"
/>
</g>
</svg>
</media-settings-menu-button>
<!-- PIP/Mini Player Button -->
<style>
media-controller:not([breakpointmd]) media-pip-button {
display: none;
}
</style>
<media-pip-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#pip-icon"></use>
<g id="pip-icon">
<path
d="M12 22H9.77778C9.34822 22 9 21.6162 9 21.1429V10.8571C9 10.3838 9.34822 10 9.77778 10L22.2222 10C22.6518 10 23 10.3838 23 10.8571V12.5714"
/>
<path
d="M15 21.5714V16.4286C15 16.1919 15.199 16 15.4444 16H22.5556C22.801 16 23 16.1919 23 16.4286V17V21.5714C23 21.8081 22.801 22 22.5556 22H20.3333H17.6667H15.4444C15.199 22 15 21.8081 15 21.5714Z"
/>
</g>
</svg>
</media-pip-button>
<!-- Cast Button -->
<media-cast-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#cast-icon"></use>
<g id="cast-icon">
<path
d="M18.5 21.833h4.167c.46 0 .833-.373.833-.833V11a.833.833 0 0 0-.833-.833H9.333A.833.833 0 0 0 8.5 11v1.111m0 8.056c.92 0 1.667.746 1.667 1.666M8.5 17.667a4.167 4.167 0 0 1 4.167 4.166"
/>
<path d="M8.5 15.167a6.667 6.667 0 0 1 6.667 6.666" />
</g>
</svg>
</media-cast-button>
<!-- Fullscreen Button -->
<style>
/* Having trouble getting @property to work in the shadow dom
to clean this up. Like https://codepen.io/luwes/pen/oNRyZyx */
media-fullscreen-button .fs-arrow {
translate: 0% 0%;
}
media-fullscreen-button:hover .fs-arrow {
animation: 0.35s up-left-bounce cubic-bezier(0.34, 1.56, 0.64, 1);
}
media-fullscreen-button:hover #fs-enter-top,
media-fullscreen-button:hover #fs-exit-bottom {
animation-name: up-right-bounce;
}
media-fullscreen-button:hover #fs-enter-bottom,
media-fullscreen-button:hover #fs-exit-top {
animation-name: down-left-bounce;
}
@keyframes up-left-bounce {
0% {
translate: 0 0;
}
50% {
translate: -4% -4%;
}
}
@keyframes up-right-bounce {
0% {
translate: 0 0;
}
50% {
translate: 4% -4%;
}
}
@keyframes down-left-bounce {
0% {
translate: 0 0;
}
50% {
translate: -4% 4%;
}
}
@keyframes down-right-bounce {
0% {
translate: 0 0;
}
50% {
translate: 4% 4%;
}
}
</style>
<media-fullscreen-button class="media-button">
<svg slot="enter" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#fs-enter-paths"></use>
<g id="fs-enter-paths">
<g id="fs-enter-top" class="fs-arrow">
<path d="M18 10H22V14" />
<path d="M22 10L18 14" />
</g>
<g id="fs-enter-bottom" class="fs-arrow">
<path d="M14 22L10 22V18" />
<path d="M10 22L14 18" />
</g>
</g>
</svg>
<svg slot="exit" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#fs-exit-paths"></use>
<g id="fs-exit-paths">
<g id="fs-exit-top" class="fs-arrow">
<path d="M22 14H18V10" />
<path d="M22 10L18 14" />
</g>
<g id="fs-exit-bottom" class="fs-arrow">
<path d="M10 18L14 18V22" />
<path d="M14 18L10 22" />
</g>
</g>
</svg>
</media-fullscreen-button>
</media-control-bar>
</media-controller>
`;
}
class MediaThemeSutroElement extends MediaThemeElement {
static template = template;
}
if (globalThis.customElements && !globalThis.customElements.get('media-theme-sutro')) {
globalThis.customElements.define('media-theme-sutro', MediaThemeSutroElement);
}
export default MediaThemeSutroElement;

View File

@@ -0,0 +1,7 @@
import MediaThemeSutroElement from './media-theme.js';
declare const MediaThemeSutro: React.ForwardRefExoticComponent<
React.DetailedHTMLProps<React.HTMLAttributes<MediaThemeSutroElement>, MediaThemeSutroElement>
>;
export default MediaThemeSutro;

View File

@@ -0,0 +1,94 @@
'use client';
import React from 'react';
import Element from './media-theme.js';
export default React.forwardRef((allProps, ref) => {
let { children, suppressHydrationWarning, ...props } = allProps;
const elementRef = React.useRef(null);
for (let name in props) {
if (name[0] === 'o' && name[1] === 'n') {
const useCapture = name.endsWith('Capture');
const eventName = name.slice(2, useCapture ? name.length - 7 : undefined).toLowerCase();
const callback = props[name];
React.useEffect(() => {
const eventTarget = elementRef?.current;
if (!eventTarget || typeof callback !== 'function') return;
eventTarget.addEventListener(eventName, callback, useCapture);
return () => {
eventTarget.removeEventListener(eventName, callback, useCapture);
};
}, [elementRef?.current, callback]);
}
}
const attrs = propsToAttrs(props);
// Only render the custom element template HTML on the server..
// The custom element will render itself on the client.
if (typeof window === 'undefined' && Element?.getTemplateHTML && Element?.shadowRootOptions) {
const { mode, delegatesFocus } = Element.shadowRootOptions;
const templateShadowRoot = React.createElement('template', {
shadowrootmode: mode,
shadowrootdelegatesfocus: delegatesFocus,
dangerouslySetInnerHTML: {
__html: Element.getTemplateHTML(attrs),
},
});
children = [templateShadowRoot, children];
}
return React.createElement('media-theme-sutro', {
...attrs,
ref: React.useCallback(
(node) => {
elementRef.current = node;
if (typeof ref === 'function') {
ref(node);
} else if (ref !== null) {
ref.current = node;
}
},
[ref]
),
children,
suppressHydrationWarning,
});
});
const ReactPropToAttrNameMap = {
className: 'class',
classname: 'class',
htmlFor: 'for',
viewBox: 'viewBox',
};
function propsToAttrs(props = {}) {
let attrs = {};
for (let [propName, propValue] of Object.entries(props)) {
let attrName = toAttrName(propName, propValue);
if (attrName) attrs[attrName] = toAttrValue(propValue);
}
return attrs;
}
function toAttrName(propName, propValue) {
if (ReactPropToAttrNameMap[propName]) return ReactPropToAttrNameMap[propName];
if (typeof propValue == 'undefined') return undefined;
if (typeof propValue === 'boolean' && !propValue) return undefined;
if (propName.startsWith('on') && typeof propValue === 'function') return undefined;
if (/[A-Z]/.test(propName)) return propName.toLowerCase();
return propName;
}
function toAttrValue(propValue) {
if (typeof propValue === 'boolean') return '';
if (Array.isArray(propValue)) return propValue.join(' ');
return propValue;
}

View File

@@ -0,0 +1,35 @@
{
"name": "@player.style/sutro",
"version": "0.0.3",
"description": "A sleek and modern theme lovingly named after our favorite SF TV antenna, which is neither sleek nor modern.",
"author": "@muxinc",
"license": "MIT",
"homepage": "https://github.com/muxinc/player.style#readme",
"bugs": {
"url": "https://github.com/muxinc/player.style/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/muxinc/player.style.git",
"directory": "themes/sutro"
},
"files": [
"dist"
],
"type": "module",
"main": "dist/media-theme.js",
"exports": {
".": "./dist/media-theme.js",
"./react": "./dist/react.js"
},
"scripts": {
"clean": "rimraf dist",
"build": "build-theme"
},
"peerDependencies": {
"media-chrome": ">=1.0.0"
},
"devDependencies": {
"build-theme": "^0.0.4"
}
}

View File

@@ -0,0 +1,763 @@
<!-- Sutro -->
<style>
:host {
--_primary-color: var(--media-primary-color, #fff);
--_secondary-color: var(--media-secondary-color, transparent);
--_accent-color: var(--media-accent-color, #fff);
}
media-controller {
--base: 18px;
font-size: calc(0.75 * var(--base));
font-family: Roboto, Arial, sans-serif;
--media-font-family: Roboto, helvetica neue, segoe ui, arial, sans-serif;
-webkit-font-smoothing: antialiased;
--media-primary-color: #fff;
--media-secondary-color: transparent;
--media-menu-background: rgba(28, 28, 28, 0.6);
--media-text-color: var(--_primary-color);
--media-control-hover-background: var(--media-secondary-color);
--media-range-track-height: calc(0.125 * var(--base));
--media-range-thumb-height: var(--base);
--media-range-thumb-width: var(--base);
--media-range-thumb-border-radius: var(--base);
--media-control-height: calc(2 * var(--base));
--media-tooltip-display: none;
}
media-controller[breakpointmd] {
--base: 20px;
}
/* The biggest size controller is tied to going fullscreen
instead of a player width */
media-controller[mediaisfullscreen] {
--base: 24px;
}
.media-button {
--media-control-hover-background: var(--_secondary-color);
position: relative;
padding: 0;
opacity: 0.9;
transition: opacity 0.1s cubic-bezier(0.4, 0, 1, 1);
}
.media-button svg {
fill: none;
stroke: var(--_primary-color);
stroke-width: 1;
stroke-linecap: 'round';
stroke-linejoin: 'round';
}
svg .svg-shadow {
stroke: #000;
stroke-opacity: 0.15;
stroke-width: 2px;
fill: none;
}
</style>
<media-controller
breakpoints="md:480"
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<!-- Controls Gradient -->
<style>
.media-gradient-bottom {
--gradient-steps: hsl(0 0% 0% / 0) 0%, hsl(0 0% 0% / 0.013) 8.1%, hsl(0 0% 0% / 0.049) 15.5%,
hsl(0 0% 0% / 0.104) 22.5%, hsl(0 0% 0% / 0.175) 29%, hsl(0 0% 0% / 0.259) 35.3%, hsl(0 0% 0% / 0.352) 41.2%,
hsl(0 0% 0% / 0.45) 47.1%, hsl(0 0% 0% / 0.55) 52.9%, hsl(0 0% 0% / 0.648) 58.8%, hsl(0 0% 0% / 0.741) 64.7%,
hsl(0 0% 0% / 0.825) 71%, hsl(0 0% 0% / 0.896) 77.5%, hsl(0 0% 0% / 0.951) 84.5%, hsl(0 0% 0% / 0.987) 91.9%,
hsl(0 0% 0%) 100%;
position: absolute;
bottom: 0;
opacity: 0.7;
width: 100%;
height: calc(8 * var(--base));
background: linear-gradient(to bottom, var(--gradient-steps));
pointer-events: none;
}
</style>
<div class="media-gradient-bottom"></div>
<!-- Settings Menu -->
<style>
media-settings-menu {
--media-menu-icon-height: 20px;
--media-menu-item-icon-height: 20px;
--media-settings-menu-min-width: calc(10 * var(--base));
--media-menu-transform-in: translateY(0) scale(1);
--media-menu-transform-out: translateY(20px) rotate(3deg) scale(1);
padding-block: calc(0.15 * var(--base));
margin-right: 10px;
margin-bottom: 17px;
border-radius: 8px;
z-index: 2;
user-select: none;
}
media-settings-menu-item,
[role='menu']::part(menu-item) {
--media-icon-color: var(--_primary-color);
margin-inline: calc(0.45 * var(--base));
height: calc(1.6 * var(--base));
font-size: calc(0.7 * var(--base));
font-weight: 400;
padding: 0;
padding-left: calc(0.4 * var(--base));
padding-right: calc(0.1 * var(--base));
border-radius: 6px;
text-shadow: none;
}
[slot='submenu']::part(back button) {
font-size: calc(0.7 * var(--base));
}
media-settings-menu-item:hover {
--media-icon-color: #000;
color: #000;
background-color: #fff;
}
media-settings-menu-item:hover [slot='submenu']::part(menu-item),
[slot='submenu']::part(back indicator) {
--media-icon-color: var(--_primary-color);
}
media-settings-menu-item:hover [slot='submenu']::part(menu-item):hover {
--media-icon-color: #000;
color: #000;
background-color: #fff;
}
media-settings-menu-item[submenusize='0'] {
display: none;
}
/* Also hide if only `Auto` is added. */
.quality-settings[submenusize='1'] {
display: none;
}
</style>
<media-settings-menu hidden anchor="auto">
<media-settings-menu-item>
Playback Speed
<media-playback-rate-menu slot="submenu" hidden>
<div slot="title">Playback Speed</div>
</media-playback-rate-menu>
</media-settings-menu-item>
<media-settings-menu-item class="quality-settings">
Quality
<media-rendition-menu slot="submenu" hidden>
<div slot="title">Quality</div>
</media-rendition-menu>
</media-settings-menu-item>
<media-settings-menu-item>
Subtitles/CC
<media-captions-menu slot="submenu" hidden>
<div slot="title">Subtitles/CC</div>
</media-captions-menu>
</media-settings-menu-item>
</media-settings-menu>
<!-- Control Bar -->
<style>
media-control-bar {
position: absolute;
height: calc(2 * var(--base));
line-height: calc(2 * var(--base));
bottom: var(--base);
left: var(--base);
right: var(--base);
}
</style>
<media-control-bar>
<!-- Play/Pause -->
<style>
@keyframes bounce-scale-play {
0% {
transform: scale(0.75, 0.75);
}
50% {
transform: scale(115%, 115%);
}
100% {
transform: scale(1, 1);
}
}
.media-button {
border-radius: 25%;
backdrop-filter: blur(10px) invert(15%) brightness(80%) opacity(0);
-webkit-backdrop-filter: blur(10px) invert(15%) brightness(80%) opacity(0);
transition: backdrop-filter 0.3s, -webkit-backdrop-filter 0.3s, box-shadow 0.3s;
}
.media-button:hover {
/* background-color: rgba(0, 0, 0, 0.05); */
box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 5px;
/* hue-rotate(120deg) */
backdrop-filter: blur(10px) invert(15%) brightness(80%) opacity(1);
-webkit-backdrop-filter: blur(10px) invert(15%) brightness(80%) opacity(1);
transition: backdrop-filter 0.3s, -webkit-backdrop-filter 0.3s;
}
media-play-button #icon-play {
opacity: 0;
transform-box: view-box;
transform-origin: center center;
transform: scale(0.5, 0.5);
transition: all 0.5s;
}
media-play-button[mediapaused] #icon-play {
opacity: 1;
transform: scale(1, 1);
animation: 0.35s bounce-scale-play ease-in-out;
}
@keyframes bounce-pause-left {
0% {
font-size: 10px;
}
50% {
font-size: 3px;
}
100% {
font-size: 4px;
}
}
@keyframes bounce-pause-right {
0% {
font-size: 10px;
transform: translateX(-8px);
}
50% {
font-size: 3px;
transform: translateX(1px);
}
100% {
font-size: 4px;
transform: translateX(0);
}
}
media-play-button #pause-left,
media-play-button #pause-right {
/* Using font-size to animate height because using scale was resulting in unexpected positioning */
font-size: 4px;
opacity: 1;
transform: translateX(0);
transform-box: view-box;
}
media-play-button:not([mediapaused]) #pause-left {
animation: 0.3s bounce-pause-left ease-out;
}
media-play-button:not([mediapaused]) #pause-right {
animation: 0.3s bounce-pause-right ease-out;
}
media-play-button[mediapaused] #pause-left,
media-play-button[mediapaused] #pause-right {
opacity: 0;
font-size: 10px;
}
media-play-button[mediapaused] #pause-right {
transform-origin: right center;
transform: translateX(-8px);
}
</style>
<media-play-button mediapaused class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<!-- <use class="svg-shadow" xlink:href="#icon-play"></use> -->
<g>
<path
id="icon-play"
d="M20.7131 14.6976C21.7208 15.2735 21.7208 16.7265 20.7131 17.3024L12.7442 21.856C11.7442 22.4274 10.5 21.7054 10.5 20.5536L10.5 11.4464C10.5 10.2946 11.7442 9.57257 12.7442 10.144L20.7131 14.6976Z"
/>
</g>
<!-- <use class="svg-shadow" xlink:href="#icon-pause"></use> -->
<g id="icon-pause">
<rect id="pause-left" x="10.5" width="1em" y="10.5" height="11" rx="0.5" />
<rect id="pause-right" x="17.5" width="1em" y="10.5" height="11" rx="0.5" />
</g>
</svg>
</media-play-button>
<!-- Volume/Mute -->
<style>
media-mute-button {
position: relative;
z-index: 1;
}
media-mute-button .muted-path {
transition: clip-path 0.2s ease-out;
}
media-mute-button #muted-path-2 {
transition-delay: 0.2s;
}
media-mute-button .muted-path {
clip-path: inset(0);
}
media-mute-button:not([mediavolumelevel='off']) #muted-path-1 {
clip-path: inset(0 0 100% 0);
}
media-mute-button:not([mediavolumelevel='off']) #muted-path-2 {
clip-path: inset(0 0 100% 0);
}
media-mute-button .muted-path {
opacity: 0;
}
media-mute-button[mediavolumelevel='off'] .muted-path {
opacity: 1;
}
media-mute-button .vol-path {
opacity: 1;
transition: opacity 0.4s;
}
media-mute-button[mediavolumelevel='off'] .vol-path {
opacity: 0;
}
media-mute-button[mediavolumelevel='low'] #vol-high-path,
media-mute-button[mediavolumelevel='medium'] #vol-high-path {
opacity: 0;
}
media-volume-range {
--media-range-track-background: rgba(255, 255, 255, 0.2);
--media-range-thumb-opacity: 0;
}
@keyframes volume-in {
0% {
visibility: hidden;
opacity: 0;
transform: translateY(50%) rotate(1deg);
}
50% {
visibility: visible;
opacity: 1;
transform: rotate(-2deg);
}
100% {
visibility: visible;
opacity: 1;
transform: translateY(0) rotate(0deg);
}
}
@keyframes volume-out {
0% {
visibility: visible;
opacity: 1;
transform: translateY(0) rotate(0deg);
}
50% {
opacity: 1;
transform: rotate(0deg);
}
100% {
visibility: hidden;
opacity: 0;
transform: translateY(50%) rotate(1deg);
}
}
.media-volume-range-wrapper {
opacity: 0;
visibility: hidden;
position: absolute;
top: -100%;
left: calc(2 * var(--base));
width: calc(10 * var(--base));
height: calc(2.5 * var(--base));
transform-origin: center left;
}
media-volume-range {
/*
Hide range and animation until mediavolume attribute is set.
`visibility` didn't work, hovering over media-volume-range-wrapper
caused it to show. Should require mute-button:hover.
*/
opacity: 0;
transition: opacity 0s 1s;
width: calc(10 * var(--base));
height: var(--base);
padding: 0;
border-radius: calc(0.25 * var(--base));
overflow: hidden;
background: rgba(0, 0, 0, 0.2);
--media-range-bar-color: var(--media-accent-color);
--media-range-padding-left: 0;
--media-range-padding-right: 0;
--media-range-track-width: calc(10 * var(--base));
--media-range-track-height: var(--base);
--media-range-track-border-radius: calc(0.25 * var(--base));
--media-range-track-backdrop-filter: blur(10px) brightness(80%);
/* This makes zero volume still show some of the bar.
I can't make the bar have curved corners otherwise though. */
--media-range-thumb-width: var(--base);
--media-range-thumb-border-radius: calc(0.25 * var(--base));
/* The Sutro design has a gradient like this, but not sure I like it */
/* --media-range-thumb-box-shadow: 10px 0px 20px rgba(255, 255, 255, 0.5); */
}
media-volume-range[mediavolume] {
opacity: 1;
}
[keyboardcontrol] media-volume-range:focus {
/* TODO: This appears to be creating a think outline */
outline: 1px solid rgba(27, 127, 204, 0.9);
}
media-mute-button:hover + .media-volume-range-wrapper,
media-mute-button:focus + .media-volume-range-wrapper,
media-mute-button:focus-within + .media-volume-range-wrapper,
.media-volume-range-wrapper:hover,
.media-volume-range-wrapper:focus,
.media-volume-range-wrapper:focus-within {
animation: 0.3s volume-in forwards ease-out;
}
.media-volume-range-wrapper:not(:hover, :focus-within) {
animation: 0.3s volume-out ease-out;
}
/* When keyboard navigating the volume range and wrapper need to always be visible
otherwise focus state can't land on it. This is ok when keyboard navigating because
the hovering issues aren't a concern, unless you happen to be keyboard AND mouse navigating.
*/
[keyboardcontrol] .media-volume-range-wrapper,
[keyboardcontrol] .media-volume-range-wrapper:focus-within,
[keyboardcontrol] .media-volume-range-wrapper:focus-within media-volume-range {
visibility: visible;
}
</style>
<media-mute-button class="media-button">
<use class="svg-shadow" xlink:href="#vol-paths"></use>
<svg slot="icon" viewBox="0 0 32 32">
<g id="vol-paths">
<path
id="speaker-path"
d="M16.5 20.486v-8.972c0-1.537-2.037-2.08-2.802-.745l-1.026 1.79a2.5 2.5 0 0 1-.8.85l-1.194.78A1.5 1.5 0 0 0 10 15.446v1.11c0 .506.255.978.678 1.255l1.194.782a2.5 2.5 0 0 1 .8.849l1.026 1.79c.765 1.334 2.802.792 2.802-.745Z"
/>
<path
id="vol-low-path"
class="vol-path"
d="M18.5 18C19.6046 18 20.5 17.1046 20.5 16C20.5 14.8954 19.6046 14 18.5 14"
/>
<path
id="vol-high-path"
class="vol-path"
d="M18 21C20.7614 21 23 18.7614 23 16C23 13.2386 20.7614 11 18 11"
/>
<path id="muted-path-1" class="muted-path" d="M23 18L19 14" />
<path id="muted-path-2" class="muted-path" d="M23 14L19 18" />
</g>
</svg>
</media-mute-button>
<div class="media-volume-range-wrapper">
<media-volume-range></media-volume-range>
</div>
<!-- Time Display -->
<style>
media-time-display {
position: relative;
z-index: 1;
padding: calc(0.5 * var(--base));
font-size: calc(0.7 * var(--base));
border-radius: calc(0.5 * var(--base));
}
media-controller[breakpointmd] media-time-display:not([showduration]) {
display: none;
}
media-controller:not([breakpointmd]) media-time-display[showduration] {
display: none;
}
</style>
<media-time-display></media-time-display>
<media-time-display showduration></media-time-display>
<!-- Time Range / Progress Bar -->
<style>
media-time-range {
height: calc(2 * var(--base));
border-radius: calc(0.25 * var(--base));
--media-range-track-transition: height 0.2s linear;
--media-range-track-backdrop-filter: invert(10%) blur(5px) brightness(110%);
--media-range-track-background: rgba(255, 255, 255, 0.2);
--media-range-track-pointer-background: rgba(255, 255, 255, 0.5);
--media-range-track-border-radius: calc(0.25 * var(--base));
--media-time-range-buffered-color: rgba(255, 255, 255, 0.4);
--media-range-bar-color: var(--media-accent-color);
--media-range-thumb-background: var(--media-accent-color);
--media-range-thumb-transition: opacity 0.1s linear;
--media-range-thumb-opacity: 0;
--media-preview-thumbnail-border: calc(0.125 * var(--base)) solid #fff;
--media-preview-thumbnail-border-radius: calc(0.5 * var(--base));
--media-preview-thumbnail-min-width: calc(8 * var(--base));
--media-preview-thumbnail-max-width: calc(10 * var(--base));
--media-preview-thumbnail-min-height: calc(5 * var(--base));
--media-preview-thumbnail-max-height: calc(7 * var(--base));
--media-preview-time-margin: 0 0 -15px;
}
media-time-range:hover {
--media-range-thumb-opacity: 1;
--media-range-track-height: calc(0.25 * var(--base));
}
media-preview-time-display {
font-size: calc(0.7 * var(--base));
line-height: 1.6;
}
</style>
<media-time-range>
<media-preview-thumbnail slot="preview"></media-preview-thumbnail>
<media-preview-time-display slot="preview"></media-preview-time-display>
</media-time-range>
<!-- Subtitles/CC Button -->
<style>
media-captions-button {
position: relative;
}
media-controller:not([breakpointmd]) media-captions-button {
display: none;
}
media-captions-button svg :is(path, rect) {
stroke: none;
fill: var(--_primary-color);
}
/* Disble the captions button when no subtitles are available */
media-captions-button:not([mediasubtitleslist]) svg {
opacity: 0.3;
}
media-captions-button #cc-underline {
opacity: 1;
}
media-captions-button[mediasubtitleslist][aria-checked='true'] #cc-underline {
opacity: 1;
}
media-captions-button #cc-underline {
transition: clip-path 0.15s ease-out;
}
media-captions-button #cc-underline {
clip-path: inset(0 100% 0 0);
}
media-captions-button[aria-checked='true'] #cc-underline {
clip-path: inset(0 0 0 0);
}
</style>
<media-captions-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#cc-icon"></use>
<g id="cc-icon">
<path
class="cc-c"
d="M15.6634 14.3574H14.5636C14.4985 14.0523 14.3847 13.7842 14.2221 13.5532C14.0624 13.3222 13.8673 13.1283 13.6367 12.9715C13.409 12.8118 13.1562 12.692 12.8783 12.6122C12.6004 12.5323 12.3107 12.4924 12.0091 12.4924C11.4592 12.4924 10.961 12.6264 10.5146 12.8945C10.0711 13.1625 9.71776 13.5575 9.45463 14.0794C9.19445 14.6012 9.06436 15.2414 9.06436 16C9.06436 16.7586 9.19445 17.3988 9.45463 17.9206C9.71776 18.4425 10.0711 18.8375 10.5146 19.1055C10.961 19.3736 11.4592 19.5076 12.0091 19.5076C12.3107 19.5076 12.6004 19.4677 12.8783 19.3878C13.1562 19.308 13.409 19.1896 13.6367 19.0328C13.8673 18.8731 14.0624 18.6778 14.2221 18.4468C14.3847 18.2129 14.4985 17.9449 14.5636 17.6426H15.6634C15.5806 18.0903 15.4298 18.491 15.2111 18.8446C14.9923 19.1982 14.7203 19.499 14.3951 19.7471C14.0698 19.9924 13.7047 20.1792 13.2996 20.3075C12.8976 20.4358 12.4674 20.5 12.0091 20.5C11.2345 20.5 10.5456 20.3175 9.94246 19.9525C9.33932 19.5875 8.8648 19.0684 8.51888 18.3954C8.17296 17.7224 8 16.924 8 16C8 15.076 8.17296 14.2776 8.51888 13.6046C8.8648 12.9316 9.33932 12.4125 9.94246 12.0475C10.5456 11.6825 11.2345 11.5 12.0091 11.5C12.4674 11.5 12.8976 11.5642 13.2996 11.6925C13.7047 11.8208 14.0698 12.009 14.3951 12.2571C14.7203 12.5024 14.9923 12.8018 15.2111 13.1554C15.4298 13.5062 15.5806 13.9068 15.6634 14.3574Z"
/>
<path
class="cc-c"
d="M24 14.3574H22.9002C22.8351 14.0523 22.7213 13.7842 22.5587 13.5532C22.399 13.3222 22.2039 13.1283 21.9733 12.9715C21.7456 12.8118 21.4928 12.692 21.2149 12.6122C20.937 12.5323 20.6473 12.4924 20.3457 12.4924C19.7958 12.4924 19.2976 12.6264 18.8511 12.8945C18.4077 13.1625 18.0543 13.5575 17.7912 14.0794C17.531 14.6012 17.4009 15.2414 17.4009 16C17.4009 16.7586 17.531 17.3988 17.7912 17.9206C18.0543 18.4425 18.4077 18.8375 18.8511 19.1055C19.2976 19.3736 19.7958 19.5076 20.3457 19.5076C20.6473 19.5076 20.937 19.4677 21.2149 19.3878C21.4928 19.308 21.7456 19.1896 21.9733 19.0328C22.2039 18.8731 22.399 18.6778 22.5587 18.4468C22.7213 18.2129 22.8351 17.9449 22.9002 17.6426H24C23.9172 18.0903 23.7664 18.491 23.5476 18.8446C23.3289 19.1982 23.0569 19.499 22.7316 19.7471C22.4064 19.9924 22.0413 20.1792 21.6362 20.3075C21.2341 20.4358 20.804 20.5 20.3457 20.5C19.5711 20.5 18.8822 20.3175 18.279 19.9525C17.6759 19.5875 17.2014 19.0684 16.8555 18.3954C16.5095 17.7224 16.3366 16.924 16.3366 16C16.3366 15.076 16.5095 14.2776 16.8555 13.6046C17.2014 12.9316 17.6759 12.4125 18.279 12.0475C18.8822 11.6825 19.5711 11.5 20.3457 11.5C20.804 11.5 21.2341 11.5642 21.6362 11.6925C22.0413 11.8208 22.4064 12.009 22.7316 12.2571C23.0569 12.5024 23.3289 12.8018 23.5476 13.1554C23.7664 13.5062 23.9172 13.9068 24 14.3574Z"
/>
<rect id="cc-underline" x="8" y="23" width="16" height="1" rx="0.5" />
</g>
</svg>
</media-captions-button>
<!-- Settings Menu Button -->
<style>
media-settings-menu-button svg {
transition: transform 0.1s cubic-bezier(0.4, 0, 1, 1);
transform: rotateZ(0deg);
}
media-settings-menu-button[aria-expanded='true'] svg {
transform: rotateZ(30deg);
}
</style>
<media-settings-menu-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#settings-icon"></use>
<g id="settings-icon">
<path
d="M16 18C17.1046 18 18 17.1046 18 16C18 14.8954 17.1046 14 16 14C14.8954 14 14 14.8954 14 16C14 17.1046 14.8954 18 16 18Z"
/>
<path
d="M21.0176 13.0362L20.9715 12.9531C20.8445 12.7239 20.7797 12.4629 20.784 12.1982L20.8049 10.8997C20.8092 10.6343 20.675 10.3874 20.4545 10.2549L18.5385 9.10362C18.3186 8.97143 18.0472 8.9738 17.8293 9.10981L16.7658 9.77382C16.5485 9.90953 16.2999 9.98121 16.0465 9.98121H15.9543C15.7004 9.98121 15.4513 9.90922 15.2336 9.77295L14.1652 9.10413C13.9467 8.96728 13.674 8.96518 13.4535 9.09864L11.5436 10.2545C11.3242 10.3873 11.1908 10.6336 11.1951 10.8981L11.216 12.1982C11.2203 12.4629 11.1555 12.7239 11.0285 12.9531L10.9831 13.0351C10.856 13.2645 10.6715 13.4535 10.4493 13.5819L9.36075 14.2109C9.13763 14.3398 8.99942 14.5851 9 14.8511L9.00501 17.152C9.00559 17.4163 9.1432 17.6597 9.36476 17.7883L10.4481 18.4167C10.671 18.546 10.8559 18.7364 10.9826 18.9673L11.0313 19.0559C11.1565 19.284 11.2203 19.5431 11.2161 19.8059L11.1951 21.1003C11.1908 21.3657 11.325 21.6126 11.5456 21.7452L13.4615 22.8964C13.6814 23.0286 13.9528 23.0262 14.1707 22.8902L15.2342 22.2262C15.4515 22.0905 15.7001 22.0188 15.9535 22.0188H16.0457C16.2996 22.0188 16.5487 22.0908 16.7664 22.227L17.8348 22.8959C18.0534 23.0327 18.326 23.0348 18.5465 22.9014L20.4564 21.7455C20.6758 21.6127 20.8092 21.3664 20.8049 21.1019L20.784 19.8018C20.7797 19.5371 20.8445 19.2761 20.9715 19.0469L21.0169 18.9649C21.144 18.7355 21.3285 18.5465 21.5507 18.4181L22.6393 17.7891C22.8624 17.6602 23.0006 17.4149 23 17.1489L22.995 14.848C22.9944 14.5837 22.8568 14.3403 22.6352 14.2117L21.5493 13.5818C21.328 13.4534 21.1442 13.2649 21.0176 13.0362Z"
/>
</g>
</svg>
</media-settings-menu-button>
<!-- PIP/Mini Player Button -->
<style>
media-controller:not([breakpointmd]) media-pip-button {
display: none;
}
</style>
<media-pip-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#pip-icon"></use>
<g id="pip-icon">
<path
d="M12 22H9.77778C9.34822 22 9 21.6162 9 21.1429V10.8571C9 10.3838 9.34822 10 9.77778 10L22.2222 10C22.6518 10 23 10.3838 23 10.8571V12.5714"
/>
<path
d="M15 21.5714V16.4286C15 16.1919 15.199 16 15.4444 16H22.5556C22.801 16 23 16.1919 23 16.4286V17V21.5714C23 21.8081 22.801 22 22.5556 22H20.3333H17.6667H15.4444C15.199 22 15 21.8081 15 21.5714Z"
/>
</g>
</svg>
</media-pip-button>
<!-- Cast Button -->
<media-cast-button class="media-button">
<svg slot="icon" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#cast-icon"></use>
<g id="cast-icon">
<path
d="M18.5 21.833h4.167c.46 0 .833-.373.833-.833V11a.833.833 0 0 0-.833-.833H9.333A.833.833 0 0 0 8.5 11v1.111m0 8.056c.92 0 1.667.746 1.667 1.666M8.5 17.667a4.167 4.167 0 0 1 4.167 4.166"
/>
<path d="M8.5 15.167a6.667 6.667 0 0 1 6.667 6.666" />
</g>
</svg>
</media-cast-button>
<!-- Fullscreen Button -->
<style>
/* Having trouble getting @property to work in the shadow dom
to clean this up. Like https://codepen.io/luwes/pen/oNRyZyx */
media-fullscreen-button .fs-arrow {
translate: 0% 0%;
}
media-fullscreen-button:hover .fs-arrow {
animation: 0.35s up-left-bounce cubic-bezier(0.34, 1.56, 0.64, 1);
}
media-fullscreen-button:hover #fs-enter-top,
media-fullscreen-button:hover #fs-exit-bottom {
animation-name: up-right-bounce;
}
media-fullscreen-button:hover #fs-enter-bottom,
media-fullscreen-button:hover #fs-exit-top {
animation-name: down-left-bounce;
}
@keyframes up-left-bounce {
0% {
translate: 0 0;
}
50% {
translate: -4% -4%;
}
}
@keyframes up-right-bounce {
0% {
translate: 0 0;
}
50% {
translate: 4% -4%;
}
}
@keyframes down-left-bounce {
0% {
translate: 0 0;
}
50% {
translate: -4% 4%;
}
}
@keyframes down-right-bounce {
0% {
translate: 0 0;
}
50% {
translate: 4% 4%;
}
}
</style>
<media-fullscreen-button class="media-button">
<svg slot="enter" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#fs-enter-paths"></use>
<g id="fs-enter-paths">
<g id="fs-enter-top" class="fs-arrow">
<path d="M18 10H22V14" />
<path d="M22 10L18 14" />
</g>
<g id="fs-enter-bottom" class="fs-arrow">
<path d="M14 22L10 22V18" />
<path d="M10 22L14 18" />
</g>
</g>
</svg>
<svg slot="exit" viewBox="0 0 32 32">
<use class="svg-shadow" xlink:href="#fs-exit-paths"></use>
<g id="fs-exit-paths">
<g id="fs-exit-top" class="fs-arrow">
<path d="M22 14H18V10" />
<path d="M22 10L18 14" />
</g>
<g id="fs-exit-bottom" class="fs-arrow">
<path d="M10 18L14 18V22" />
<path d="M14 18L10 22" />
</g>
</g>
</svg>
</media-fullscreen-button>
</media-control-bar>
</media-controller>

View File

@@ -0,0 +1,30 @@
# Changelog
## [0.0.7](https://github.com/muxinc/player.style/compare/@player.style/tailwind-audio@0.0.6...@player.style/tailwind-audio@0.0.7) (2024-09-10)
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.3 to ^0.0.4
## [0.0.6](https://github.com/muxinc/player.style/compare/@player.style/tailwind-audio-v0.0.5...@player.style/tailwind-audio@0.0.6) (2024-08-15)
### Features
* add tailwind-audio theme ([#40](https://github.com/muxinc/player.style/issues/40)) ([c80e967](https://github.com/muxinc/player.style/commit/c80e9670548ff1db8e241e0b8dc90084004ebd5f))
### Bug Fixes
* improve color CSS vars & site color picker ([#49](https://github.com/muxinc/player.style/issues/49)) ([a8e8dc0](https://github.com/muxinc/player.style/commit/a8e8dc0898979e72d035af87233b2a0941fdcc7f))
* upgrade to Media Chrome v4 ([#64](https://github.com/muxinc/player.style/issues/64)) ([be68af2](https://github.com/muxinc/player.style/commit/be68af2f9c3a6ff6674b9951f0b34f2bfdb042aa))
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.2 to ^0.0.3

View File

@@ -0,0 +1,13 @@
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
declare global {
interface HTMLElementTagNameMap {
'media-theme-tailwind-audio': MediaThemeTailwindAudioElement;
}
}
declare class MediaThemeTailwindAudioElement extends MediaThemeElement {
static template: HTMLTemplateElement;
}
export default MediaThemeTailwindAudioElement;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
import MediaThemeTailwindAudioElement from './media-theme.js';
declare const MediaThemeTailwindAudio: React.ForwardRefExoticComponent<
React.DetailedHTMLProps<React.HTMLAttributes<MediaThemeTailwindAudioElement>, MediaThemeTailwindAudioElement>
>;
export default MediaThemeTailwindAudio;

View File

@@ -0,0 +1,94 @@
'use client';
import React from 'react';
import Element from './media-theme.js';
export default React.forwardRef((allProps, ref) => {
let { children, suppressHydrationWarning, ...props } = allProps;
const elementRef = React.useRef(null);
for (let name in props) {
if (name[0] === 'o' && name[1] === 'n') {
const useCapture = name.endsWith('Capture');
const eventName = name.slice(2, useCapture ? name.length - 7 : undefined).toLowerCase();
const callback = props[name];
React.useEffect(() => {
const eventTarget = elementRef?.current;
if (!eventTarget || typeof callback !== 'function') return;
eventTarget.addEventListener(eventName, callback, useCapture);
return () => {
eventTarget.removeEventListener(eventName, callback, useCapture);
};
}, [elementRef?.current, callback]);
}
}
const attrs = propsToAttrs(props);
// Only render the custom element template HTML on the server..
// The custom element will render itself on the client.
if (typeof window === 'undefined' && Element?.getTemplateHTML && Element?.shadowRootOptions) {
const { mode, delegatesFocus } = Element.shadowRootOptions;
const templateShadowRoot = React.createElement('template', {
shadowrootmode: mode,
shadowrootdelegatesfocus: delegatesFocus,
dangerouslySetInnerHTML: {
__html: Element.getTemplateHTML(attrs),
},
});
children = [templateShadowRoot, children];
}
return React.createElement('media-theme-tailwind-audio', {
...attrs,
ref: React.useCallback(
(node) => {
elementRef.current = node;
if (typeof ref === 'function') {
ref(node);
} else if (ref !== null) {
ref.current = node;
}
},
[ref]
),
children,
suppressHydrationWarning,
});
});
const ReactPropToAttrNameMap = {
className: 'class',
classname: 'class',
htmlFor: 'for',
viewBox: 'viewBox',
};
function propsToAttrs(props = {}) {
let attrs = {};
for (let [propName, propValue] of Object.entries(props)) {
let attrName = toAttrName(propName, propValue);
if (attrName) attrs[attrName] = toAttrValue(propValue);
}
return attrs;
}
function toAttrName(propName, propValue) {
if (ReactPropToAttrNameMap[propName]) return ReactPropToAttrNameMap[propName];
if (typeof propValue == 'undefined') return undefined;
if (typeof propValue === 'boolean' && !propValue) return undefined;
if (propName.startsWith('on') && typeof propValue === 'function') return undefined;
if (/[A-Z]/.test(propName)) return propName.toLowerCase();
return propName;
}
function toAttrValue(propValue) {
if (typeof propValue === 'boolean') return '';
if (Array.isArray(propValue)) return propValue.join(' ');
return propValue;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,38 @@
{
"name": "@player.style/tailwind-audio",
"version": "0.0.7",
"description": "A slick, minimal audio player theme made with Tailwind CSS.",
"author": "@luwes",
"license": "MIT",
"homepage": "https://github.com/muxinc/player.style#readme",
"bugs": {
"url": "https://github.com/muxinc/player.style/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/muxinc/player.style.git",
"directory": "themes/tailwind-audio"
},
"files": [
"dist"
],
"type": "module",
"main": "dist/media-theme.js",
"exports": {
".": "./dist/media-theme.js",
"./react": "./dist/react.js"
},
"scripts": {
"clean": "rimraf dist",
"prebuild": "tailwindcss -i ./styles.css --minify -o ./dist/styles.css",
"build": "build-theme"
},
"peerDependencies": {
"media-chrome": ">=1.0.0"
},
"devDependencies": {
"@tailwindcss/container-queries": "^0.1.0",
"build-theme": "^0.0.4",
"tailwindcss": "^3.2.4"
}
}

View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -0,0 +1,16 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./**/*.{html,js}'],
theme: {
extend: {
colors: {
// todo: needs more sub variants because slate-500, slate-700 and slate-900 is used.
// ideally 3 shades of each color would be created via CSS.
// primary: 'var(--media-primary-color, rgb(51 65 85 / var(--tw-bg-opacity)))',
secondary: 'var(--media-secondary-color, #fff)',
accent: 'var(--media-accent-color, rgb(79 70 229))',
},
},
},
plugins: [require('@tailwindcss/container-queries')],
};

View File

@@ -0,0 +1,229 @@
<style>
<%- await include('/styles.css') -%>
</style>
<svg class="hidden">
<symbol
id="backward"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M8 5L5 8M5 8L8 11M5 8H13.5C16.5376 8 19 10.4624 19 13.5C19 15.4826 18.148 17.2202 17 18.188"
></path>
<path d="M5 15V19"></path>
<path
d="M8 18V16C8 15.4477 8.44772 15 9 15H10C10.5523 15 11 15.4477 11 16V18C11 18.5523
10.5523 19 10 19H9C8.44772 19 8 18.5523 8 18Z"
></path>
</symbol>
<symbol id="play" viewBox="0 0 24 24">
<path
fill-rule="evenodd"
d="M4.5 5.653c0-1.426 1.529-2.33 2.779-1.643l11.54 6.348c1.295.712 1.295 2.573 0
3.285L7.28 19.991c-1.25.687-2.779-.217-2.779-1.643V5.653z"
clip-rule="evenodd"
/>
</symbol>
<symbol id="pause" viewBox="0 0 24 24">
<path
fill-rule="evenodd"
d="M6.75 5.25a.75.75 0 01.75-.75H9a.75.75 0 01.75.75v13.5a.75.75 0
01-.75.75H7.5a.75.75 0 01-.75-.75V5.25zm7.5 0A.75.75 0 0115 4.5h1.5a.75.75 0 01.75.75v13.5a.75.75 0
01-.75.75H15a.75.75 0 01-.75-.75V5.25z"
clip-rule="evenodd"
/>
</symbol>
<symbol id="forward" viewBox="0 0 24 24">
<path
d="M16 5L19 8M19 8L16 11M19 8H10.5C7.46243 8 5 10.4624 5 13.5C5 15.4826 5.85204 17.2202 7 18.188"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
></path>
<path d="M13 15V19" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
<path
d="M16 18V16C16 15.4477 16.4477 15 17 15H18C18.5523 15 19 15.4477 19 16V18C19 18.5523 18.5523 19 18
19H17C16.4477 19 16 18.5523 16 18Z"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
></path>
</symbol>
<symbol id="high" viewBox="0 0 24 24">
<path
d="M13.5 4.06c0-1.336-1.616-2.005-2.56-1.06l-4.5 4.5H4.508c-1.141 0-2.318.664-2.66 1.905A9.76 9.76 0
001.5 12c0 .898.121 1.768.35 2.595.341 1.24 1.518 1.905 2.659 1.905h1.93l4.5 4.5c.945.945 2.561.276
2.561-1.06V4.06zM18.584 5.106a.75.75 0 011.06 0c3.808 3.807 3.808 9.98 0 13.788a.75.75 0 11-1.06-1.06
8.25 8.25 0 000-11.668.75.75 0 010-1.06z"
></path>
<path
d="M15.932 7.757a.75.75 0 011.061 0 6 6 0 010 8.486.75.75 0 01-1.06-1.061 4.5 4.5 0 000-6.364.75.75 0
010-1.06z"
></path>
</symbol>
<symbol id="off" viewBox="0 0 24 24">
<path
d="M13.5 4.06c0-1.336-1.616-2.005-2.56-1.06l-4.5 4.5H4.508c-1.141 0-2.318.664-2.66 1.905A9.76 9.76 0
001.5 12c0 .898.121 1.768.35 2.595.341 1.24 1.518 1.905 2.659 1.905h1.93l4.5 4.5c.945.945 2.561.276
2.561-1.06V4.06zM17.78 9.22a.75.75 0 10-1.06 1.06L18.44 12l-1.72 1.72a.75.75 0 001.06 1.06l1.72-1.72 1.72
1.72a.75.75 0 101.06-1.06L20.56 12l1.72-1.72a.75.75 0 00-1.06-1.06l-1.72 1.72-1.72-1.72z"
/>
</symbol>
</svg>
<media-controller
audio
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
class="@container block w-full shadow-xl shadow-black/5"
style="
--media-background-color: transparent;
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-tooltip-display: none;
"
>
<slot name="media" slot="media"></slot>
<media-time-range
class="block @md:hidden w-full h-2 min-h-0 p-0 bg-slate-50 focus-visible:ring-slate-700 focus-visible:ring-2"
style="
--media-range-track-background: transparent;
--media-time-range-buffered-color: rgb(0 0 0 / 0.02);
--media-range-bar-color: var(--media-accent-color, rgb(79 70 229));
--media-range-track-height: 0.5rem;
--media-range-thumb-background: var(--media-accent-color, rgb(79 70 229));
--media-range-thumb-box-shadow: 0 0 0 2px var(--media-secondary-color, rgb(255 255 255 / 0.9));
--media-range-thumb-width: 0.25rem;
--media-range-thumb-height: 1rem;
--media-preview-time-text-shadow: transparent;
"
>
<media-preview-time-display
slot="preview"
class="text-slate-600 text-xs"
></media-preview-time-display>
</media-time-range>
<media-control-bar
class="h-20 @md:h-16 px-4 w-full flex items-center justify-between @md:rounded-md @md:ring-1 @md:ring-slate-700/10 bg-secondary"
>
<media-seek-backward-button
seekoffset="10"
class="w-8 h-8 p-0 group rounded-full focus:outline-none focus-visible:ring-slate-700 focus-visible:ring-2"
>
<svg
slot="icon"
aria-hidden="true"
class="w-7 h-7 fill-none stroke-slate-500 group-hover:stroke-slate-700"
>
<use href="#backward" />
</svg>
</media-seek-backward-button>
<media-play-button
class="h-10 w-10 p-2 mx-3 rounded-full bg-slate-700 hover:bg-slate-900 focus:outline-none focus:ring-slate-700 focus:ring-2 focus:ring-offset-2"
style="--media-primary-color: #fff"
>
<svg slot="play" aria-hidden="true" class="relative left-px">
<use href="#play" />
</svg>
<svg slot="pause" aria-hidden="true">
<use href="#pause" />
</svg>
</media-play-button>
<media-seek-forward-button
seekoffset="10"
class="w-8 h-8 p-0 group relative rounded-full focus:outline-none focus-visible:ring-slate-700 focus-visible:ring-2"
>
<svg
slot="icon"
aria-hidden="true"
class="w-7 h-7 fill-none stroke-slate-500 group-hover:stroke-slate-700"
>
<use href="#forward" />
</svg>
</media-seek-forward-button>
<div class="hidden @md:block h-full border-l border-slate-700/10 mx-4"></div>
<media-time-display
class="hidden @md:block text-slate-500 text-sm rounded-md focus:outline-none focus:ring-slate-700 focus:ring-2"
></media-time-display>
<media-time-range
class="hidden @md:block h-2 min-h-0 p-0 m-2 rounded-md bg-slate-50 focus-visible:ring-slate-700 focus-visible:ring-2"
style="
--media-range-track-background: transparent;
--media-time-buffered-color: rgb(0 0 0 / 0.02);
--media-range-bar-color: var(--media-accent-color, rgb(79 70 229));
--media-range-track-border-radius: 4px;
--media-range-track-height: 0.5rem;
--media-range-thumb-background: var(--media-accent-color, rgb(79 70 229));
--media-range-thumb-box-shadow: 0 0 0 2px var(--media-secondary-color, rgb(255 255 255 / 0.9));
--media-range-thumb-width: 0.25rem;
--media-range-thumb-height: 1rem;
--media-preview-time-text-shadow: transparent;
"
>
<media-preview-time-display
slot="preview"
class="text-slate-600 text-xs"
></media-preview-time-display>
</media-time-range>
<media-duration-display
class="hidden @md:block text-slate-500 text-sm"
></media-duration-display>
<media-playback-rate-button
class="text-slate-500 rounded-md focus:outline-none focus-visible:ring-slate-700 focus-visible:ring-2"
></media-playback-rate-button>
<media-mute-button
class="group relative order-first @md:order-none rounded-md focus:outline-none focus-visible:ring-slate-700 focus-visible:ring-2"
>
<svg
slot="high"
aria-hidden="true"
class="h-5 w-5 fill-slate-500 stroke-slate-500 group-hover:fill-slate-700 group-hover:stroke-slate-700"
>
<use href="#high" />
</svg>
<svg
slot="medium"
aria-hidden="true"
class="h-5 w-5 fill-slate-500 stroke-slate-500 group-hover:fill-slate-700 group-hover:stroke-slate-700"
>
<use href="#high" />
</svg>
<svg
slot="low"
aria-hidden="true"
class="h-5 w-5 fill-slate-500 stroke-slate-500 group-hover:fill-slate-700 group-hover:stroke-slate-700"
>
<use href="#high" />
</svg>
<svg
slot="off"
aria-hidden="true"
class="h-5 w-5 fill-slate-500 stroke-slate-500 group-hover:fill-slate-700 group-hover:stroke-slate-700"
>
<use href="#off" />
</svg>
</media-mute-button>
</media-control-bar>
</media-controller>

View File

@@ -0,0 +1,37 @@
# Changelog
## [0.0.7](https://github.com/muxinc/player.style/compare/@player.style/vimeonova@0.0.6...@player.style/vimeonova@0.0.7) (2024-09-10)
### Features
* add Sutro audio theme ([#65](https://github.com/muxinc/player.style/issues/65)) ([1ec5d61](https://github.com/muxinc/player.style/commit/1ec5d61b223138b1f668ec1d593189e2717a7279))
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.3 to ^0.0.4
## [0.0.6](https://github.com/muxinc/player.style/compare/@player.style/vimeonova-v0.0.5...@player.style/vimeonova@0.0.6) (2024-08-15)
### Features
* add Vimeonova theme ([#44](https://github.com/muxinc/player.style/issues/44)) ([e421c28](https://github.com/muxinc/player.style/commit/e421c28ae88a16fce65c6beca0e778d01fc1a353))
### Bug Fixes
* add Vimeonova color support ([#54](https://github.com/muxinc/player.style/issues/54)) ([e954611](https://github.com/muxinc/player.style/commit/e9546111a87a1974da018fe95d1f50c5fed25720))
* responsive fullscreen ([#61](https://github.com/muxinc/player.style/issues/61)) ([05343b8](https://github.com/muxinc/player.style/commit/05343b8ddfe6eafec255384d8ab40b63b1a724f0)), closes [#59](https://github.com/muxinc/player.style/issues/59)
* upgrade to Media Chrome v4 ([#64](https://github.com/muxinc/player.style/issues/64)) ([be68af2](https://github.com/muxinc/player.style/commit/be68af2f9c3a6ff6674b9951f0b34f2bfdb042aa))
* vimeonova issues ([48fa5ff](https://github.com/muxinc/player.style/commit/48fa5ffe4f922468a6fc3518a9fbbb2b2b322084))
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.2 to ^0.0.3

View File

@@ -0,0 +1,13 @@
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
declare global {
interface HTMLElementTagNameMap {
'media-theme-vimeonova': MediaThemeVimeonovaElement;
}
}
declare class MediaThemeVimeonovaElement extends MediaThemeElement {
static template: HTMLTemplateElement;
}
export default MediaThemeVimeonovaElement;

View File

@@ -0,0 +1,657 @@
<style>
:host {
--vimeonova-black: 23 35 34;
--vimeonova-primary-color: var(--media-primary-color, rgb(253 244 255));
--vimeonova-secondary-color: var(--media-secondary-color, rgb(--vimeonova-black / 0.75));
--vimeonova-accent-color: var(--media-accent-color, rgb(0 186 115));
--vimeonova-control-bar-height: 32px;
--vimeonova-control-bar-border-radius: 0.125rem;
--vimeonova-play-button-border-radius: 0.25rem;
--media-control-background: var(--vimeonova-secondary-color);
--media-control-hover-background: var(--vimeonova-secondary-color);
--media-icon-color: var(--vimeonova-primary-color);
--media-menu-border-radius: 0.25rem;
--media-tooltip-display: none;
color: var(--vimeonova-primary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
:host {
--vimeonova-secondary-color: color-mix(in srgb, var(--media-secondary-color, rgb(23 35 34)) 75%, transparent);
}
}
media-controller {
display: block;
container: media-theme-vimeonova / inline-size;
}
.hidden {
display: none;
}
.header {
display: flex;
flex-direction: column;
align-items: flex-start;
row-gap: 1px;
margin: 0.625rem;
}
.title,
.byline {
display: inline-block;
background: var(--vimeonova-secondary-color);
margin: 0;
padding: 0.15rem 0.2rem;
line-height: 1;
font-size: 0.8rem;
font-weight: normal;
}
.title {
color: var(--vimeonova-accent-color);
font-size: 1.3rem;
font-weight: bold;
}
.byline {
color: var(--vimeonova-accent-color);
}
.control-bar-container {
position: relative;
overflow: visible;
display: flex;
align-items: end;
padding: 0.35rem;
width: 100%;
box-sizing: border-box;
}
@container (inline-size >=384px) {
.control-bar-container {
column-gap: 0.625rem;
padding: 0.625rem;
}
}
.control-bar-right {
flex-grow: 1;
}
media-control-bar {
background: var(--media-control-background);
height: var(--vimeonova-control-bar-height);
border-bottom-left-radius: var(--vimeonova-control-bar-border-radius);
border-bottom-right-radius: var(--vimeonova-control-bar-border-radius);
width: 100%;
}
media-control-bar [role='button'],
media-control-bar [role='switch'] {
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-button-icon-active-transform: scale(1.2);
--media-button-icon-transition: transform 0.2s ease;
color: var(--vimeonova-primary-color);
padding: 0.3125rem 0.35rem;
}
media-control-bar svg {
fill: none;
}
media-control-bar svg:active {
transform: scale(1.2);
}
media-play-button {
--media-control-background: var(--vimeonova-secondary-color);
--media-control-hover-background: var(--vimeonova-accent-color);
--media-button-icon-height: 100%;
display: none;
border-radius: var(--vimeonova-play-button-border-radius);
color: var(--vimeonova-primary-color);
width: 65px;
flex: 0 0 65px;
padding: 0.3125rem 0.625rem;
aspect-ratio: 16 / 10;
}
[slot='centered-chrome'] media-play-button {
display: block;
position: relative;
top: -30%;
}
media-play-button:active {
--media-control-hover-background: var(--vimeonova-accent-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
media-play-button:active {
--media-control-hover-background: color-mix(in srgb, var(--vimeonova-accent-color) 80%, transparent);
}
}
media-time-range {
--media-range-padding: 0;
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-time-range-buffered-color: dimgray;
--media-range-track-background: rgb(var(--vimeonova-black) / 0.5);
--media-range-track-border-radius: 0;
--media-range-bar-color: var(--vimeonova-accent-color);
--media-range-thumb-background: none;
--media-range-thumb-width: 0px;
--media-range-thumb-height: 0px;
--media-range-track-height: 10px;
--media-range-track-transition: height 0.2s ease;
--media-preview-thumbnail-border-radius: 2px;
--media-preview-thumbnail-border: 4px solid var(--vimeonova-secondary-color);
--media-box-margin: 0;
--media-preview-time-background: rgb(var(--vimeonova-black) / 1);
padding-inline: 10px;
z-index: 1;
}
media-time-range.small {
--media-box-padding-left: 2px;
--media-box-padding-right: 2px;
--media-range-track-height: 5px;
--media-range-track-border-radius: var(--vimeonova-control-bar-border-radius)
var(--vimeonova-control-bar-border-radius) 0 0;
height: 5px;
width: 100%;
padding: 0;
}
@keyframes buffer {
100% {
--media-range-track-background: rgb(var(--vimeonova-black) / 0.5)
url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="100%"><style>@keyframes buffer { 100% { transform: translateX(-10px); }}%3C/style><defs><pattern id="buffer-pattern" patternUnits="userSpaceOnUse" x="0" y="0" width="10" height="10" viewBox="0 0 10 10"><line x1="5" y1="-1" x2="-5" y2="10" stroke-width="2" stroke="dimgray" stroke-linecap="butt" /><line x1="10" y1="-1" x2="0" y2="10" stroke-width="2" stroke="dimgray" stroke-linecap="butt" /><line x1="15" y1="-1" x2="5" y2="10" stroke-width="2" stroke="dimgray" stroke-linecap="butt" /></pattern></defs><rect width="110%" height="100%" fill="url(%23buffer-pattern)" style="animation: buffer 250ms linear infinite;" /></svg>');
}
}
[medialoading]:not([mediapaused]) media-time-range {
animation: 1000000s 0.5s buffer reverse;
}
media-time-range.large {
display: none;
height: var(--vimeonova-control-bar-height);
flex-grow: 10000;
}
media-time-range > * {
position: relative;
bottom: -11px;
}
media-time-range.small > * {
bottom: 3px;
}
@container (inline-size >=384px) {
[slot='centered-chrome'] media-play-button {
display: none;
}
.control-bar-container media-play-button {
display: block;
}
media-time-range.small {
border-top-left-radius: var(--vimeonova-control-bar-border-radius);
border-top-right-radius: var(--vimeonova-control-bar-border-radius);
}
}
@container (inline-size >=484px) {
media-control-bar {
border-radius: var(--vimeonova-control-bar-border-radius);
}
media-time-range.small {
display: none;
}
media-time-range.large {
display: block;
}
}
media-preview-time-display,
media-time-display {
--media-preview-time-background: var(--vimeonova-primary-color);
padding: 2px 4px;
border-radius: 0;
line-height: normal;
color: rgb(var(--vimeonova-black) / 1);
font-family: Verdana, sans-serif;
font-size: 10px;
box-shadow: rgb(0 0 0 / 0.7) 1px 1px 0px 0px;
text-shadow: none;
}
media-preview-thumbnail {
max-width: 213px;
max-height: 200px;
}
media-preview-time-display {
margin-top: 5px;
min-width: auto;
--media-preview-time-background: rgb(var(--vimeonova-black) / 1);
color: var(--vimeonova-primary-color);
}
[part='arrow'] {
--media-box-arrow-background: rgb(var(--vimeonova-black) / 1);
--media-box-arrow-height: 4px;
--media-box-arrow-width: 4px;
--media-box-arrow-offset: 0px;
left: 1px;
}
[part='arrow'][slot='current']::before {
--media-box-arrow-background: var(--vimeonova-primary-color);
}
[part='arrow']::before {
content: '';
border-color: transparent;
border-top-color: var(--media-box-arrow-background, var(--_control-background));
border-width: var(
--media-box-arrow-border-width,
var(--media-box-arrow-height, 5px) var(--media-box-arrow-width, 6px) 0
);
border-style: solid;
position: absolute;
bottom: 0.5px;
margin-left: calc((var(--media-box-arrow-width) + 1px) * -1);
}
media-volume-range {
--media-range-track-background-color: rgb(var(--vimeonova-black) / 0.8);
--media-range-track-border-radius: 1px;
--media-range-bar-color: var(--vimeonova-accent-color);
--media-range-thumb-background: none;
--media-range-thumb-width: 0px;
--media-range-thumb-height: 0px;
--media-range-track-height: 6px;
height: var(--vimeonova-control-bar-height);
background: var(--vimeonova-secondary-color);
border-radius: var(--media-menu-border-radius);
}
.media-volume-wrapper {
position: relative;
}
.media-volume-range-wrapper {
width: 122px;
height: 34px;
overflow: hidden;
opacity: 0;
transform: rotate(-90deg);
position: absolute;
top: -80px;
left: -52px;
border-left: 16px solid transparent;
visibility: hidden;
}
@container (inline-size >=484px) {
.media-volume-range-wrapper {
top: -77px;
}
}
media-mute-button:hover + .media-volume-range-wrapper,
media-mute-button:focus + .media-volume-range-wrapper,
media-mute-button:focus-within + .media-volume-range-wrapper,
.media-volume-range-wrapper:hover,
.media-volume-range-wrapper:focus,
.media-volume-range-wrapper:focus-within {
opacity: 1;
visibility: visible;
}
[role='menu'] {
position: absolute;
margin-bottom: 10px;
}
@container (inline-size >=484px) {
[role='menu'] {
margin-bottom: 7px;
}
}
.spacer {
flex-grow: 1;
height: 100%;
}
</style>
<media-controller
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<div slot="top-chrome" class="header">
<template if="mediatitle">
<h1 class="title">{{mediatitle}}</h1>
</template>
<template if="mediabyline">
<h2 class="byline">{{mediabyline}}</h2>
</template>
</div>
<div slot="centered-chrome">
<media-play-button>
<svg
slot="play"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M7 4v16l13 -8z"></path>
</svg>
<svg
slot="pause"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<rect x="6" y="5" width="4" height="14" rx="0"></rect>
<rect x="14" y="5" width="4" height="14" rx="0"></rect>
</svg>
</media-play-button>
</div>
<div class="control-bar-container" id="vimeonova-bounds">
<media-play-button>
<svg
slot="play"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M7 4v16l13 -8z"></path>
</svg>
<svg
slot="pause"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<rect x="6" y="5" width="4" height="14" rx="0"></rect>
<rect x="14" y="5" width="4" height="14" rx="0"></rect>
</svg>
</media-play-button>
<div class="control-bar-right">
<media-time-range class="small">
<media-preview-time-display slot="preview"></media-preview-time-display>
<div part="arrow" slot="preview"></div>
<media-time-display slot="current"></media-time-display>
<div part="arrow" slot="current"></div>
</media-time-range>
<media-control-bar>
<media-time-range class="large" bounds="vimeonova-bounds">
<media-preview-thumbnail slot="preview"></media-preview-thumbnail>
<media-preview-time-display slot="preview"></media-preview-time-display>
<div part="arrow" slot="preview"></div>
<media-time-display slot="current"></media-time-display>
<div part="arrow" slot="current"></div>
</media-time-range>
<div class="spacer"></div>
<media-captions-menu-button>
<svg slot="on" aria-hidden="true" fill="none" viewBox="0 0 24 24">
<path
fill="currentColor"
fill-rule="evenodd"
d="M2 8a4 4 0 0 1 4-4h12a4 4 0 0 1 4 4v7a4 4 0 0 1-4 4h-.532l-2.2 2.64a1 1 0 0 1-1.536 0l-2.2-2.64H5.999A4 4 0 0 1 2 15V8Zm13.57.183a3.333 3.333 0 0 1 2.338.826.82.82 0 0 1-1.083 1.232 1.693 1.693 0 0 0-2.336.097 1.674 1.674 0 0 0 0 2.324 1.692 1.692 0 0 0 2.336.097.82.82 0 0 1 1.083 1.232 3.333 3.333 0 0 1-4.6-.191 3.314 3.314 0 0 1 0-4.6m2.261-1.017c-.856.035-1.666.4-2.261 1.017Zm-6.7-.005a3.338 3.338 0 0 1 2.342.828.825.825 0 0 1-1.089 1.239 1.688 1.688 0 0 0-2.33.097 1.669 1.669 0 0 0 0 2.316 1.688 1.688 0 0 0 2.33.097.825.825 0 1 1 1.09 1.24 3.338 3.338 0 0 1-4.608-.192 3.319 3.319 0 0 1 0-4.606m2.265-1.02a3.347 3.347 0 0 0-2.265 1.02Z"
clip-rule="evenodd"
/>
</svg>
<svg slot="off" aria-hidden="true" fill="none" viewBox="0 0 24 24">
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.6"
d="M17.367 9.625a2.513 2.513 0 0 0-3.469.144 2.494 2.494 0 0 0 0 3.461 2.513 2.513 0 0 0 3.469.145m-6.7-3.75a2.513 2.513 0 0 0-3.469.144 2.494 2.494 0 0 0 0 3.461 2.512 2.512 0 0 0 3.469.145"
/>
<path
fill="currentColor"
d="M17 18v-1h-.468l-.3.36L17 18Zm-5 0 .768-.64-.3-.36H12v1Zm2.5 3-.768.64a1 1 0 0 0 1.536 0L14.5 21ZM6 6h12V4H6v2Zm14 2v7h2V8h-2ZM4 15V8H2v7h2Zm14 2h-1v2h1v-2Zm-6 0H6v2h6v-2Zm4.232.36-2.5 3 1.536 1.28 2.5-3-1.536-1.28Zm-.964 3-2.5-3-1.536 1.28 2.5 3 1.536-1.28ZM2 15a4 4 0 0 0 4 4v-2a2 2 0 0 1-2-2H2Zm18 0a2 2 0 0 1-2 2v2a4 4 0 0 0 4-4h-2Zm-2-9a2 2 0 0 1 2 2h2a4 4 0 0 0-4-4v2ZM6 4a4 4 0 0 0-4 4h2a2 2 0 0 1 2-2V4Z"
/>
</svg>
</media-captions-menu-button>
<media-playback-rate-menu-button></media-playback-rate-menu-button>
<div class="media-volume-wrapper">
<media-mute-button>
<svg
slot="high"
aria-hidden="true"
viewBox="0 0 24 25"
stroke-width="1.8"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M15 8a5 5 0 0 1 0 8"></path>
<path d="M17.7 5a9 9 0 0 1 0 14"></path>
<path
d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"
fill="currentColor"
></path>
</svg>
<svg
slot="medium"
aria-hidden="true"
viewBox="0 0 24 25"
stroke-width="1.8"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M15 8a5 5 0 0 1 0 8"></path>
<path d="M17.7 5a9 9 0 0 1 0 14"></path>
<path
d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"
fill="currentColor"
></path>
</svg>
<svg
slot="low"
aria-hidden="true"
viewBox="0 0 24 25"
stroke-width="1.8"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M15 8a5 5 0 0 1 0 8"></path>
<path
d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"
fill="currentColor"
></path>
</svg>
<svg
slot="off"
aria-hidden="true"
viewBox="0 0 24 25"
stroke-width="1.8"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path
d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"
></path>
<path d="M16 10l4 4m0 -4l-4 4"></path>
</svg>
</media-mute-button>
<div class="media-volume-range-wrapper">
<media-volume-range></media-volume-range>
</div>
</div>
<media-rendition-menu-button>
<svg slot="icon" class="media-hd-icon" aria-hidden="true" viewBox="0 0 28 24">
<path
fill="currentColor"
d="M19.866 18.971h-5.458L16.728 5h5.239c1.437 0 2.638.289 3.602.866.964.578 1.648 1.403 2.053 2.477.405 1.073.485 2.351.239 3.834-.237 1.428-.716 2.649-1.44 3.663a7.076 7.076 0 0 1-2.756 2.326c-1.114.537-2.38.805-3.8.805Zm-1.133-3.22h1.378c.691 0 1.308-.12 1.849-.361.546-.246 1-.655 1.364-1.228.369-.578.635-1.367.798-2.367.155-.946.15-1.676-.013-2.19-.164-.519-.476-.878-.935-1.078-.46-.205-1.053-.307-1.78-.307h-1.406l-1.255 7.531ZM0 18.971 2.32 5h3.792l-.9 5.458h5.02L11.134 5h3.794l-2.32 13.971H8.814l.9-5.457h-5.02l-.901 5.457H0Z"
/>
</svg>
<svg slot="icon" class="media-sd-icon hidden" aria-hidden="true" viewBox="0 0 28 24">
<path
fill="currentColor"
d="M19.857 18.967H14.41L16.725 5.02h5.23c1.434 0 2.633.288 3.595.864.962.577 1.646 1.401 2.05 2.472.404 1.072.483 2.347.238 3.827-.236 1.426-.715 2.645-1.437 3.657a7.062 7.062 0 0 1-2.75 2.322c-1.113.536-2.377.804-3.794.804Zm-1.13-3.214h1.375c.69 0 1.306-.12 1.846-.361.545-.246.999-.654 1.362-1.226.367-.577.633-1.364.797-2.363.154-.944.15-1.673-.014-2.186-.164-.517-.474-.876-.933-1.076-.459-.204-1.051-.306-1.777-.306H19.98l-1.253 7.518Zm-8.496-6.374c.041-.45-.068-.801-.327-1.056-.258-.258-.694-.388-1.307-.388-.39 0-.717.046-.98.136-.26.091-.461.216-.607.375-.14.159-.229.343-.265.551a.792.792 0 0 0 .007.45.85.85 0 0 0 .279.36c.14.11.324.207.551.294.232.086.507.163.824.231l1.09.245c.744.164 1.369.38 1.872.647.509.263.909.577 1.199.94.29.363.481.77.572 1.219.095.45.098.94.007 1.47-.155.918-.51 1.694-1.07 2.33-.558.635-1.286 1.119-2.185 1.45-.899.331-1.939.497-3.119.497-1.207 0-2.233-.18-3.078-.538-.84-.363-1.448-.917-1.825-1.662-.372-.748-.463-1.704-.272-2.866h3.595c-.054.426-.009.785.136 1.076.146.29.38.51.702.66.322.15.724.225 1.205.225.409 0 .758-.05 1.049-.15.29-.1.52-.238.688-.415.168-.177.27-.38.306-.606a.741.741 0 0 0-.109-.559c-.109-.163-.306-.31-.592-.442s-.68-.252-1.178-.361l-1.335-.3c-1.185-.272-2.08-.722-2.683-1.348-.604-.627-.817-1.485-.64-2.574.145-.89.51-1.666 1.096-2.329.59-.667 1.34-1.185 2.247-1.553.913-.372 1.923-.558 3.03-.558 1.126 0 2.068.188 2.826.565.763.377 1.31.906 1.642 1.587.336.68.426 1.48.272 2.397h-3.623Z"
/>
</svg>
<svg slot="icon" class="media-4k-icon hidden" aria-hidden="true" viewBox="0 0 28 24">
<path
fill="currentColor"
d="M13.163 18.887 15.47 5h3.77l-.922 5.615h.19L23.606 5H28l-5.696 6.184 3.499 7.703H21.3l-2.224-5.207-1.546 1.654-.596 3.553h-3.77ZM0 16.717l.488-2.929L7.54 5h2.658l-.65 3.906h-1.52L4.232 13.68l-.027.108h8.246l-.489 2.93H0Zm6.401 2.17.516-3.065.298-1.274L8.788 5h3.526L10.01 18.887H6.4Z"
/>
</svg>
</media-rendition-menu-button>
<media-pip-button>
<svg
slot="enter"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M11 19h-6a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v4"></path>
<rect x="14" y="14" width="7" height="5" rx="1" fill="currentColor"></rect>
<line x1="7" y1="9" x2="11" y2="13"></line>
<path d="M8 13h3v-3"></path>
</svg>
<svg
slot="exit"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M11 19h-6a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v4"></path>
<rect x="14" y="14" width="7" height="5" rx="1" fill="currentColor"></rect>
<line x1="7" y1="9" x2="11" y2="13"></line>
<path d="M7 12v-3h3"></path>
</svg>
</media-pip-button>
<media-airplay-button></media-airplay-button>
<media-cast-button>
<svg
slot="enter"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<line x1="3" y1="19" x2="3.01" y2="19"></line>
<path d="M7 19a4 4 0 0 0 -4 -4"></path>
<path d="M11 19a8 8 0 0 0 -8 -8"></path>
<path d="M15 19h3a3 3 0 0 0 3 -3v-8a3 3 0 0 0 -3 -3h-12a3 3 0 0 0 -2.8 2"></path>
</svg>
<svg
slot="exit"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M3 19h.01"></path>
<path d="M7 19a4 4 0 0 0 -4 -4"></path>
<path d="M11 19a8 8 0 0 0 -8 -8"></path>
<path
d="M15 19h3a3 3 0 0 0 .875 -.13m1.997 -2.002a3 3 0 0 0 .128 -.868v-8a3 3 0 0 0 -3 -3h-9m-3.865 .136a3 3 0 0 0 -1.935 1.864"
></path>
<path d="M3 3l18 18"></path>
</svg>
</media-cast-button>
<media-fullscreen-button>
<svg slot="enter" aria-hidden="true" fill="none" viewBox="0 0 24 24">
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 5h4v4M15 9l4-4M9 19H5v-4M5 19l4-4M15 19h4v-4M15 15l4 4M9 5H5v4M5 5l4 4"
/>
</svg>
<svg slot="exit" aria-hidden="true" fill="none" viewBox="0 0 24 24">
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5 9h4V5M4.5 4.5 9 9M5 15h4v4M4.5 19.5 9 15M19 9h-4V5M15 9l4.5-4.5M19 15h-4v4M15 15l4.5 4.5"
/>
</svg>
</media-fullscreen-button>
</media-control-bar>
</div>
</div>
<media-captions-menu anchor="auto" hidden></media-captions-menu>
<media-playback-rate-menu anchor="auto" hidden></media-playback-rate-menu>
<media-rendition-menu anchor="auto" hidden></media-rendition-menu>
</media-controller>

View File

@@ -0,0 +1,687 @@
/*
<media-theme-vimeonova>
<video
slot="media"
src="https://stream.mux.com/fXNzVtmtWuyz00xnSrJg4OJH6PyNo6D02UzmgeKGkP5YQ/high.mp4"
></video>
</media-theme-vimeonova>
*/
import 'media-chrome';
import { globalThis } from 'media-chrome/dist/utils/server-safe-globals.js';
import { MediaThemeElement } from 'media-chrome/dist/media-theme-element.js';
import 'media-chrome/dist/menu/index.js';
const template = globalThis.document?.createElement?.('template');
if (template) {
template.innerHTML = /*html*/`
<style>
:host {
--vimeonova-black: 23 35 34;
--vimeonova-primary-color: var(--media-primary-color, rgb(253 244 255));
--vimeonova-secondary-color: var(--media-secondary-color, rgb(--vimeonova-black / 0.75));
--vimeonova-accent-color: var(--media-accent-color, rgb(0 186 115));
--vimeonova-control-bar-height: 32px;
--vimeonova-control-bar-border-radius: 0.125rem;
--vimeonova-play-button-border-radius: 0.25rem;
--media-control-background: var(--vimeonova-secondary-color);
--media-control-hover-background: var(--vimeonova-secondary-color);
--media-icon-color: var(--vimeonova-primary-color);
--media-menu-border-radius: 0.25rem;
--media-tooltip-display: none;
color: var(--vimeonova-primary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
:host {
--vimeonova-secondary-color: color-mix(in srgb, var(--media-secondary-color, rgb(23 35 34)) 75%, transparent);
}
}
media-controller {
display: block;
container: media-theme-vimeonova / inline-size;
}
.hidden {
display: none;
}
.header {
display: flex;
flex-direction: column;
align-items: flex-start;
row-gap: 1px;
margin: 0.625rem;
}
.title,
.byline {
display: inline-block;
background: var(--vimeonova-secondary-color);
margin: 0;
padding: 0.15rem 0.2rem;
line-height: 1;
font-size: 0.8rem;
font-weight: normal;
}
.title {
color: var(--vimeonova-accent-color);
font-size: 1.3rem;
font-weight: bold;
}
.byline {
color: var(--vimeonova-accent-color);
}
.control-bar-container {
position: relative;
overflow: visible;
display: flex;
align-items: end;
padding: 0.35rem;
width: 100%;
box-sizing: border-box;
}
@container (inline-size >=384px) {
.control-bar-container {
column-gap: 0.625rem;
padding: 0.625rem;
}
}
.control-bar-right {
flex-grow: 1;
}
media-control-bar {
background: var(--media-control-background);
height: var(--vimeonova-control-bar-height);
border-bottom-left-radius: var(--vimeonova-control-bar-border-radius);
border-bottom-right-radius: var(--vimeonova-control-bar-border-radius);
width: 100%;
}
media-control-bar [role='button'],
media-control-bar [role='switch'] {
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-button-icon-active-transform: scale(1.2);
--media-button-icon-transition: transform 0.2s ease;
color: var(--vimeonova-primary-color);
padding: 0.3125rem 0.35rem;
}
media-control-bar svg {
fill: none;
}
media-control-bar svg:active {
transform: scale(1.2);
}
media-play-button {
--media-control-background: var(--vimeonova-secondary-color);
--media-control-hover-background: var(--vimeonova-accent-color);
--media-button-icon-height: 100%;
display: none;
border-radius: var(--vimeonova-play-button-border-radius);
color: var(--vimeonova-primary-color);
width: 65px;
flex: 0 0 65px;
padding: 0.3125rem 0.625rem;
aspect-ratio: 16 / 10;
}
[slot='centered-chrome'] media-play-button {
display: block;
position: relative;
top: -30%;
}
media-play-button:active {
--media-control-hover-background: var(--vimeonova-accent-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
media-play-button:active {
--media-control-hover-background: color-mix(in srgb, var(--vimeonova-accent-color) 80%, transparent);
}
}
media-time-range {
--media-range-padding: 0;
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-time-range-buffered-color: dimgray;
--media-range-track-background: rgb(var(--vimeonova-black) / 0.5);
--media-range-track-border-radius: 0;
--media-range-bar-color: var(--vimeonova-accent-color);
--media-range-thumb-background: none;
--media-range-thumb-width: 0px;
--media-range-thumb-height: 0px;
--media-range-track-height: 10px;
--media-range-track-transition: height 0.2s ease;
--media-preview-thumbnail-border-radius: 2px;
--media-preview-thumbnail-border: 4px solid var(--vimeonova-secondary-color);
--media-box-margin: 0;
--media-preview-time-background: rgb(var(--vimeonova-black) / 1);
padding-inline: 10px;
z-index: 1;
}
media-time-range.small {
--media-box-padding-left: 2px;
--media-box-padding-right: 2px;
--media-range-track-height: 5px;
--media-range-track-border-radius: var(--vimeonova-control-bar-border-radius)
var(--vimeonova-control-bar-border-radius) 0 0;
height: 5px;
width: 100%;
padding: 0;
}
@keyframes buffer {
100% {
--media-range-track-background: rgb(var(--vimeonova-black) / 0.5)
url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="100%"><style>@keyframes buffer { 100% { transform: translateX(-10px); }}%3C/style><defs><pattern id="buffer-pattern" patternUnits="userSpaceOnUse" x="0" y="0" width="10" height="10" viewBox="0 0 10 10"><line x1="5" y1="-1" x2="-5" y2="10" stroke-width="2" stroke="dimgray" stroke-linecap="butt" /><line x1="10" y1="-1" x2="0" y2="10" stroke-width="2" stroke="dimgray" stroke-linecap="butt" /><line x1="15" y1="-1" x2="5" y2="10" stroke-width="2" stroke="dimgray" stroke-linecap="butt" /></pattern></defs><rect width="110%" height="100%" fill="url(%23buffer-pattern)" style="animation: buffer 250ms linear infinite;" /></svg>');
}
}
[medialoading]:not([mediapaused]) media-time-range {
animation: 1000000s 0.5s buffer reverse;
}
media-time-range.large {
display: none;
height: var(--vimeonova-control-bar-height);
flex-grow: 10000;
}
media-time-range > * {
position: relative;
bottom: -11px;
}
media-time-range.small > * {
bottom: 3px;
}
@container (inline-size >=384px) {
[slot='centered-chrome'] media-play-button {
display: none;
}
.control-bar-container media-play-button {
display: block;
}
media-time-range.small {
border-top-left-radius: var(--vimeonova-control-bar-border-radius);
border-top-right-radius: var(--vimeonova-control-bar-border-radius);
}
}
@container (inline-size >=484px) {
media-control-bar {
border-radius: var(--vimeonova-control-bar-border-radius);
}
media-time-range.small {
display: none;
}
media-time-range.large {
display: block;
}
}
media-preview-time-display,
media-time-display {
--media-preview-time-background: var(--vimeonova-primary-color);
padding: 2px 4px;
border-radius: 0;
line-height: normal;
color: rgb(var(--vimeonova-black) / 1);
font-family: Verdana, sans-serif;
font-size: 10px;
box-shadow: rgb(0 0 0 / 0.7) 1px 1px 0px 0px;
text-shadow: none;
}
media-preview-thumbnail {
max-width: 213px;
max-height: 200px;
}
media-preview-time-display {
margin-top: 5px;
min-width: auto;
--media-preview-time-background: rgb(var(--vimeonova-black) / 1);
color: var(--vimeonova-primary-color);
}
[part='arrow'] {
--media-box-arrow-background: rgb(var(--vimeonova-black) / 1);
--media-box-arrow-height: 4px;
--media-box-arrow-width: 4px;
--media-box-arrow-offset: 0px;
left: 1px;
}
[part='arrow'][slot='current']::before {
--media-box-arrow-background: var(--vimeonova-primary-color);
}
[part='arrow']::before {
content: '';
border-color: transparent;
border-top-color: var(--media-box-arrow-background, var(--_control-background));
border-width: var(
--media-box-arrow-border-width,
var(--media-box-arrow-height, 5px) var(--media-box-arrow-width, 6px) 0
);
border-style: solid;
position: absolute;
bottom: 0.5px;
margin-left: calc((var(--media-box-arrow-width) + 1px) * -1);
}
media-volume-range {
--media-range-track-background-color: rgb(var(--vimeonova-black) / 0.8);
--media-range-track-border-radius: 1px;
--media-range-bar-color: var(--vimeonova-accent-color);
--media-range-thumb-background: none;
--media-range-thumb-width: 0px;
--media-range-thumb-height: 0px;
--media-range-track-height: 6px;
height: var(--vimeonova-control-bar-height);
background: var(--vimeonova-secondary-color);
border-radius: var(--media-menu-border-radius);
}
.media-volume-wrapper {
position: relative;
}
.media-volume-range-wrapper {
width: 122px;
height: 34px;
overflow: hidden;
opacity: 0;
transform: rotate(-90deg);
position: absolute;
top: -80px;
left: -52px;
border-left: 16px solid transparent;
visibility: hidden;
}
@container (inline-size >=484px) {
.media-volume-range-wrapper {
top: -77px;
}
}
media-mute-button:hover + .media-volume-range-wrapper,
media-mute-button:focus + .media-volume-range-wrapper,
media-mute-button:focus-within + .media-volume-range-wrapper,
.media-volume-range-wrapper:hover,
.media-volume-range-wrapper:focus,
.media-volume-range-wrapper:focus-within {
opacity: 1;
visibility: visible;
}
[role='menu'] {
position: absolute;
margin-bottom: 10px;
}
@container (inline-size >=484px) {
[role='menu'] {
margin-bottom: 7px;
}
}
.spacer {
flex-grow: 1;
height: 100%;
}
</style>
<media-controller
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<div slot="top-chrome" class="header">
<template if="mediatitle">
<h1 class="title">{{mediatitle}}</h1>
</template>
<template if="mediabyline">
<h2 class="byline">{{mediabyline}}</h2>
</template>
</div>
<div slot="centered-chrome">
<media-play-button>
<svg
slot="play"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M7 4v16l13 -8z"></path>
</svg>
<svg
slot="pause"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<rect x="6" y="5" width="4" height="14" rx="0"></rect>
<rect x="14" y="5" width="4" height="14" rx="0"></rect>
</svg>
</media-play-button>
</div>
<div class="control-bar-container" id="vimeonova-bounds">
<media-play-button>
<svg
slot="play"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M7 4v16l13 -8z"></path>
</svg>
<svg
slot="pause"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<rect x="6" y="5" width="4" height="14" rx="0"></rect>
<rect x="14" y="5" width="4" height="14" rx="0"></rect>
</svg>
</media-play-button>
<div class="control-bar-right">
<media-time-range class="small">
<media-preview-time-display slot="preview"></media-preview-time-display>
<div part="arrow" slot="preview"></div>
<media-time-display slot="current"></media-time-display>
<div part="arrow" slot="current"></div>
</media-time-range>
<media-control-bar>
<media-time-range class="large" bounds="vimeonova-bounds">
<media-preview-thumbnail slot="preview"></media-preview-thumbnail>
<media-preview-time-display slot="preview"></media-preview-time-display>
<div part="arrow" slot="preview"></div>
<media-time-display slot="current"></media-time-display>
<div part="arrow" slot="current"></div>
</media-time-range>
<div class="spacer"></div>
<media-captions-menu-button>
<svg slot="on" aria-hidden="true" fill="none" viewBox="0 0 24 24">
<path
fill="currentColor"
fill-rule="evenodd"
d="M2 8a4 4 0 0 1 4-4h12a4 4 0 0 1 4 4v7a4 4 0 0 1-4 4h-.532l-2.2 2.64a1 1 0 0 1-1.536 0l-2.2-2.64H5.999A4 4 0 0 1 2 15V8Zm13.57.183a3.333 3.333 0 0 1 2.338.826.82.82 0 0 1-1.083 1.232 1.693 1.693 0 0 0-2.336.097 1.674 1.674 0 0 0 0 2.324 1.692 1.692 0 0 0 2.336.097.82.82 0 0 1 1.083 1.232 3.333 3.333 0 0 1-4.6-.191 3.314 3.314 0 0 1 0-4.6m2.261-1.017c-.856.035-1.666.4-2.261 1.017Zm-6.7-.005a3.338 3.338 0 0 1 2.342.828.825.825 0 0 1-1.089 1.239 1.688 1.688 0 0 0-2.33.097 1.669 1.669 0 0 0 0 2.316 1.688 1.688 0 0 0 2.33.097.825.825 0 1 1 1.09 1.24 3.338 3.338 0 0 1-4.608-.192 3.319 3.319 0 0 1 0-4.606m2.265-1.02a3.347 3.347 0 0 0-2.265 1.02Z"
clip-rule="evenodd"
/>
</svg>
<svg slot="off" aria-hidden="true" fill="none" viewBox="0 0 24 24">
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.6"
d="M17.367 9.625a2.513 2.513 0 0 0-3.469.144 2.494 2.494 0 0 0 0 3.461 2.513 2.513 0 0 0 3.469.145m-6.7-3.75a2.513 2.513 0 0 0-3.469.144 2.494 2.494 0 0 0 0 3.461 2.512 2.512 0 0 0 3.469.145"
/>
<path
fill="currentColor"
d="M17 18v-1h-.468l-.3.36L17 18Zm-5 0 .768-.64-.3-.36H12v1Zm2.5 3-.768.64a1 1 0 0 0 1.536 0L14.5 21ZM6 6h12V4H6v2Zm14 2v7h2V8h-2ZM4 15V8H2v7h2Zm14 2h-1v2h1v-2Zm-6 0H6v2h6v-2Zm4.232.36-2.5 3 1.536 1.28 2.5-3-1.536-1.28Zm-.964 3-2.5-3-1.536 1.28 2.5 3 1.536-1.28ZM2 15a4 4 0 0 0 4 4v-2a2 2 0 0 1-2-2H2Zm18 0a2 2 0 0 1-2 2v2a4 4 0 0 0 4-4h-2Zm-2-9a2 2 0 0 1 2 2h2a4 4 0 0 0-4-4v2ZM6 4a4 4 0 0 0-4 4h2a2 2 0 0 1 2-2V4Z"
/>
</svg>
</media-captions-menu-button>
<media-playback-rate-menu-button></media-playback-rate-menu-button>
<div class="media-volume-wrapper">
<media-mute-button>
<svg
slot="high"
aria-hidden="true"
viewBox="0 0 24 25"
stroke-width="1.8"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M15 8a5 5 0 0 1 0 8"></path>
<path d="M17.7 5a9 9 0 0 1 0 14"></path>
<path
d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"
fill="currentColor"
></path>
</svg>
<svg
slot="medium"
aria-hidden="true"
viewBox="0 0 24 25"
stroke-width="1.8"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M15 8a5 5 0 0 1 0 8"></path>
<path d="M17.7 5a9 9 0 0 1 0 14"></path>
<path
d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"
fill="currentColor"
></path>
</svg>
<svg
slot="low"
aria-hidden="true"
viewBox="0 0 24 25"
stroke-width="1.8"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M15 8a5 5 0 0 1 0 8"></path>
<path
d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"
fill="currentColor"
></path>
</svg>
<svg
slot="off"
aria-hidden="true"
viewBox="0 0 24 25"
stroke-width="1.8"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path
d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"
></path>
<path d="M16 10l4 4m0 -4l-4 4"></path>
</svg>
</media-mute-button>
<div class="media-volume-range-wrapper">
<media-volume-range></media-volume-range>
</div>
</div>
<media-rendition-menu-button>
<svg slot="icon" class="media-hd-icon" aria-hidden="true" viewBox="0 0 28 24">
<path
fill="currentColor"
d="M19.866 18.971h-5.458L16.728 5h5.239c1.437 0 2.638.289 3.602.866.964.578 1.648 1.403 2.053 2.477.405 1.073.485 2.351.239 3.834-.237 1.428-.716 2.649-1.44 3.663a7.076 7.076 0 0 1-2.756 2.326c-1.114.537-2.38.805-3.8.805Zm-1.133-3.22h1.378c.691 0 1.308-.12 1.849-.361.546-.246 1-.655 1.364-1.228.369-.578.635-1.367.798-2.367.155-.946.15-1.676-.013-2.19-.164-.519-.476-.878-.935-1.078-.46-.205-1.053-.307-1.78-.307h-1.406l-1.255 7.531ZM0 18.971 2.32 5h3.792l-.9 5.458h5.02L11.134 5h3.794l-2.32 13.971H8.814l.9-5.457h-5.02l-.901 5.457H0Z"
/>
</svg>
<svg slot="icon" class="media-sd-icon hidden" aria-hidden="true" viewBox="0 0 28 24">
<path
fill="currentColor"
d="M19.857 18.967H14.41L16.725 5.02h5.23c1.434 0 2.633.288 3.595.864.962.577 1.646 1.401 2.05 2.472.404 1.072.483 2.347.238 3.827-.236 1.426-.715 2.645-1.437 3.657a7.062 7.062 0 0 1-2.75 2.322c-1.113.536-2.377.804-3.794.804Zm-1.13-3.214h1.375c.69 0 1.306-.12 1.846-.361.545-.246.999-.654 1.362-1.226.367-.577.633-1.364.797-2.363.154-.944.15-1.673-.014-2.186-.164-.517-.474-.876-.933-1.076-.459-.204-1.051-.306-1.777-.306H19.98l-1.253 7.518Zm-8.496-6.374c.041-.45-.068-.801-.327-1.056-.258-.258-.694-.388-1.307-.388-.39 0-.717.046-.98.136-.26.091-.461.216-.607.375-.14.159-.229.343-.265.551a.792.792 0 0 0 .007.45.85.85 0 0 0 .279.36c.14.11.324.207.551.294.232.086.507.163.824.231l1.09.245c.744.164 1.369.38 1.872.647.509.263.909.577 1.199.94.29.363.481.77.572 1.219.095.45.098.94.007 1.47-.155.918-.51 1.694-1.07 2.33-.558.635-1.286 1.119-2.185 1.45-.899.331-1.939.497-3.119.497-1.207 0-2.233-.18-3.078-.538-.84-.363-1.448-.917-1.825-1.662-.372-.748-.463-1.704-.272-2.866h3.595c-.054.426-.009.785.136 1.076.146.29.38.51.702.66.322.15.724.225 1.205.225.409 0 .758-.05 1.049-.15.29-.1.52-.238.688-.415.168-.177.27-.38.306-.606a.741.741 0 0 0-.109-.559c-.109-.163-.306-.31-.592-.442s-.68-.252-1.178-.361l-1.335-.3c-1.185-.272-2.08-.722-2.683-1.348-.604-.627-.817-1.485-.64-2.574.145-.89.51-1.666 1.096-2.329.59-.667 1.34-1.185 2.247-1.553.913-.372 1.923-.558 3.03-.558 1.126 0 2.068.188 2.826.565.763.377 1.31.906 1.642 1.587.336.68.426 1.48.272 2.397h-3.623Z"
/>
</svg>
<svg slot="icon" class="media-4k-icon hidden" aria-hidden="true" viewBox="0 0 28 24">
<path
fill="currentColor"
d="M13.163 18.887 15.47 5h3.77l-.922 5.615h.19L23.606 5H28l-5.696 6.184 3.499 7.703H21.3l-2.224-5.207-1.546 1.654-.596 3.553h-3.77ZM0 16.717l.488-2.929L7.54 5h2.658l-.65 3.906h-1.52L4.232 13.68l-.027.108h8.246l-.489 2.93H0Zm6.401 2.17.516-3.065.298-1.274L8.788 5h3.526L10.01 18.887H6.4Z"
/>
</svg>
</media-rendition-menu-button>
<media-pip-button>
<svg
slot="enter"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M11 19h-6a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v4"></path>
<rect x="14" y="14" width="7" height="5" rx="1" fill="currentColor"></rect>
<line x1="7" y1="9" x2="11" y2="13"></line>
<path d="M8 13h3v-3"></path>
</svg>
<svg
slot="exit"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M11 19h-6a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v4"></path>
<rect x="14" y="14" width="7" height="5" rx="1" fill="currentColor"></rect>
<line x1="7" y1="9" x2="11" y2="13"></line>
<path d="M7 12v-3h3"></path>
</svg>
</media-pip-button>
<media-airplay-button></media-airplay-button>
<media-cast-button>
<svg
slot="enter"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<line x1="3" y1="19" x2="3.01" y2="19"></line>
<path d="M7 19a4 4 0 0 0 -4 -4"></path>
<path d="M11 19a8 8 0 0 0 -8 -8"></path>
<path d="M15 19h3a3 3 0 0 0 3 -3v-8a3 3 0 0 0 -3 -3h-12a3 3 0 0 0 -2.8 2"></path>
</svg>
<svg
slot="exit"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M3 19h.01"></path>
<path d="M7 19a4 4 0 0 0 -4 -4"></path>
<path d="M11 19a8 8 0 0 0 -8 -8"></path>
<path
d="M15 19h3a3 3 0 0 0 .875 -.13m1.997 -2.002a3 3 0 0 0 .128 -.868v-8a3 3 0 0 0 -3 -3h-9m-3.865 .136a3 3 0 0 0 -1.935 1.864"
></path>
<path d="M3 3l18 18"></path>
</svg>
</media-cast-button>
<media-fullscreen-button>
<svg slot="enter" aria-hidden="true" fill="none" viewBox="0 0 24 24">
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 5h4v4M15 9l4-4M9 19H5v-4M5 19l4-4M15 19h4v-4M15 15l4 4M9 5H5v4M5 5l4 4"
/>
</svg>
<svg slot="exit" aria-hidden="true" fill="none" viewBox="0 0 24 24">
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5 9h4V5M4.5 4.5 9 9M5 15h4v4M4.5 19.5 9 15M19 9h-4V5M15 9l4.5-4.5M19 15h-4v4M15 15l4.5 4.5"
/>
</svg>
</media-fullscreen-button>
</media-control-bar>
</div>
</div>
<media-captions-menu anchor="auto" hidden></media-captions-menu>
<media-playback-rate-menu anchor="auto" hidden></media-playback-rate-menu>
<media-rendition-menu anchor="auto" hidden></media-rendition-menu>
</media-controller>
`;
}
class MediaThemeVimeonovaElement extends MediaThemeElement {
static template = template;
}
if (globalThis.customElements && !globalThis.customElements.get('media-theme-vimeonova')) {
globalThis.customElements.define('media-theme-vimeonova', MediaThemeVimeonovaElement);
}
export default MediaThemeVimeonovaElement;

View File

@@ -0,0 +1,7 @@
import MediaThemeVimeonovaElement from './media-theme.js';
declare const MediaThemeVimeonova: React.ForwardRefExoticComponent<
React.DetailedHTMLProps<React.HTMLAttributes<MediaThemeVimeonovaElement>, MediaThemeVimeonovaElement>
>;
export default MediaThemeVimeonova;

View File

@@ -0,0 +1,94 @@
'use client';
import React from 'react';
import Element from './media-theme.js';
export default React.forwardRef((allProps, ref) => {
let { children, suppressHydrationWarning, ...props } = allProps;
const elementRef = React.useRef(null);
for (let name in props) {
if (name[0] === 'o' && name[1] === 'n') {
const useCapture = name.endsWith('Capture');
const eventName = name.slice(2, useCapture ? name.length - 7 : undefined).toLowerCase();
const callback = props[name];
React.useEffect(() => {
const eventTarget = elementRef?.current;
if (!eventTarget || typeof callback !== 'function') return;
eventTarget.addEventListener(eventName, callback, useCapture);
return () => {
eventTarget.removeEventListener(eventName, callback, useCapture);
};
}, [elementRef?.current, callback]);
}
}
const attrs = propsToAttrs(props);
// Only render the custom element template HTML on the server..
// The custom element will render itself on the client.
if (typeof window === 'undefined' && Element?.getTemplateHTML && Element?.shadowRootOptions) {
const { mode, delegatesFocus } = Element.shadowRootOptions;
const templateShadowRoot = React.createElement('template', {
shadowrootmode: mode,
shadowrootdelegatesfocus: delegatesFocus,
dangerouslySetInnerHTML: {
__html: Element.getTemplateHTML(attrs),
},
});
children = [templateShadowRoot, children];
}
return React.createElement('media-theme-vimeonova', {
...attrs,
ref: React.useCallback(
(node) => {
elementRef.current = node;
if (typeof ref === 'function') {
ref(node);
} else if (ref !== null) {
ref.current = node;
}
},
[ref]
),
children,
suppressHydrationWarning,
});
});
const ReactPropToAttrNameMap = {
className: 'class',
classname: 'class',
htmlFor: 'for',
viewBox: 'viewBox',
};
function propsToAttrs(props = {}) {
let attrs = {};
for (let [propName, propValue] of Object.entries(props)) {
let attrName = toAttrName(propName, propValue);
if (attrName) attrs[attrName] = toAttrValue(propValue);
}
return attrs;
}
function toAttrName(propName, propValue) {
if (ReactPropToAttrNameMap[propName]) return ReactPropToAttrNameMap[propName];
if (typeof propValue == 'undefined') return undefined;
if (typeof propValue === 'boolean' && !propValue) return undefined;
if (propName.startsWith('on') && typeof propValue === 'function') return undefined;
if (/[A-Z]/.test(propName)) return propName.toLowerCase();
return propName;
}
function toAttrValue(propValue) {
if (typeof propValue === 'boolean') return '';
if (Array.isArray(propValue)) return propValue.join(' ');
return propValue;
}

View File

@@ -0,0 +1,35 @@
{
"name": "@player.style/vimeonova",
"version": "0.0.7",
"description": "A fresh take on the classic Vimeo player design.",
"author": "@luwes",
"license": "MIT",
"homepage": "https://github.com/muxinc/player.style#readme",
"bugs": {
"url": "https://github.com/muxinc/player.style/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/muxinc/player.style.git",
"directory": "themes/vimeonova"
},
"files": [
"dist"
],
"type": "module",
"main": "dist/media-theme.js",
"exports": {
".": "./dist/media-theme.js",
"./react": "./dist/react.js"
},
"scripts": {
"clean": "rimraf dist",
"build": "build-theme"
},
"peerDependencies": {
"media-chrome": ">=1.0.0"
},
"devDependencies": {
"build-theme": "^0.0.4"
}
}

View File

@@ -0,0 +1,657 @@
<style>
:host {
--vimeonova-black: 23 35 34;
--vimeonova-primary-color: var(--media-primary-color, rgb(253 244 255));
--vimeonova-secondary-color: var(--media-secondary-color, rgb(--vimeonova-black / 0.75));
--vimeonova-accent-color: var(--media-accent-color, rgb(0 186 115));
--vimeonova-control-bar-height: 32px;
--vimeonova-control-bar-border-radius: 0.125rem;
--vimeonova-play-button-border-radius: 0.25rem;
--media-control-background: var(--vimeonova-secondary-color);
--media-control-hover-background: var(--vimeonova-secondary-color);
--media-icon-color: var(--vimeonova-primary-color);
--media-menu-border-radius: 0.25rem;
--media-tooltip-display: none;
color: var(--vimeonova-primary-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
:host {
--vimeonova-secondary-color: color-mix(in srgb, var(--media-secondary-color, rgb(23 35 34)) 75%, transparent);
}
}
media-controller {
display: block;
container: media-theme-vimeonova / inline-size;
}
.hidden {
display: none;
}
.header {
display: flex;
flex-direction: column;
align-items: flex-start;
row-gap: 1px;
margin: 0.625rem;
}
.title,
.byline {
display: inline-block;
background: var(--vimeonova-secondary-color);
margin: 0;
padding: 0.15rem 0.2rem;
line-height: 1;
font-size: 0.8rem;
font-weight: normal;
}
.title {
color: var(--vimeonova-accent-color);
font-size: 1.3rem;
font-weight: bold;
}
.byline {
color: var(--vimeonova-accent-color);
}
.control-bar-container {
position: relative;
overflow: visible;
display: flex;
align-items: end;
padding: 0.35rem;
width: 100%;
box-sizing: border-box;
}
@container (inline-size >=384px) {
.control-bar-container {
column-gap: 0.625rem;
padding: 0.625rem;
}
}
.control-bar-right {
flex-grow: 1;
}
media-control-bar {
background: var(--media-control-background);
height: var(--vimeonova-control-bar-height);
border-bottom-left-radius: var(--vimeonova-control-bar-border-radius);
border-bottom-right-radius: var(--vimeonova-control-bar-border-radius);
width: 100%;
}
media-control-bar [role='button'],
media-control-bar [role='switch'] {
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-button-icon-active-transform: scale(1.2);
--media-button-icon-transition: transform 0.2s ease;
color: var(--vimeonova-primary-color);
padding: 0.3125rem 0.35rem;
}
media-control-bar svg {
fill: none;
}
media-control-bar svg:active {
transform: scale(1.2);
}
media-play-button {
--media-control-background: var(--vimeonova-secondary-color);
--media-control-hover-background: var(--vimeonova-accent-color);
--media-button-icon-height: 100%;
display: none;
border-radius: var(--vimeonova-play-button-border-radius);
color: var(--vimeonova-primary-color);
width: 65px;
flex: 0 0 65px;
padding: 0.3125rem 0.625rem;
aspect-ratio: 16 / 10;
}
[slot='centered-chrome'] media-play-button {
display: block;
position: relative;
top: -30%;
}
media-play-button:active {
--media-control-hover-background: var(--vimeonova-accent-color);
}
@supports (color: color-mix(in srgb, red, blue)) {
media-play-button:active {
--media-control-hover-background: color-mix(in srgb, var(--vimeonova-accent-color) 80%, transparent);
}
}
media-time-range {
--media-range-padding: 0;
--media-control-background: transparent;
--media-control-hover-background: transparent;
--media-time-range-buffered-color: dimgray;
--media-range-track-background: rgb(var(--vimeonova-black) / 0.5);
--media-range-track-border-radius: 0;
--media-range-bar-color: var(--vimeonova-accent-color);
--media-range-thumb-background: none;
--media-range-thumb-width: 0px;
--media-range-thumb-height: 0px;
--media-range-track-height: 10px;
--media-range-track-transition: height 0.2s ease;
--media-preview-thumbnail-border-radius: 2px;
--media-preview-thumbnail-border: 4px solid var(--vimeonova-secondary-color);
--media-box-margin: 0;
--media-preview-time-background: rgb(var(--vimeonova-black) / 1);
padding-inline: 10px;
z-index: 1;
}
media-time-range.small {
--media-box-padding-left: 2px;
--media-box-padding-right: 2px;
--media-range-track-height: 5px;
--media-range-track-border-radius: var(--vimeonova-control-bar-border-radius)
var(--vimeonova-control-bar-border-radius) 0 0;
height: 5px;
width: 100%;
padding: 0;
}
@keyframes buffer {
100% {
--media-range-track-background: rgb(var(--vimeonova-black) / 0.5)
url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="100%"><style>@keyframes buffer { 100% { transform: translateX(-10px); }}%3C/style><defs><pattern id="buffer-pattern" patternUnits="userSpaceOnUse" x="0" y="0" width="10" height="10" viewBox="0 0 10 10"><line x1="5" y1="-1" x2="-5" y2="10" stroke-width="2" stroke="dimgray" stroke-linecap="butt" /><line x1="10" y1="-1" x2="0" y2="10" stroke-width="2" stroke="dimgray" stroke-linecap="butt" /><line x1="15" y1="-1" x2="5" y2="10" stroke-width="2" stroke="dimgray" stroke-linecap="butt" /></pattern></defs><rect width="110%" height="100%" fill="url(%23buffer-pattern)" style="animation: buffer 250ms linear infinite;" /></svg>');
}
}
[medialoading]:not([mediapaused]) media-time-range {
animation: 1000000s 0.5s buffer reverse;
}
media-time-range.large {
display: none;
height: var(--vimeonova-control-bar-height);
flex-grow: 10000;
}
media-time-range > * {
position: relative;
bottom: -11px;
}
media-time-range.small > * {
bottom: 3px;
}
@container (inline-size >=384px) {
[slot='centered-chrome'] media-play-button {
display: none;
}
.control-bar-container media-play-button {
display: block;
}
media-time-range.small {
border-top-left-radius: var(--vimeonova-control-bar-border-radius);
border-top-right-radius: var(--vimeonova-control-bar-border-radius);
}
}
@container (inline-size >=484px) {
media-control-bar {
border-radius: var(--vimeonova-control-bar-border-radius);
}
media-time-range.small {
display: none;
}
media-time-range.large {
display: block;
}
}
media-preview-time-display,
media-time-display {
--media-preview-time-background: var(--vimeonova-primary-color);
padding: 2px 4px;
border-radius: 0;
line-height: normal;
color: rgb(var(--vimeonova-black) / 1);
font-family: Verdana, sans-serif;
font-size: 10px;
box-shadow: rgb(0 0 0 / 0.7) 1px 1px 0px 0px;
text-shadow: none;
}
media-preview-thumbnail {
max-width: 213px;
max-height: 200px;
}
media-preview-time-display {
margin-top: 5px;
min-width: auto;
--media-preview-time-background: rgb(var(--vimeonova-black) / 1);
color: var(--vimeonova-primary-color);
}
[part='arrow'] {
--media-box-arrow-background: rgb(var(--vimeonova-black) / 1);
--media-box-arrow-height: 4px;
--media-box-arrow-width: 4px;
--media-box-arrow-offset: 0px;
left: 1px;
}
[part='arrow'][slot='current']::before {
--media-box-arrow-background: var(--vimeonova-primary-color);
}
[part='arrow']::before {
content: '';
border-color: transparent;
border-top-color: var(--media-box-arrow-background, var(--_control-background));
border-width: var(
--media-box-arrow-border-width,
var(--media-box-arrow-height, 5px) var(--media-box-arrow-width, 6px) 0
);
border-style: solid;
position: absolute;
bottom: 0.5px;
margin-left: calc((var(--media-box-arrow-width) + 1px) * -1);
}
media-volume-range {
--media-range-track-background-color: rgb(var(--vimeonova-black) / 0.8);
--media-range-track-border-radius: 1px;
--media-range-bar-color: var(--vimeonova-accent-color);
--media-range-thumb-background: none;
--media-range-thumb-width: 0px;
--media-range-thumb-height: 0px;
--media-range-track-height: 6px;
height: var(--vimeonova-control-bar-height);
background: var(--vimeonova-secondary-color);
border-radius: var(--media-menu-border-radius);
}
.media-volume-wrapper {
position: relative;
}
.media-volume-range-wrapper {
width: 122px;
height: 34px;
overflow: hidden;
opacity: 0;
transform: rotate(-90deg);
position: absolute;
top: -80px;
left: -52px;
border-left: 16px solid transparent;
visibility: hidden;
}
@container (inline-size >=484px) {
.media-volume-range-wrapper {
top: -77px;
}
}
media-mute-button:hover + .media-volume-range-wrapper,
media-mute-button:focus + .media-volume-range-wrapper,
media-mute-button:focus-within + .media-volume-range-wrapper,
.media-volume-range-wrapper:hover,
.media-volume-range-wrapper:focus,
.media-volume-range-wrapper:focus-within {
opacity: 1;
visibility: visible;
}
[role='menu'] {
position: absolute;
margin-bottom: 10px;
}
@container (inline-size >=484px) {
[role='menu'] {
margin-bottom: 7px;
}
}
.spacer {
flex-grow: 1;
height: 100%;
}
</style>
<media-controller
defaultsubtitles="{{defaultsubtitles}}"
defaultduration="{{defaultduration}}"
gesturesdisabled="{{disabled}}"
hotkeys="{{hotkeys}}"
nohotkeys="{{nohotkeys}}"
defaultstreamtype="on-demand"
>
<slot name="media" slot="media"></slot>
<slot name="poster" slot="poster"></slot>
<div slot="top-chrome" class="header">
<template if="mediatitle">
<h1 class="title">{{mediatitle}}</h1>
</template>
<template if="mediabyline">
<h2 class="byline">{{mediabyline}}</h2>
</template>
</div>
<div slot="centered-chrome">
<media-play-button>
<svg
slot="play"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M7 4v16l13 -8z"></path>
</svg>
<svg
slot="pause"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<rect x="6" y="5" width="4" height="14" rx="0"></rect>
<rect x="14" y="5" width="4" height="14" rx="0"></rect>
</svg>
</media-play-button>
</div>
<div class="control-bar-container" id="vimeonova-bounds">
<media-play-button>
<svg
slot="play"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M7 4v16l13 -8z"></path>
</svg>
<svg
slot="pause"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<rect x="6" y="5" width="4" height="14" rx="0"></rect>
<rect x="14" y="5" width="4" height="14" rx="0"></rect>
</svg>
</media-play-button>
<div class="control-bar-right">
<media-time-range class="small">
<media-preview-time-display slot="preview"></media-preview-time-display>
<div part="arrow" slot="preview"></div>
<media-time-display slot="current"></media-time-display>
<div part="arrow" slot="current"></div>
</media-time-range>
<media-control-bar>
<media-time-range class="large" bounds="vimeonova-bounds">
<media-preview-thumbnail slot="preview"></media-preview-thumbnail>
<media-preview-time-display slot="preview"></media-preview-time-display>
<div part="arrow" slot="preview"></div>
<media-time-display slot="current"></media-time-display>
<div part="arrow" slot="current"></div>
</media-time-range>
<div class="spacer"></div>
<media-captions-menu-button>
<svg slot="on" aria-hidden="true" fill="none" viewBox="0 0 24 24">
<path
fill="currentColor"
fill-rule="evenodd"
d="M2 8a4 4 0 0 1 4-4h12a4 4 0 0 1 4 4v7a4 4 0 0 1-4 4h-.532l-2.2 2.64a1 1 0 0 1-1.536 0l-2.2-2.64H5.999A4 4 0 0 1 2 15V8Zm13.57.183a3.333 3.333 0 0 1 2.338.826.82.82 0 0 1-1.083 1.232 1.693 1.693 0 0 0-2.336.097 1.674 1.674 0 0 0 0 2.324 1.692 1.692 0 0 0 2.336.097.82.82 0 0 1 1.083 1.232 3.333 3.333 0 0 1-4.6-.191 3.314 3.314 0 0 1 0-4.6m2.261-1.017c-.856.035-1.666.4-2.261 1.017Zm-6.7-.005a3.338 3.338 0 0 1 2.342.828.825.825 0 0 1-1.089 1.239 1.688 1.688 0 0 0-2.33.097 1.669 1.669 0 0 0 0 2.316 1.688 1.688 0 0 0 2.33.097.825.825 0 1 1 1.09 1.24 3.338 3.338 0 0 1-4.608-.192 3.319 3.319 0 0 1 0-4.606m2.265-1.02a3.347 3.347 0 0 0-2.265 1.02Z"
clip-rule="evenodd"
/>
</svg>
<svg slot="off" aria-hidden="true" fill="none" viewBox="0 0 24 24">
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.6"
d="M17.367 9.625a2.513 2.513 0 0 0-3.469.144 2.494 2.494 0 0 0 0 3.461 2.513 2.513 0 0 0 3.469.145m-6.7-3.75a2.513 2.513 0 0 0-3.469.144 2.494 2.494 0 0 0 0 3.461 2.512 2.512 0 0 0 3.469.145"
/>
<path
fill="currentColor"
d="M17 18v-1h-.468l-.3.36L17 18Zm-5 0 .768-.64-.3-.36H12v1Zm2.5 3-.768.64a1 1 0 0 0 1.536 0L14.5 21ZM6 6h12V4H6v2Zm14 2v7h2V8h-2ZM4 15V8H2v7h2Zm14 2h-1v2h1v-2Zm-6 0H6v2h6v-2Zm4.232.36-2.5 3 1.536 1.28 2.5-3-1.536-1.28Zm-.964 3-2.5-3-1.536 1.28 2.5 3 1.536-1.28ZM2 15a4 4 0 0 0 4 4v-2a2 2 0 0 1-2-2H2Zm18 0a2 2 0 0 1-2 2v2a4 4 0 0 0 4-4h-2Zm-2-9a2 2 0 0 1 2 2h2a4 4 0 0 0-4-4v2ZM6 4a4 4 0 0 0-4 4h2a2 2 0 0 1 2-2V4Z"
/>
</svg>
</media-captions-menu-button>
<media-playback-rate-menu-button></media-playback-rate-menu-button>
<div class="media-volume-wrapper">
<media-mute-button>
<svg
slot="high"
aria-hidden="true"
viewBox="0 0 24 25"
stroke-width="1.8"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M15 8a5 5 0 0 1 0 8"></path>
<path d="M17.7 5a9 9 0 0 1 0 14"></path>
<path
d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"
fill="currentColor"
></path>
</svg>
<svg
slot="medium"
aria-hidden="true"
viewBox="0 0 24 25"
stroke-width="1.8"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M15 8a5 5 0 0 1 0 8"></path>
<path d="M17.7 5a9 9 0 0 1 0 14"></path>
<path
d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"
fill="currentColor"
></path>
</svg>
<svg
slot="low"
aria-hidden="true"
viewBox="0 0 24 25"
stroke-width="1.8"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M15 8a5 5 0 0 1 0 8"></path>
<path
d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"
fill="currentColor"
></path>
</svg>
<svg
slot="off"
aria-hidden="true"
viewBox="0 0 24 25"
stroke-width="1.8"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path
d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a0.8 .8 0 0 1 1.5 .5v14a0.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"
></path>
<path d="M16 10l4 4m0 -4l-4 4"></path>
</svg>
</media-mute-button>
<div class="media-volume-range-wrapper">
<media-volume-range></media-volume-range>
</div>
</div>
<media-rendition-menu-button>
<svg slot="icon" class="media-hd-icon" aria-hidden="true" viewBox="0 0 28 24">
<path
fill="currentColor"
d="M19.866 18.971h-5.458L16.728 5h5.239c1.437 0 2.638.289 3.602.866.964.578 1.648 1.403 2.053 2.477.405 1.073.485 2.351.239 3.834-.237 1.428-.716 2.649-1.44 3.663a7.076 7.076 0 0 1-2.756 2.326c-1.114.537-2.38.805-3.8.805Zm-1.133-3.22h1.378c.691 0 1.308-.12 1.849-.361.546-.246 1-.655 1.364-1.228.369-.578.635-1.367.798-2.367.155-.946.15-1.676-.013-2.19-.164-.519-.476-.878-.935-1.078-.46-.205-1.053-.307-1.78-.307h-1.406l-1.255 7.531ZM0 18.971 2.32 5h3.792l-.9 5.458h5.02L11.134 5h3.794l-2.32 13.971H8.814l.9-5.457h-5.02l-.901 5.457H0Z"
/>
</svg>
<svg slot="icon" class="media-sd-icon hidden" aria-hidden="true" viewBox="0 0 28 24">
<path
fill="currentColor"
d="M19.857 18.967H14.41L16.725 5.02h5.23c1.434 0 2.633.288 3.595.864.962.577 1.646 1.401 2.05 2.472.404 1.072.483 2.347.238 3.827-.236 1.426-.715 2.645-1.437 3.657a7.062 7.062 0 0 1-2.75 2.322c-1.113.536-2.377.804-3.794.804Zm-1.13-3.214h1.375c.69 0 1.306-.12 1.846-.361.545-.246.999-.654 1.362-1.226.367-.577.633-1.364.797-2.363.154-.944.15-1.673-.014-2.186-.164-.517-.474-.876-.933-1.076-.459-.204-1.051-.306-1.777-.306H19.98l-1.253 7.518Zm-8.496-6.374c.041-.45-.068-.801-.327-1.056-.258-.258-.694-.388-1.307-.388-.39 0-.717.046-.98.136-.26.091-.461.216-.607.375-.14.159-.229.343-.265.551a.792.792 0 0 0 .007.45.85.85 0 0 0 .279.36c.14.11.324.207.551.294.232.086.507.163.824.231l1.09.245c.744.164 1.369.38 1.872.647.509.263.909.577 1.199.94.29.363.481.77.572 1.219.095.45.098.94.007 1.47-.155.918-.51 1.694-1.07 2.33-.558.635-1.286 1.119-2.185 1.45-.899.331-1.939.497-3.119.497-1.207 0-2.233-.18-3.078-.538-.84-.363-1.448-.917-1.825-1.662-.372-.748-.463-1.704-.272-2.866h3.595c-.054.426-.009.785.136 1.076.146.29.38.51.702.66.322.15.724.225 1.205.225.409 0 .758-.05 1.049-.15.29-.1.52-.238.688-.415.168-.177.27-.38.306-.606a.741.741 0 0 0-.109-.559c-.109-.163-.306-.31-.592-.442s-.68-.252-1.178-.361l-1.335-.3c-1.185-.272-2.08-.722-2.683-1.348-.604-.627-.817-1.485-.64-2.574.145-.89.51-1.666 1.096-2.329.59-.667 1.34-1.185 2.247-1.553.913-.372 1.923-.558 3.03-.558 1.126 0 2.068.188 2.826.565.763.377 1.31.906 1.642 1.587.336.68.426 1.48.272 2.397h-3.623Z"
/>
</svg>
<svg slot="icon" class="media-4k-icon hidden" aria-hidden="true" viewBox="0 0 28 24">
<path
fill="currentColor"
d="M13.163 18.887 15.47 5h3.77l-.922 5.615h.19L23.606 5H28l-5.696 6.184 3.499 7.703H21.3l-2.224-5.207-1.546 1.654-.596 3.553h-3.77ZM0 16.717l.488-2.929L7.54 5h2.658l-.65 3.906h-1.52L4.232 13.68l-.027.108h8.246l-.489 2.93H0Zm6.401 2.17.516-3.065.298-1.274L8.788 5h3.526L10.01 18.887H6.4Z"
/>
</svg>
</media-rendition-menu-button>
<media-pip-button>
<svg
slot="enter"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M11 19h-6a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v4"></path>
<rect x="14" y="14" width="7" height="5" rx="1" fill="currentColor"></rect>
<line x1="7" y1="9" x2="11" y2="13"></line>
<path d="M8 13h3v-3"></path>
</svg>
<svg
slot="exit"
aria-hidden="true"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M11 19h-6a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v4"></path>
<rect x="14" y="14" width="7" height="5" rx="1" fill="currentColor"></rect>
<line x1="7" y1="9" x2="11" y2="13"></line>
<path d="M7 12v-3h3"></path>
</svg>
</media-pip-button>
<media-airplay-button></media-airplay-button>
<media-cast-button>
<svg
slot="enter"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<line x1="3" y1="19" x2="3.01" y2="19"></line>
<path d="M7 19a4 4 0 0 0 -4 -4"></path>
<path d="M11 19a8 8 0 0 0 -8 -8"></path>
<path d="M15 19h3a3 3 0 0 0 3 -3v-8a3 3 0 0 0 -3 -3h-12a3 3 0 0 0 -2.8 2"></path>
</svg>
<svg
slot="exit"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M3 19h.01"></path>
<path d="M7 19a4 4 0 0 0 -4 -4"></path>
<path d="M11 19a8 8 0 0 0 -8 -8"></path>
<path
d="M15 19h3a3 3 0 0 0 .875 -.13m1.997 -2.002a3 3 0 0 0 .128 -.868v-8a3 3 0 0 0 -3 -3h-9m-3.865 .136a3 3 0 0 0 -1.935 1.864"
></path>
<path d="M3 3l18 18"></path>
</svg>
</media-cast-button>
<media-fullscreen-button>
<svg slot="enter" aria-hidden="true" fill="none" viewBox="0 0 24 24">
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 5h4v4M15 9l4-4M9 19H5v-4M5 19l4-4M15 19h4v-4M15 15l4 4M9 5H5v4M5 5l4 4"
/>
</svg>
<svg slot="exit" aria-hidden="true" fill="none" viewBox="0 0 24 24">
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5 9h4V5M4.5 4.5 9 9M5 15h4v4M4.5 19.5 9 15M19 9h-4V5M15 9l4.5-4.5M19 15h-4v4M15 15l4.5 4.5"
/>
</svg>
</media-fullscreen-button>
</media-control-bar>
</div>
</div>
<media-captions-menu anchor="auto" hidden></media-captions-menu>
<media-playback-rate-menu anchor="auto" hidden></media-playback-rate-menu>
<media-rendition-menu anchor="auto" hidden></media-rendition-menu>
</media-controller>

View File

@@ -0,0 +1,29 @@
# Changelog
## [0.0.7](https://github.com/muxinc/player.style/compare/@player.style/winamp@0.0.6...@player.style/winamp@0.0.7) (2024-09-10)
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.3 to ^0.0.4
## [0.0.6](https://github.com/muxinc/player.style/compare/@player.style/winamp-v0.0.5...@player.style/winamp@0.0.6) (2024-08-15)
### Features
* add Winamp theme ([#53](https://github.com/muxinc/player.style/issues/53)) ([e258398](https://github.com/muxinc/player.style/commit/e258398d75eab19cf1656e5a597f518344d5f5b3))
### Bug Fixes
* upgrade to Media Chrome v4 ([#64](https://github.com/muxinc/player.style/issues/64)) ([be68af2](https://github.com/muxinc/player.style/commit/be68af2f9c3a6ff6674b9951f0b34f2bfdb042aa))
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* build-theme bumped from ^0.0.2 to ^0.0.3

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1003 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

Some files were not shown because too many files have changed in this diff Show More