diff --git a/apps/sandbox/README.md b/apps/sandbox/README.md index f5d7463073..27069f4647 100644 --- a/apps/sandbox/README.md +++ b/apps/sandbox/README.md @@ -54,6 +54,8 @@ import { SOURCES } from '@app/shared/sources'; See `templates/html-video/main.ts` for a minimal reference, or `templates/react-video/main.tsx` for a React one. +Each html template spells out its player the way a consumer would — the player element, the skin, and the media inside it. `createHtmlSandbox` only supplies what the shell varies: `skinTag`, the live `playerTag`, the source and poster URLs, and the attributes the Options panel controls. The markup inside `render` can be copied as is, with `${skinTag}` replaced by a skin's tag such as `video-skin`. + ## Syncing changes back to templates When you've made improvements in `src/` that should become the new baseline: diff --git a/apps/sandbox/app/shared/html/sandbox.ts b/apps/sandbox/app/shared/html/sandbox.ts index 04433fff91..6e26524c6f 100644 --- a/apps/sandbox/app/shared/html/sandbox.ts +++ b/apps/sandbox/app/shared/html/sandbox.ts @@ -3,7 +3,6 @@ import { escapeHtml } from '@videojs/utils/string'; import { applyCaptionTracks } from '../captions'; import { findMediaTag } from '../media-element'; -import { PLAYER_FRAME_CLASSES } from '../player-frame'; import { getDirection, getInitialPlaybackOverrides, @@ -29,11 +28,19 @@ export type HtmlSandboxPlayer = 'video' | 'audio' | 'background'; /** A source assigned as an object, for what a `src` attribute cannot carry: tokens, license servers, engine options. */ export type HtmlSandboxSource = MuxSource | ({ src: string } & PlaybackOverrides); -/** What a template's media markup can read: the shell's selections plus what the runtime derived from them. */ +/** What a template's markup can read: the shell's selections plus what the runtime derived from them. */ export interface HtmlSandboxContext { readonly state: Readonly; /** The live player and skin variants are in use for this render. */ readonly live: boolean; + /** The player element for this render, such as `video-player` or `live-audio-player`. */ + readonly playerTag: string; + /** The skin element the shell selected and the runtime registered, such as `video-skin` or `audio-minimal-skin`. */ + readonly skinTag: string; + /** The source's poster URL, safe to interpolate into an attribute, or empty when it has none. */ + readonly poster: string; + /** A tiny blurred rendition of the poster for a blur-up placeholder, attribute-safe, or empty when there is none. */ + readonly placeholder: string; /** The selected source's plain URL, or empty when it has none. */ readonly url: string; /** ` src="…"` for the media element, or empty when the source has to be assigned as an object after render. */ @@ -52,19 +59,13 @@ export interface HtmlSandboxOptions { readonly player: HtmlSandboxPlayer; /** Switch to the live player and skin while the selected source is live. Leave off for media that cannot play one. */ readonly live?: boolean; - /** - * How the poster reaches the skin. `image` slots the source's poster image after the media. `derived` hands the URL - * to the player and slots a blurred placeholder before the media instead, for media that derives its poster from - * `src`. Neither renders by default. - */ - readonly poster?: 'image' | 'derived'; /** * Fold the query-string playback overrides into the initial source. That forces the object form, so the engine is * built with them rather than reconfigured afterwards. */ readonly playbackOverrides?: boolean; - /** The media element and any media components beside it, inside the skin. */ - readonly media: (context: HtmlSandboxContext) => string; + /** The whole player as a consumer would write it: the player element, the skin, and the media inside it. */ + readonly render: (context: HtmlSandboxContext) => string; /** Runs once the markup is in the document, for what an attribute cannot carry: assigning `context.source`. */ readonly attach?: (context: HtmlSandboxContext) => void; } @@ -120,62 +121,36 @@ function describeSource(state: SandboxState, playbackOverrides: boolean) { }; } -function createContext(options: HtmlSandboxOptions, state: SandboxState, live: boolean): HtmlSandboxContext { +function playerTagFor(player: HtmlSandboxPlayer, live: boolean): string { + if (player === 'background') return 'background-video-player'; + + return live ? `live-${player}-player` : `${player}-player`; +} + +function createContext( + options: HtmlSandboxOptions, + state: SandboxState, + live: boolean, + skinTag: string +): HtmlSandboxContext { const { url, src, source } = describeSource(state, options.playbackOverrides === true); return { state, live, + playerTag: playerTagFor(options.player, live), + skinTag, url, src, source, attrs: renderMediaAttrs(state), chapters: renderChapters(getChapters(state.source)), storyboard: renderStoryboard(getStoryboardSrc(state.source)), + poster: escapeHtml(getPosterSrc(state.source) ?? ''), + placeholder: escapeHtml(getPlaceholderSrc(state.source) ?? ''), }; } -function renderPlayer(options: HtmlSandboxOptions, skinTag: string, context: HtmlSandboxContext): string { - const { player, poster } = options; - const { live, state } = context; - const posterSrc = poster === undefined ? undefined : getPosterSrc(state.source); - const placeholder = poster === 'derived' ? getPlaceholderSrc(state.source) : undefined; - const children = html` - ${placeholder ? `` : ''} - ${options.media(context)} - ${poster === 'image' && posterSrc ? html`Video poster` : ''} - `; - - if (player === 'background') { - return html` - - <${skinTag}>${children} - - `; - } - - if (player === 'audio') { - const playerTag = live ? 'live-audio-player' : 'audio-player'; - - return html` -
- <${playerTag}> - <${skinTag}>${children} - -
- `; - } - - const playerTag = live ? 'live-video-player' : 'video-player'; - const posterAttr = poster === 'derived' && posterSrc ? ` poster="${escapeHtml(posterSrc)}"` : ''; - - return html` - <${playerTag}${posterAttr}> - <${skinTag} class="${PLAYER_FRAME_CLASSES.video}">${children} - - `; -} - function getRoot(): HTMLElement { const root = document.getElementById('root'); if (!root) throw new Error('The sandbox page has no #root element.'); @@ -184,9 +159,10 @@ function getRoot(): HTMLElement { } /** - * Mount a preview page: read the shell's selections, load the skin they name, render the player around the template's - * media markup, and render again as the shell streams changes. A locale change applies in place through `` - * once the player is up; a direction change renders again, since the provider owns the pinned `dir`. + * Mount a preview page: read the shell's selections, load the skin they name, render the template's player markup with + * the tags and sources they resolve to, and render again as the shell streams changes. A locale change applies in place + * through `` once the player is up; a direction change renders again, since the provider owns the pinned + * `dir`. */ export function createHtmlSandbox(options: HtmlSandboxOptions): void { const state = readSandboxState('html'); @@ -202,11 +178,11 @@ export function createHtmlSandbox(options: HtmlSandboxOptions): void { const skinTag = await loadLatest(() => loadSkinTag(options.player, state, live)); if (!skinTag) return; - const context = createContext(options, state, live); + const context = createContext(options, state, live, skinTag); const template = document.createElement('template'); - template.innerHTML = wrapSandboxHtmlI18n(renderPlayer(options, skinTag, context)); + template.innerHTML = wrapSandboxHtmlI18n(options.render(context)); // Subtitle tracks are the page's to add, so a template never has to spell them out. They go in while the markup is // still inert: a custom media element reads its tracks when it upgrades, not when children arrive later. diff --git a/apps/sandbox/app/shared/player-frame.ts b/apps/sandbox/app/shared/player-frame.ts index 5df64a8aab..d05d0119ee 100644 --- a/apps/sandbox/app/shared/player-frame.ts +++ b/apps/sandbox/app/shared/player-frame.ts @@ -16,8 +16,9 @@ export function defaultPlayerWidth(player: MediaPlayer): number { } /** - * How a preview frames its player: centred, and capped by the shell's width control through `--sandbox-player-width`, - * with the skin's own cap when a page is opened without one. + * How the React skin components frame their player: centred, and capped by the shell's width control through + * `--sandbox-player-width`, with the skin's own cap when a page is opened without one. The html templates write the + * plain `max-w-4xl` and `max-w-xl` classes a consumer would, and `styles.css` caps those the same way. */ export const PLAYER_FRAME_CLASSES = { // Keep centred controls on device pixels instead of the fractional height produced by aspect-ratio. diff --git a/apps/sandbox/app/styles.css b/apps/sandbox/app/styles.css index 946b292cd0..58943e15e4 100644 --- a/apps/sandbox/app/styles.css +++ b/apps/sandbox/app/styles.css @@ -46,6 +46,24 @@ } } +/* + * The shell's width control sizes the player through `--sandbox-player-width` (see `shared/player-frame.ts`). The html + * templates frame their player with the classes a consumer would write, `max-w-4xl` and `max-w-xl`, and these unlayered + * rules cap them at the control's width instead, falling back to those same widths when a page is opened without one. + * React pages take the equivalent classes through `VideoSkinComponent` and `AudioSkinComponent`. The CDN page puts + * `` inside the player rather than around it, hence the second selector. + */ +#root :is(video-player, live-video-player) > :not(media-i18n), +#root :is(video-player, live-video-player) > media-i18n > * { + max-width: var(--sandbox-player-width, 56rem); + /* Keep centred controls on device pixels instead of the fractional height produced by aspect-ratio. */ + height: round(nearest, calc(min(var(--sandbox-player-width, 56rem), 100vw - 1rem) * 9 / 16), 2px) !important; +} + +#root :has(> :is(audio-player, live-audio-player)) { + max-width: var(--sandbox-player-width, 36rem); +} + @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); diff --git a/apps/sandbox/templates/cdn/main.ts b/apps/sandbox/templates/cdn/main.ts index ca03ada35b..7aeee75955 100644 --- a/apps/sandbox/templates/cdn/main.ts +++ b/apps/sandbox/templates/cdn/main.ts @@ -10,7 +10,6 @@ import { ensureCdnSandboxLocale } from '@app/shared/i18n/cdn-sandbox-locales'; import { syncDocumentLocale } from '@app/shared/i18n/document-locale'; import type { SandboxLocaleTag } from '@app/shared/i18n/locale-meta'; import { findMediaTag } from '@app/shared/media-element'; -import { PLAYER_FRAME_CLASSES } from '@app/shared/player-frame'; import { getDirection, getInitialLocale, @@ -364,7 +363,7 @@ async function render() { if (descriptor.player === 'audio') { root.innerHTML = html` -
+
${wrapCdnPlayerI18n( playerTag, html` @@ -380,7 +379,7 @@ async function render() { } const skin = html` - <${skinTag} class="${PLAYER_FRAME_CLASSES.video}"> + <${skinTag} class="mx-auto aspect-video max-w-4xl"> <${mediaTag} ${mediaClassAttr} ${sourceAttr} ${mediaAttrs} playsinline ${crossoriginAttr}> ${skinnedVideo ? renderChapters(getChapters(state.source)) : ''} ${renderStoryboard(storyboard)} diff --git a/apps/sandbox/templates/html-audio/main.ts b/apps/sandbox/templates/html-audio/main.ts index 9acc37873e..fa34d6afda 100644 --- a/apps/sandbox/templates/html-audio/main.ts +++ b/apps/sandbox/templates/html-audio/main.ts @@ -4,5 +4,13 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'audio', - media: ({ src, attrs }) => html``, + render: ({ skinTag, src, attrs }) => html` +
+ + <${skinTag}> + + + +
+ `, }); diff --git a/apps/sandbox/templates/html-background-video/main.ts b/apps/sandbox/templates/html-background-video/main.ts index e0a85d05fe..c1237c0fde 100644 --- a/apps/sandbox/templates/html-background-video/main.ts +++ b/apps/sandbox/templates/html-background-video/main.ts @@ -7,5 +7,11 @@ import { BACKGROUND_VIDEO_SRC } from '@app/shared/sources'; createHtmlSandbox({ player: 'background', - media: () => html``, + render: () => html` + + + + + + `, }); diff --git a/apps/sandbox/templates/html-cloudflare-video/main.ts b/apps/sandbox/templates/html-cloudflare-video/main.ts index 4d3f2723be..cff9666567 100644 --- a/apps/sandbox/templates/html-cloudflare-video/main.ts +++ b/apps/sandbox/templates/html-cloudflare-video/main.ts @@ -6,6 +6,11 @@ import { CLOUDFLARE_VIDEO_SRC } from '@app/shared/sources'; createHtmlSandbox({ player: 'video', - media: () => - html``, + render: ({ skinTag }) => html` + + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + + + `, }); diff --git a/apps/sandbox/templates/html-dash-video/main.ts b/apps/sandbox/templates/html-dash-video/main.ts index 6e5e3c332a..a643cff57d 100644 --- a/apps/sandbox/templates/html-dash-video/main.ts +++ b/apps/sandbox/templates/html-dash-video/main.ts @@ -6,12 +6,16 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'video', - poster: 'image', - media: ({ src, attrs, storyboard }) => html` - ${storyboard} - - + render: ({ skinTag, src, attrs, storyboard, poster }) => html` + + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + ${storyboard} + + + ${poster ? html`Video poster` : ''} + + `, }); diff --git a/apps/sandbox/templates/html-hls-audio/main.ts b/apps/sandbox/templates/html-hls-audio/main.ts index a8aaeb7220..9b7ac9f5a9 100644 --- a/apps/sandbox/templates/html-hls-audio/main.ts +++ b/apps/sandbox/templates/html-hls-audio/main.ts @@ -7,5 +7,13 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'audio', live: true, - media: ({ src, attrs }) => html``, + render: ({ playerTag, skinTag, src, attrs }) => html` +
+ <${playerTag}> + <${skinTag}> + + + +
+ `, }); diff --git a/apps/sandbox/templates/html-hls-background-video/main.ts b/apps/sandbox/templates/html-hls-background-video/main.ts index 7710738756..dd7f1555bc 100644 --- a/apps/sandbox/templates/html-hls-background-video/main.ts +++ b/apps/sandbox/templates/html-hls-background-video/main.ts @@ -20,5 +20,11 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'background', - media: ({ src }) => html``, + render: ({ src }) => html` + + + + + + `, }); diff --git a/apps/sandbox/templates/html-hls-video/main.ts b/apps/sandbox/templates/html-hls-video/main.ts index 0e3559f099..424241f6c7 100644 --- a/apps/sandbox/templates/html-hls-video/main.ts +++ b/apps/sandbox/templates/html-hls-video/main.ts @@ -7,11 +7,15 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'video', live: true, - poster: 'image', - media: ({ src, attrs, chapters, storyboard }) => html` - - ${chapters} - ${storyboard} - + render: ({ playerTag, skinTag, src, attrs, chapters, storyboard, poster }) => html` + <${playerTag}> + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + ${chapters} + ${storyboard} + + ${poster ? html`Video poster` : ''} + + `, }); diff --git a/apps/sandbox/templates/html-hlsjs-video/main.ts b/apps/sandbox/templates/html-hlsjs-video/main.ts index c0c814426e..75413412f0 100644 --- a/apps/sandbox/templates/html-hlsjs-video/main.ts +++ b/apps/sandbox/templates/html-hlsjs-video/main.ts @@ -7,17 +7,21 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'video', live: true, - poster: 'image', // A source carrying DRM license servers has no room in the `src` attribute, so // it is assigned as an object below instead. Query-string playback overrides // need the object for the same reason, and need it before the first load so the // engine is built with them rather than reconfigured afterwards. playbackOverrides: true, - media: ({ src, attrs, chapters, storyboard }) => html` - - ${chapters} - ${storyboard} - + render: ({ playerTag, skinTag, src, attrs, chapters, storyboard, poster }) => html` + <${playerTag}> + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + ${chapters} + ${storyboard} + + ${poster ? html`Video poster` : ''} + + `, attach: ({ source }) => { if (source) document.querySelector('hlsjs-video')!.source = source; diff --git a/apps/sandbox/templates/html-mux-audio-spf/main.ts b/apps/sandbox/templates/html-mux-audio-spf/main.ts index 36126c326b..9ed57d044b 100644 --- a/apps/sandbox/templates/html-mux-audio-spf/main.ts +++ b/apps/sandbox/templates/html-mux-audio-spf/main.ts @@ -20,15 +20,21 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'audio', live: true, - media: ({ src, attrs }) => html` - - - - + render: ({ playerTag, skinTag, src, attrs }) => html` +
+ <${playerTag}> + <${skinTag}> + + + + + + +
`, // A source carrying signed tokens has no room in the `src` attribute, so it is // assigned as an object instead. `source.drm` is accepted but inert here: SPF diff --git a/apps/sandbox/templates/html-mux-audio/main.ts b/apps/sandbox/templates/html-mux-audio/main.ts index af307cfa34..54e9b22342 100644 --- a/apps/sandbox/templates/html-mux-audio/main.ts +++ b/apps/sandbox/templates/html-mux-audio/main.ts @@ -9,11 +9,17 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'audio', live: true, - media: ({ src, attrs }) => html` - - - - + render: ({ playerTag, skinTag, src, attrs }) => html` +
+ <${playerTag}> + <${skinTag}> + + + + + + +
`, // A source carrying signed tokens has no room in the `src` attribute, so it is // assigned as an object instead — the same way `html-mux-video` does. diff --git a/apps/sandbox/templates/html-mux-background-video/main.ts b/apps/sandbox/templates/html-mux-background-video/main.ts index f7684ac906..73d380d4d7 100644 --- a/apps/sandbox/templates/html-mux-background-video/main.ts +++ b/apps/sandbox/templates/html-mux-background-video/main.ts @@ -20,7 +20,11 @@ import { withMuxMaxResolution } from '@app/shared/sources'; createHtmlSandbox({ player: 'background', - media: ({ url }) => html` - + render: ({ url }) => html` + + + + + `, }); diff --git a/apps/sandbox/templates/html-mux-video-spf/main.ts b/apps/sandbox/templates/html-mux-video-spf/main.ts index 890fa48818..b189f87003 100644 --- a/apps/sandbox/templates/html-mux-video-spf/main.ts +++ b/apps/sandbox/templates/html-mux-video-spf/main.ts @@ -23,13 +23,18 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'video', live: true, - poster: 'derived', - media: ({ src, attrs }) => html` - - - - - + render: ({ playerTag, skinTag, src, attrs, poster, placeholder }) => html` + <${playerTag}${poster ? ` poster="${poster}"` : ''}> + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + ${placeholder ? html`` : ''} + + + + + + + `, // A source carrying signed tokens has no room in the `src` attribute, so it is // assigned as an object instead. `source.drm` is accepted but inert here: SPF diff --git a/apps/sandbox/templates/html-mux-video/main.ts b/apps/sandbox/templates/html-mux-video/main.ts index cbc7207395..fa1d3c5bde 100644 --- a/apps/sandbox/templates/html-mux-video/main.ts +++ b/apps/sandbox/templates/html-mux-video/main.ts @@ -9,18 +9,23 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'video', live: true, - poster: 'derived', // A source carrying signed tokens has no room in the `src` attribute, so it is // assigned as an object below instead. Query-string playback overrides need the // object for the same reason, and need it before the first load so the engine is // built with them rather than reconfigured afterwards. playbackOverrides: true, - media: ({ src, attrs, chapters }) => html` - - ${chapters} - - - + render: ({ playerTag, skinTag, src, attrs, chapters, poster, placeholder }) => html` + <${playerTag}${poster ? ` poster="${poster}"` : ''}> + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + ${placeholder ? html`` : ''} + + ${chapters} + + + + + `, // A Mux `source.drm.token` becomes the FairPlay / Widevine / PlayReady license // servers; the playback, poster, and storyboard tokens sign the rest. diff --git a/apps/sandbox/templates/html-native-hls-video/main.ts b/apps/sandbox/templates/html-native-hls-video/main.ts index 5cfc9cdc99..f5885672e6 100644 --- a/apps/sandbox/templates/html-native-hls-video/main.ts +++ b/apps/sandbox/templates/html-native-hls-video/main.ts @@ -7,12 +7,16 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'video', live: true, - poster: 'image', - media: ({ src, attrs, chapters, storyboard }) => html` - - ${chapters} - ${storyboard} - + render: ({ playerTag, skinTag, src, attrs, chapters, storyboard, poster }) => html` + <${playerTag}> + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + ${chapters} + ${storyboard} + + ${poster ? html`Video poster` : ''} + + `, // A source carrying DRM license servers has no room in the `src` attribute, so // it is assigned as an object instead. Only the FairPlay entry of its `drm` is diff --git a/apps/sandbox/templates/html-shaka-video/main.ts b/apps/sandbox/templates/html-shaka-video/main.ts index 06295579d5..faadcbe40c 100644 --- a/apps/sandbox/templates/html-shaka-video/main.ts +++ b/apps/sandbox/templates/html-shaka-video/main.ts @@ -5,10 +5,14 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'video', - poster: 'image', - media: ({ src, attrs, storyboard }) => html` - - ${storyboard} + render: ({ skinTag, src, attrs, storyboard, poster }) => html` + + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + ${storyboard} + ${poster ? html`Video poster` : ''} + + `, }); diff --git a/apps/sandbox/templates/html-spotify-audio/main.ts b/apps/sandbox/templates/html-spotify-audio/main.ts index 69f85509d5..92fc9f0856 100644 --- a/apps/sandbox/templates/html-spotify-audio/main.ts +++ b/apps/sandbox/templates/html-spotify-audio/main.ts @@ -6,8 +6,14 @@ import { SPOTIFY_AUDIO_SRC } from '@app/shared/sources'; createHtmlSandbox({ player: 'audio', - media: () => html` - - + render: ({ skinTag }) => html` +
+ + <${skinTag}> + + + + +
`, }); diff --git a/apps/sandbox/templates/html-tiktok-video/main.ts b/apps/sandbox/templates/html-tiktok-video/main.ts index 018ce98722..e347b9e78e 100644 --- a/apps/sandbox/templates/html-tiktok-video/main.ts +++ b/apps/sandbox/templates/html-tiktok-video/main.ts @@ -6,8 +6,12 @@ import { TIKTOK_VIDEO_SRC } from '@app/shared/sources'; createHtmlSandbox({ player: 'video', - media: () => html` - - + render: ({ skinTag }) => html` + + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + + + `, }); diff --git a/apps/sandbox/templates/html-twitch-video/main.ts b/apps/sandbox/templates/html-twitch-video/main.ts index c64a2d20b6..0250b4d44f 100644 --- a/apps/sandbox/templates/html-twitch-video/main.ts +++ b/apps/sandbox/templates/html-twitch-video/main.ts @@ -6,5 +6,11 @@ import { TWITCH_VIDEO_SRC } from '@app/shared/sources'; createHtmlSandbox({ player: 'video', - media: () => html``, + render: ({ skinTag }) => html` + + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + + + `, }); diff --git a/apps/sandbox/templates/html-video/main.ts b/apps/sandbox/templates/html-video/main.ts index b182d31cfc..49ce80678b 100644 --- a/apps/sandbox/templates/html-video/main.ts +++ b/apps/sandbox/templates/html-video/main.ts @@ -4,11 +4,15 @@ import { createHtmlSandbox, html } from '@app/shared/html/sandbox'; createHtmlSandbox({ player: 'video', - poster: 'image', - media: ({ src, attrs, chapters, storyboard }) => html` - - ${chapters} - ${storyboard} - + render: ({ skinTag, src, attrs, chapters, storyboard, poster }) => html` + + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + ${chapters} + ${storyboard} + + ${poster ? html`Video poster` : ''} + + `, }); diff --git a/apps/sandbox/templates/html-vimeo-video/main.ts b/apps/sandbox/templates/html-vimeo-video/main.ts index 680cafc853..549fed47e6 100644 --- a/apps/sandbox/templates/html-vimeo-video/main.ts +++ b/apps/sandbox/templates/html-vimeo-video/main.ts @@ -6,5 +6,11 @@ import { VIMEO_VIDEO_SRC } from '@app/shared/sources'; createHtmlSandbox({ player: 'video', - media: () => html``, + render: ({ skinTag }) => html` + + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + + + `, }); diff --git a/apps/sandbox/templates/html-wistia-video/main.ts b/apps/sandbox/templates/html-wistia-video/main.ts index 62d66b5446..fe9d2f0f43 100644 --- a/apps/sandbox/templates/html-wistia-video/main.ts +++ b/apps/sandbox/templates/html-wistia-video/main.ts @@ -6,5 +6,11 @@ import { WISTIA_VIDEO_SRC } from '@app/shared/sources'; createHtmlSandbox({ player: 'video', - media: () => html``, + render: ({ skinTag }) => html` + + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + + + `, }); diff --git a/apps/sandbox/templates/html-youtube-video/main.ts b/apps/sandbox/templates/html-youtube-video/main.ts index bc408fea43..54f31abb8c 100644 --- a/apps/sandbox/templates/html-youtube-video/main.ts +++ b/apps/sandbox/templates/html-youtube-video/main.ts @@ -6,5 +6,11 @@ import { YOUTUBE_VIDEO_SRC } from '@app/shared/sources'; createHtmlSandbox({ player: 'video', - media: () => html``, + render: ({ skinTag }) => html` + + <${skinTag} class="mx-auto aspect-video max-w-4xl"> + + + + `, });