# VJS-10 Architecture & Design Philosophy ## How to Read This Document This document describes VJS-10's **architectural principles and patterns**, not implementation chronology. **Status Indicators:** - βœ… **Implemented** - Currently exists in codebase with code references - 🚧 **In Progress** - Partially implemented, under active development - πŸ“‹ **Planned** - Architectural vision, not yet started **Code References:** - File paths link to actual implementation locations - Examples show real patterns from working code - Sections without status indicators describe foundational principles --- ## Overview VJS-10 represents a significant architectural evolution in media player component libraries, prioritizing platform-native development experiences while maintaining shared core logic. This document outlines the design philosophy, architectural influences, and key decisions that shape the VJS-10 ecosystem. ## Architectural Influences & Inspirations ### Media Elements: Platform-Agnostic HTMLMediaElement Contract VJS-10's media state management architecture draws significant inspiration from the [media-elements monorepo](https://github.com/muxinc/media-elements), which pioneered the concept of creating HTMLMediaElement-compatible elements that work across different media providers while maintaining consistent interfaces. #### 1. Extended HTMLMediaElement Contract Foundation **Media Elements Innovation**: The media-elements monorepo established the pattern of creating custom elements that "look like" HTMLMediaElement but can be extended for different media providers (HLS, DASH, YouTube, Vimeo, etc.). **Core Architecture Pattern**: ```typescript // Media Elements: CustomVideoElement extends HTMLVideoElement export class CustomVideoElement extends HTMLVideoElement implements HTMLVideoElement { readonly nativeEl: HTMLVideoElement; // Maintains HTMLMediaElement contract get currentTime() { return this.nativeEl?.currentTime ?? 0; } set currentTime(val) { if (this.nativeEl) this.nativeEl.currentTime = val; } play(): Promise { return this.nativeEl?.play() ?? Promise.resolve(); } pause(): void { this.nativeEl?.pause(); } } // Provider-specific implementations class HlsVideoElement extends CustomVideoElement { api: Hls | null = null; async load() { if (Hls.isSupported()) { this.api = new Hls(this.config); this.api.loadSource(this.src); this.api.attachMedia(this.nativeEl); } } } ``` **Key Architectural Assumptions**: - Media state owner must be an `HTMLElement` (DOM-based) - Must implement the complete `HTMLMediaElement` interface - Provider-specific logic encapsulated in custom element classes - Shadow DOM for consistent styling and behavior **Reference**: [`packages/custom-media-element/custom-media-element.ts`](https://github.com/muxinc/media-elements/blob/main/packages/custom-media-element/custom-media-element.ts) #### 2. VJS-10's Platform-Agnostic Evolution **VJS-10 Innovation**: Relaxed the HTMLElement requirement while maintaining the HTMLMediaElement contract, enabling true cross-platform compatibility. **Architectural Relaxation**: ```typescript // VJS-10: MediaStateOwner - JavaScript interface only export type MediaStateOwner = Partial & Pick & EventTarget & { // Only requires EventTarget, not HTMLElement // HTMLMediaElement contract maintained currentTime?: number; duration?: number; volume?: number; muted?: boolean; paused?: boolean; // Extended media-specific properties (Media Elements influence) streamType?: StreamTypes; targetLiveWindow?: number; videoRenditions?: Rendition[] & EventTarget; audioTracks?: AudioTrack[] & EventTarget; // Platform-specific extensions webkitDisplayingFullscreen?: boolean; webkitCurrentPlaybackTargetIsWireless?: boolean; }; ``` **Cross-Platform Implementation**: **HTML Platform** (Media Elements Heritage): ```typescript // Direct evolution from media-elements CustomVideoElement export class MediaVideoElement extends HTMLVideoElement implements MediaStateOwner { connectedCallback() { // Media Elements pattern: delegate to native element this.mediaStore = createMediaStore(this.nativeEl); } } ``` **React Platform** (Platform-Agnostic Contract): ```typescript // Uses HTMLVideoElement but not as DOM element export function useVideoElement(): MediaStateOwner { const videoRef = useRef(null); return useMemo(() => ({ // Maintains HTMLMediaElement contract without DOM assumptions get currentTime() { return videoRef.current?.currentTime ?? 0; }, set currentTime(val) { if (videoRef.current) videoRef.current.currentTime = val; }, play: () => videoRef.current?.play() ?? Promise.resolve(), pause: () => videoRef.current?.pause(), addEventListener: (type, listener) => videoRef.current?.addEventListener(type, listener), removeEventListener: (type, listener) => videoRef.current?.removeEventListener(type, listener), }), []); } ``` **React Native Platform** (Contract Without HTMLMediaElement): ```typescript // Implements MediaStateOwner contract with React Native Video export function useVideoElementNative(): MediaStateOwner { const videoRef = useRef