feat(monorepo): migrate prototype code to organized package structure

Migrate all prototype code from vjs10-prototype repository into the
monorepo structure following established dependency hierarchy and
package organization patterns.

Core packages migrated:
- @vjs-10/media-store: Complete media store with nanostores integration
- @vjs-10/playback-engine: HLS.js playback engine implementation
- @vjs-10/media: Core media state owner and interfaces

HTML packages migrated:
- @vjs-10/html-icons: Web component icons with proper base classes
- @vjs-10/html-media-elements: Context provider integration
- @vjs-10/html: Main HTML UI components, skins, and utilities

React packages migrated:
- @vjs-10/react-icons: React icon components
- @vjs-10/react-media-elements: Video component with state integration
- @vjs-10/react-media-store: MediaProvider and React hooks
- @vjs-10/react: Main React UI components and skins

Changes made:
- Updated all imports to use monorepo package names (@vjs-10/*)
- Distributed dependencies to specific packages that use them
- Preserved all prototype functionality and component structure
- Created proper index files for all packages
- Fixed workspace protocol usage for npm compatibility

🤖 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 13:17:46 -07:00
co-authored by Claude
parent fc5a0e46fd
commit 4b472ec49c
61 changed files with 1967 additions and 995 deletions
@@ -0,0 +1,76 @@
import Hls from 'hls.js';
/** @TODO Move interface/type defs (CJP) */
/** @TODO Narrow and/or parameterize EventTarget via generics/inference (CJP) */
export interface IBasePlaybackEngine extends EventTarget {
src: HTMLMediaElement['src'] | undefined;
// NOTE: Unlike other APIs, this *must* be an HTMLMediaElement based on internal and/or external API assumptions (CJP)
mediaElement: HTMLMediaElement | undefined;
/** @TODO Widen/extend and/or parameterize EventTarget via generics/inference (CJP) */
element: HTMLElement | undefined;
destroy: () => void;
}
export class HlsJSPlaybackEngine extends EventTarget {
constructor() {
super();
}
protected _hlsInstance: Hls | undefined;
get src() {
return this._hlsInstance?.url ?? undefined;
}
set src(val) {
if (this.src === val) return;
if (!this._hlsInstance) {
this._createHlsInstance();
}
if (!this.src && val) {
this._hlsInstance?.loadSource(val);
}
}
// NOTE: Some playback engines may not rely on an underlying HTMLMediaElement but still have
// an HTMLElement (e.g. HTMLCanvasElement, HTMLImageElement, etc.). This API provides a more
// generic interface for cases where we want more minimal assumptions (e.g. fullscreen behaviors for most playtforms but not iOS)
get element(): HTMLElement | undefined {
return this.mediaElement;
}
set element(val) {
if (this.element === val) return;
/** @TODO programmatic type checking? (CJP) */
this.mediaElement = val as HTMLMediaElement;
}
get mediaElement() {
return this._hlsInstance?.media ?? undefined;
}
set mediaElement(val) {
if (this.mediaElement === val) return;
if (!this._hlsInstance) {
this._createHlsInstance();
}
if (!this.mediaElement && val) {
this._hlsInstance?.attachMedia(val);
}
}
protected _createHlsInstance() {
this._hlsInstance = new Hls();
}
protected _destroyHlsInstance() {
this._hlsInstance?.destroy();
this._hlsInstance = undefined;
}
destroy() {
this._destroyHlsInstance();
}
}
export const createPlaybackEngine = () => new HlsJSPlaybackEngine();