mirror of
https://github.com/zoriya/v10.git
synced 2026-08-05 13:48:14 +00:00
fix(html): fix html container sizing (#881)
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
video-player {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
video-player video,
|
||||
video-player hls-video,
|
||||
video-player simple-hls-video {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
video-player video::-webkit-media-text-track-container {
|
||||
transition: transform var(--media-caption-track-duration, 150ms) ease-out;
|
||||
transition-delay: var(--media-caption-track-delay, 600ms);
|
||||
transform: translateY(var(--media-caption-track-y, 0)) scale(0.98);
|
||||
z-index: var(--media-caption-track-z, 1);
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
video-player video::-webkit-media-text-track-container {
|
||||
transition-duration: 50ms;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +1,14 @@
|
||||
import type { ReactiveElement } from '@videojs/element';
|
||||
import type { Constructor } from '@videojs/utils/types';
|
||||
import styles from './base.css?inline';
|
||||
|
||||
/**
|
||||
* Light DOM stylesheet that bridges CSS custom properties set by skins
|
||||
* to native WebKit text track pseudo-elements on the slotted `<video>`.
|
||||
*
|
||||
* `::slotted(video)::-webkit-media-text-track-container` is invalid per
|
||||
* CSS spec, so this bridge lives in light DOM where it can directly
|
||||
* target the video element's pseudo-elements.
|
||||
*/
|
||||
const NATIVE_CAPTION_BRIDGE_CSS = /* css */ `
|
||||
.media-skin > video::-webkit-media-text-track-container {
|
||||
transition: transform var(--media-caption-track-duration, 150ms) ease-out;
|
||||
transition-delay: var(--media-caption-track-delay, 600ms);
|
||||
transform: translateY(var(--media-caption-track-y, 0)) scale(0.98);
|
||||
z-index: var(--media-caption-track-z, 1);
|
||||
font-family: inherit;
|
||||
}
|
||||
const STYLES_ID = '__media-styles';
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.media-skin > video::-webkit-media-text-track-container {
|
||||
transition-duration: 50ms;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const BRIDGE_ID = 'media-caption-bridge';
|
||||
|
||||
function ensureCaptionBridge(): void {
|
||||
if (document.getElementById(BRIDGE_ID)) return;
|
||||
function ensureStyles(): void {
|
||||
if (document.getElementById(STYLES_ID)) return;
|
||||
const style = document.createElement('style');
|
||||
style.id = BRIDGE_ID;
|
||||
style.textContent = NATIVE_CAPTION_BRIDGE_CSS;
|
||||
style.id = STYLES_ID;
|
||||
style.textContent = styles;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
@@ -40,8 +17,8 @@ function ensureCaptionBridge(): void {
|
||||
* `getTemplateHTML` method into a shadow root. Native `<slot>` elements
|
||||
* handle light DOM projection automatically.
|
||||
*
|
||||
* When `static styles` is set, the stylesheet is adopted into the shadow
|
||||
* root via `adoptedStyleSheets`.
|
||||
* When `static styles` is set, the stylesheet is adopted into the
|
||||
* shadow root via `adoptedStyleSheets`.
|
||||
*/
|
||||
export function SkinMixin<Base extends Constructor<ReactiveElement>>(
|
||||
BaseClass: Base
|
||||
@@ -53,8 +30,7 @@ export function SkinMixin<Base extends Constructor<ReactiveElement>>(
|
||||
constructor(...args: any[]) {
|
||||
super(...args);
|
||||
|
||||
this.classList.add('media-skin');
|
||||
ensureCaptionBridge();
|
||||
ensureStyles();
|
||||
|
||||
if (!this.shadowRoot) {
|
||||
const ctor = this.constructor as typeof SkinElement & { getTemplateHTML?: () => string };
|
||||
|
||||
@@ -106,7 +106,7 @@ function getTemplateHTML() {
|
||||
<span class="media-tooltip-label media-tooltip-label--disable-captions">Disable captions</span>
|
||||
</media-tooltip>
|
||||
|
||||
<media-pip-button commandfor="pip-tooltip" class="media-button media-button--icon">
|
||||
<media-pip-button commandfor="pip-tooltip" class="media-button media-button--icon media-button--pip">
|
||||
${renderIcon('pip', { class: 'media-icon' })}
|
||||
</media-pip-button>
|
||||
<media-tooltip id="pip-tooltip" side="top" class="media-surface media-tooltip">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Skin } from '@app/types';
|
||||
import type { Skin } from '../../types';
|
||||
|
||||
const videoStylesheets: Record<Skin, string> = {
|
||||
default: new URL('@videojs/html/video/skin.css', import.meta.url).href,
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"prompts": "^2.4.2",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"rimraf": "^6.1.3",
|
||||
"tailwindcss": "^4.2.0",
|
||||
"tsx": "^4.0.0",
|
||||
"typescript": "^5.0.0",
|
||||
|
||||
@@ -21,7 +21,7 @@ function render() {
|
||||
loadVideoStylesheets(currentSkin);
|
||||
|
||||
document.getElementById('root')!.innerHTML = html`
|
||||
<video-player class="contents">
|
||||
<video-player>
|
||||
<${tag} class="w-full aspect-video max-w-4xl mx-auto">
|
||||
<hls-video slot="media" src="${SOURCES[currentSource].url}"></hls-video>
|
||||
</${tag}>
|
||||
|
||||
@@ -21,7 +21,7 @@ function render() {
|
||||
loadVideoStylesheets(currentSkin);
|
||||
|
||||
document.getElementById('root')!.innerHTML = html`
|
||||
<video-player class="contents">
|
||||
<video-player>
|
||||
<${tag} class="w-full aspect-video max-w-4xl mx-auto">
|
||||
<simple-hls-video slot="media" src="${SOURCES[currentSource].url}"></simple-hls-video>
|
||||
</${tag}>
|
||||
|
||||
@@ -20,7 +20,7 @@ function render() {
|
||||
const tag = TAILWIND_SKIN_TAGS[currentSkin].video;
|
||||
|
||||
document.getElementById('root')!.innerHTML = html`
|
||||
<video-player class="contents">
|
||||
<video-player>
|
||||
<${tag} class="w-full aspect-video max-w-4xl mx-auto">
|
||||
<video slot="media" src="${SOURCES[currentSource].url}"></video>
|
||||
</${tag}>
|
||||
|
||||
@@ -20,7 +20,7 @@ function render() {
|
||||
loadVideoStylesheets(currentSkin);
|
||||
|
||||
document.getElementById('root')!.innerHTML = html`
|
||||
<video-player class="contents">
|
||||
<video-player>
|
||||
<${tag} class="w-full aspect-video max-w-4xl mx-auto">
|
||||
<video slot="media" src="${SOURCES[currentSource].url}"></video>
|
||||
</${tag}>
|
||||
|
||||
@@ -28,10 +28,6 @@ document.getElementById('root')!.innerHTML = html`
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
video-player {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
simple-hls-video {
|
||||
width: 640px;
|
||||
aspect-ratio: 16 / 9;
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
container: media-root / inline-size;
|
||||
border-radius: var(--media-border-radius, 2rem);
|
||||
font-family:
|
||||
|
||||
@@ -2,7 +2,7 @@ import { cn } from '@videojs/utils/style';
|
||||
|
||||
export const root = cn(
|
||||
// Layout & containment
|
||||
'block relative isolate @container/media-root',
|
||||
'block relative isolate h-full w-full @container/media-root',
|
||||
// Appearance
|
||||
'rounded-(--media-border-radius,2rem)',
|
||||
'font-[Inter_Variable,Inter,ui-sans-serif,system-ui,sans-serif] text-[0.8125rem] leading-normal subpixel-antialiased',
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/* ==========================================================================
|
||||
Native Caption Bridge
|
||||
---------------------------------------------------------------------------
|
||||
Receives CSS custom properties set by any skin and applies them to the
|
||||
native WebKit text track container on the slotted <video> element.
|
||||
|
||||
This stylesheet MUST live in the light DOM because ::slotted() cannot be
|
||||
chained with vendor pseudo-elements like ::-webkit-media-text-track-container.
|
||||
|
||||
CSS custom properties cascade through the shadow DOM boundary, so skins
|
||||
define the values and this bridge reads them.
|
||||
========================================================================== */
|
||||
|
||||
.media-skin > video::-webkit-media-text-track-container {
|
||||
transition: transform var(--media-caption-track-duration, 150ms) ease-out;
|
||||
transition-delay: var(--media-caption-track-delay, 600ms);
|
||||
transform: translateY(var(--media-caption-track-y, 0)) scale(0.98);
|
||||
z-index: var(--media-caption-track-z, 1);
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.media-skin > video::-webkit-media-text-track-container {
|
||||
transition-duration: 50ms;
|
||||
}
|
||||
}
|
||||
Generated
+13
@@ -299,6 +299,9 @@ importers:
|
||||
react-dom:
|
||||
specifier: ^19.0.0
|
||||
version: 19.2.4(react@19.2.4)
|
||||
rimraf:
|
||||
specifier: ^6.1.3
|
||||
version: 6.1.3
|
||||
tailwindcss:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.1
|
||||
@@ -6549,6 +6552,11 @@ packages:
|
||||
rfdc@1.4.1:
|
||||
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
|
||||
|
||||
rimraf@6.1.3:
|
||||
resolution: {integrity: sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==}
|
||||
engines: {node: 20 || >=22}
|
||||
hasBin: true
|
||||
|
||||
rolldown-plugin-dts@0.17.8:
|
||||
resolution: {integrity: sha512-76EEBlhF00yeY6M7VpMkWKI4r9WjuoMiOGey7j4D6zf3m0BR+ZrrY9hvSXdueJ3ljxSLq4DJBKFpX/X9+L7EKw==}
|
||||
engines: {node: '>=20.19.0'}
|
||||
@@ -14516,6 +14524,11 @@ snapshots:
|
||||
|
||||
rfdc@1.4.1: {}
|
||||
|
||||
rimraf@6.1.3:
|
||||
dependencies:
|
||||
glob: 13.0.6
|
||||
package-json-from-dist: 1.0.1
|
||||
|
||||
rolldown-plugin-dts@0.17.8(rolldown@1.0.0-beta.45)(typescript@5.9.3):
|
||||
dependencies:
|
||||
'@babel/generator': 7.29.1
|
||||
|
||||
@@ -13,6 +13,14 @@ function getCdnFileName(useCase: UseCase, skin: Skin): string {
|
||||
}
|
||||
|
||||
function generateCdnCode(useCase: UseCase, skin: Skin): string {
|
||||
if (useCase === 'background-video') {
|
||||
return `<script type="module">
|
||||
import '${CDN_BASE}/background/player.js';
|
||||
import '${CDN_BASE}/background/skin.js';
|
||||
</script>
|
||||
<link rel="stylesheet" href="${CDN_BASE}/background/skin.css" />`;
|
||||
}
|
||||
|
||||
const name = getCdnFileName(useCase, skin);
|
||||
|
||||
return `<script type="module" src="${CDN_BASE}/${name}.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user