mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
chore(site): rewrite media element builder for MediaHost architecture (#1334)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
b731cba6ba
commit
d8cd59e0fd
Vendored
+84
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Mock media contract types — mirrors packages/core/src/core/media/types.ts.
|
||||
*
|
||||
* Exercises: event extraction from capability event interfaces.
|
||||
* VideoEvents extends all capability events (including TextTrackListEvents).
|
||||
* AudioEvents extends a subset (no text track events).
|
||||
*/
|
||||
|
||||
export interface EventLike<Detail = void> {
|
||||
readonly type: string;
|
||||
readonly timeStamp: number;
|
||||
readonly detail?: Detail;
|
||||
}
|
||||
|
||||
export interface MediaPlaybackEvents {
|
||||
play: EventLike;
|
||||
playing: EventLike;
|
||||
waiting: EventLike;
|
||||
}
|
||||
|
||||
export interface MediaPauseEvents {
|
||||
pause: EventLike;
|
||||
ended: EventLike;
|
||||
}
|
||||
|
||||
export interface MediaSeekEvents {
|
||||
timeupdate: EventLike;
|
||||
durationchange: EventLike;
|
||||
seeking: EventLike;
|
||||
seeked: EventLike;
|
||||
loadedmetadata: EventLike;
|
||||
}
|
||||
|
||||
export interface MediaSourceEvents {
|
||||
loadstart: EventLike;
|
||||
emptied: EventLike;
|
||||
canplay: EventLike;
|
||||
canplaythrough: EventLike;
|
||||
loadeddata: EventLike;
|
||||
}
|
||||
|
||||
export interface MediaVolumeEvents {
|
||||
volumechange: EventLike;
|
||||
}
|
||||
|
||||
export interface MediaPlaybackRateEvents {
|
||||
ratechange: EventLike;
|
||||
}
|
||||
|
||||
export interface MediaBufferEvents {
|
||||
progress: EventLike;
|
||||
}
|
||||
|
||||
export interface MediaErrorEvents {
|
||||
error: EventLike;
|
||||
}
|
||||
|
||||
export interface TextTrackListEvents {
|
||||
addtrack: EventLike;
|
||||
removetrack: EventLike;
|
||||
changetrack: EventLike;
|
||||
trackmodechange: EventLike;
|
||||
}
|
||||
|
||||
export interface VideoEvents
|
||||
extends MediaPlaybackEvents,
|
||||
MediaPauseEvents,
|
||||
MediaSeekEvents,
|
||||
MediaSourceEvents,
|
||||
MediaVolumeEvents,
|
||||
MediaPlaybackRateEvents,
|
||||
MediaBufferEvents,
|
||||
MediaErrorEvents,
|
||||
TextTrackListEvents {}
|
||||
|
||||
export interface AudioEvents
|
||||
extends MediaPlaybackEvents,
|
||||
MediaPauseEvents,
|
||||
MediaSeekEvents,
|
||||
MediaSourceEvents,
|
||||
MediaVolumeEvents,
|
||||
MediaPlaybackRateEvents,
|
||||
MediaBufferEvents,
|
||||
MediaErrorEvents {}
|
||||
+5
-9
@@ -1,11 +1,13 @@
|
||||
/**
|
||||
* Mock complex delegate — mirrors HlsMediaBase.
|
||||
* Mock complex host — mirrors HlsMedia.
|
||||
*
|
||||
* Exercises: multiple getter/setter pairs with JSDoc descriptions,
|
||||
* readonly properties, boolean type, overlap with native Attributes
|
||||
* readonly properties, boolean type, overlap with native attributes
|
||||
* (src, preload) that should be deduplicated by the builder.
|
||||
*/
|
||||
export class ComplexDelegate {
|
||||
import { HTMLVideoElementHost } from '../simple';
|
||||
|
||||
export class ComplexHost extends HTMLVideoElementHost {
|
||||
#src: string = '';
|
||||
#type: string | undefined;
|
||||
#preferPlayback: string | undefined = 'mse';
|
||||
@@ -69,10 +71,4 @@ export class ComplexDelegate {
|
||||
get engine(): object | null {
|
||||
return this.#engine;
|
||||
}
|
||||
|
||||
attach(_target: EventTarget): void {}
|
||||
detach(): void {}
|
||||
destroy(): void {}
|
||||
}
|
||||
|
||||
export class ComplexCustomMedia {}
|
||||
|
||||
+41
-46
@@ -1,37 +1,14 @@
|
||||
/**
|
||||
* Mock custom media element infrastructure.
|
||||
*
|
||||
* Exercises: shared Events, Attributes, and CSS vars that the builder reads
|
||||
* to populate media element references. Slots are parsed from the template
|
||||
* HTML (getVideoTemplateHTML / getAudioTemplateHTML), not from exported arrays.
|
||||
* Exercises: shared native attributes (via static properties), CSS vars,
|
||||
* and slots that the builder reads to populate media element references.
|
||||
* Slots are parsed from getVideoTemplateHTML / getCommonTemplateHTML.
|
||||
*
|
||||
* VideoCSSVars/AudioCSSVars follow the `{ camelKey: '--var-name' }` pattern
|
||||
* with JSDoc descriptions, matching UI component css-vars files.
|
||||
*/
|
||||
|
||||
export const Events = [
|
||||
'abort',
|
||||
'canplay',
|
||||
'durationchange',
|
||||
'ended',
|
||||
'pause',
|
||||
'play',
|
||||
'timeupdate',
|
||||
'volumechange',
|
||||
] as const;
|
||||
|
||||
export const Attributes = [
|
||||
'autoplay',
|
||||
'controls',
|
||||
'crossorigin',
|
||||
'loop',
|
||||
'muted',
|
||||
'playsinline',
|
||||
'poster',
|
||||
'preload',
|
||||
'src',
|
||||
] as const;
|
||||
|
||||
/** CSS custom property names for video elements. */
|
||||
export const VideoCSSVars = {
|
||||
/** Border radius of the video element. */
|
||||
@@ -68,26 +45,44 @@ function getVideoTemplateHTML(attrs: Record<string, string>): string {
|
||||
`;
|
||||
}
|
||||
|
||||
function getAudioTemplateHTML(attrs: Record<string, string>): string {
|
||||
return /*html*/ `
|
||||
<style>
|
||||
audio { width: 100%; }
|
||||
</style>
|
||||
<slot name="media">
|
||||
<audio></audio>
|
||||
</slot>
|
||||
<slot></slot>
|
||||
`;
|
||||
function getCommonTemplateHTML(tag: string) {
|
||||
return (attrs: Record<string, string>) => {
|
||||
return /*html*/ `
|
||||
<style>
|
||||
${tag} { width: 100%; }
|
||||
</style>
|
||||
<slot name="media">
|
||||
<${tag}></${tag}>
|
||||
</slot>
|
||||
<slot></slot>
|
||||
`;
|
||||
};
|
||||
}
|
||||
|
||||
// Minimal stubs — the builder only needs to detect these by name, not run them.
|
||||
export function CustomMediaMixin(base: any, _opts: any) {
|
||||
return base;
|
||||
}
|
||||
// Stub — the builder parses the AST, it doesn't run the code.
|
||||
// Mirrors the real CustomMediaElement factory signature.
|
||||
export function CustomMediaElement(tag: string, Host: any) {
|
||||
class CustomMedia {
|
||||
static getTemplateHTML = tag === 'video' ? getVideoTemplateHTML : getCommonTemplateHTML(tag);
|
||||
static shadowRootOptions = { mode: 'open' };
|
||||
|
||||
export const CustomVideoElement = class {
|
||||
static getTemplateHTML = getVideoTemplateHTML;
|
||||
};
|
||||
export const CustomAudioElement = class {
|
||||
static getTemplateHTML = getAudioTemplateHTML;
|
||||
};
|
||||
static properties = {
|
||||
autoPictureInPicture: { type: Boolean },
|
||||
autoplay: { type: Boolean },
|
||||
controls: { type: Boolean },
|
||||
controlsList: { type: String },
|
||||
crossOrigin: { type: String },
|
||||
defaultMuted: { type: Boolean, attribute: 'muted' },
|
||||
disablePictureInPicture: { type: Boolean },
|
||||
disableRemotePlayback: { type: Boolean },
|
||||
loading: { type: String },
|
||||
loop: { type: Boolean },
|
||||
playsInline: { type: Boolean },
|
||||
poster: { type: String },
|
||||
preload: { type: String },
|
||||
src: { type: String },
|
||||
};
|
||||
}
|
||||
|
||||
return CustomMedia;
|
||||
}
|
||||
|
||||
+5
-7
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* Mock extending delegate — mirrors MuxMediaBase extending HlsMediaBase.
|
||||
* Mock extending host — mirrors MuxVideoMedia extending HlsMedia.
|
||||
*
|
||||
* Exercises: delegate inheritance. The builder must walk the extends chain
|
||||
* to extract properties from both this class and its parent (ComplexDelegate).
|
||||
* Exercises: host inheritance. The builder must walk the extends chain
|
||||
* to extract properties from both this class and its parent (ComplexHost).
|
||||
* Child properties override parent properties of the same name.
|
||||
*/
|
||||
import { ComplexDelegate } from '../complex';
|
||||
import { ComplexHost } from '../complex';
|
||||
|
||||
export class ExtendingDelegate extends ComplexDelegate {
|
||||
export class ExtendingHost extends ComplexHost {
|
||||
#playbackId: string = '';
|
||||
#customDomain: string = '';
|
||||
|
||||
@@ -38,5 +38,3 @@ export class ExtendingDelegate extends ComplexDelegate {
|
||||
super.debug = value;
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtendingCustomMedia {}
|
||||
|
||||
+11
-9
@@ -1,10 +1,18 @@
|
||||
/**
|
||||
* Mock simple delegate — mirrors DashMediaBase.
|
||||
* Mock simple host — mirrors DashMedia.
|
||||
*
|
||||
* Exercises: minimal delegate with just src (read-write) and engine (readonly).
|
||||
* Exercises: minimal host with just src (read-write) and engine (readonly).
|
||||
* No JSDoc on properties — tests that missing descriptions produce undefined.
|
||||
*/
|
||||
export class SimpleDelegate {
|
||||
|
||||
// Stub — the builder walks the prototype chain and stops here.
|
||||
export class HTMLVideoElementHost {
|
||||
attach(_target: EventTarget): void {}
|
||||
detach(): void {}
|
||||
destroy(): void {}
|
||||
}
|
||||
|
||||
export class SimpleHost extends HTMLVideoElementHost {
|
||||
#src: string = '';
|
||||
#engine: object = {};
|
||||
|
||||
@@ -19,10 +27,4 @@ export class SimpleDelegate {
|
||||
get engine(): object {
|
||||
return this.#engine;
|
||||
}
|
||||
|
||||
attach(_target: EventTarget): void {}
|
||||
detach(): void {}
|
||||
destroy(): void {}
|
||||
}
|
||||
|
||||
export class SimpleCustomMedia {}
|
||||
|
||||
+7
-8
@@ -1,17 +1,16 @@
|
||||
/**
|
||||
* Mock complex media element — mirrors HlsVideo.
|
||||
*
|
||||
* Exercises: standard mixin composition with a complex delegate
|
||||
* that has JSDoc descriptions on its getter/setters.
|
||||
* Exercises: standard composition with CustomMediaElement factory
|
||||
* and a complex host that has JSDoc descriptions on its getter/setters.
|
||||
*/
|
||||
import { ComplexCustomMedia, ComplexDelegate } from '../../../../core/src/dom/media/complex';
|
||||
|
||||
// Stubs — the builder parses the AST, it doesn't run the code.
|
||||
import { ComplexHost } from '../../../../core/src/dom/media/complex';
|
||||
import { CustomMediaElement } from '../../../../core/src/dom/media/custom-media-element';
|
||||
|
||||
// Stub — the builder parses the AST, it doesn't run the code.
|
||||
function MediaAttachMixin(base: any) {
|
||||
return base;
|
||||
}
|
||||
function MediaPropsMixin(base: any, _delegate: any) {
|
||||
return base;
|
||||
}
|
||||
|
||||
export class ComplexVideo extends MediaPropsMixin(MediaAttachMixin(ComplexCustomMedia), ComplexDelegate) {}
|
||||
export class ComplexVideo extends MediaAttachMixin(CustomMediaElement('video', ComplexHost)) {}
|
||||
|
||||
+4
-6
@@ -1,15 +1,13 @@
|
||||
/**
|
||||
* Mock extending media element — mirrors MuxVideo.
|
||||
*
|
||||
* Exercises: media element with a delegate that inherits from another delegate.
|
||||
* Exercises: media element with a host that inherits from another host.
|
||||
*/
|
||||
import { ExtendingCustomMedia, ExtendingDelegate } from '../../../../core/src/dom/media/extending';
|
||||
import { CustomMediaElement } from '../../../../core/src/dom/media/custom-media-element';
|
||||
import { ExtendingHost } from '../../../../core/src/dom/media/extending';
|
||||
|
||||
function MediaAttachMixin(base: any) {
|
||||
return base;
|
||||
}
|
||||
function MediaPropsMixin(base: any, _delegate: any) {
|
||||
return base;
|
||||
}
|
||||
|
||||
export class ExtendingVideo extends MediaPropsMixin(MediaAttachMixin(ExtendingCustomMedia), ExtendingDelegate) {}
|
||||
export class ExtendingVideo extends MediaAttachMixin(CustomMediaElement('video', ExtendingHost)) {}
|
||||
|
||||
+6
-8
@@ -1,18 +1,16 @@
|
||||
/**
|
||||
* Mock simple media element — mirrors DashVideo.
|
||||
*
|
||||
* Exercises: standard mixin composition with a simple delegate.
|
||||
* The builder follows this import chain to discover the delegate class
|
||||
* Exercises: standard composition with CustomMediaElement factory.
|
||||
* The builder follows this import chain to discover the host class
|
||||
* and resolve its properties.
|
||||
*/
|
||||
import { SimpleCustomMedia, SimpleDelegate } from '../../../../core/src/dom/media/simple';
|
||||
import { CustomMediaElement } from '../../../../core/src/dom/media/custom-media-element';
|
||||
import { SimpleHost } from '../../../../core/src/dom/media/simple';
|
||||
|
||||
// Stubs — the builder parses the AST, it doesn't run the code.
|
||||
// Stub — the builder parses the AST, it doesn't run the code.
|
||||
function MediaAttachMixin(base: any) {
|
||||
return base;
|
||||
}
|
||||
function MediaPropsMixin(base: any, _delegate: any) {
|
||||
return base;
|
||||
}
|
||||
|
||||
export class SimpleVideo extends MediaPropsMixin(MediaAttachMixin(SimpleCustomMedia), SimpleDelegate) {}
|
||||
export class SimpleVideo extends MediaAttachMixin(CustomMediaElement('video', SimpleHost)) {}
|
||||
|
||||
Reference in New Issue
Block a user