feat: initialize Video.js 10 monorepo with core architecture

- Set up monorepo structure with core, HTML, React, and React Native packages
- Add TypeScript configuration with project references
- Create foundational packages: media-store, playback-engine, media, icons
- Implement platform-specific packages for HTML, React, and React Native
- Add comprehensive documentation and development tooling
- Include CLAUDE.md with development guidelines and conventional commits

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Christian Pillsbury
2025-07-29 10:41:46 -07:00
co-authored by Claude
commit 4b0d84e9c8
55 changed files with 3421 additions and 0 deletions
@@ -0,0 +1,83 @@
export interface MediaSource {
src: string;
type: string;
}
export interface PlaybackEngineOptions {
autoplay?: boolean;
preload?: 'none' | 'metadata' | 'auto';
}
export abstract class PlaybackEngine {
protected element: HTMLMediaElement | null = null;
protected options: PlaybackEngineOptions;
constructor(options: PlaybackEngineOptions = {}) {
this.options = options;
}
abstract attach(element: HTMLMediaElement): void;
abstract detach(): void;
abstract load(source: MediaSource): Promise<void>;
abstract play(): Promise<void>;
abstract pause(): void;
abstract seekTo(time: number): void;
getElement(): HTMLMediaElement | null {
return this.element;
}
}
export class NativePlaybackEngine extends PlaybackEngine {
attach(element: HTMLMediaElement): void {
this.element = element;
}
detach(): void {
this.element = null;
}
async load(source: MediaSource): Promise<void> {
if (!this.element) {
throw new Error('No media element attached');
}
this.element.src = source.src;
await new Promise((resolve, reject) => {
const onLoad = () => {
this.element!.removeEventListener('loadedmetadata', onLoad);
this.element!.removeEventListener('error', onError);
resolve(void 0);
};
const onError = () => {
this.element!.removeEventListener('loadedmetadata', onLoad);
this.element!.removeEventListener('error', onError);
reject(new Error('Failed to load media'));
};
this.element.addEventListener('loadedmetadata', onLoad);
this.element.addEventListener('error', onError);
});
}
async play(): Promise<void> {
if (!this.element) {
throw new Error('No media element attached');
}
await this.element.play();
}
pause(): void {
if (!this.element) {
throw new Error('No media element attached');
}
this.element.pause();
}
seekTo(time: number): void {
if (!this.element) {
throw new Error('No media element attached');
}
this.element.currentTime = time;
}
}