From 4448a5b252f0873fcf5e2340f4d8fb3adf1943e5 Mon Sep 17 00:00:00 2001 From: Christian Pillsbury Date: Tue, 21 Oct 2025 14:02:10 -0700 Subject: [PATCH] docs: readmes v0 (#72) Co-authored-by: Claude --- README.md | 218 +++++- eslint.config.mjs | 28 + packages/core/core/README.md | 286 ++++++++ packages/core/icons/README.md | 234 ++++++ packages/core/media-store/README.md | 205 ++++++ packages/core/media/README.md | 293 ++++++++ packages/core/playback-engine/README.md | 240 +++++++ packages/html/html-icons/README.md | 307 ++++++++ packages/html/html-media-elements/README.md | 330 +++++++++ packages/html/html-media-store/README.md | 384 ++++++++++ packages/html/html/README.md | 429 +++++++++++ packages/react/react-media-elements/README.md | 482 +++++++++++++ packages/react/react-media-store/README.md | 530 ++++++++++++++ packages/react/react/README.md | 672 ++++++++++++++++++ 14 files changed, 4618 insertions(+), 20 deletions(-) create mode 100644 packages/core/core/README.md create mode 100644 packages/core/icons/README.md create mode 100644 packages/core/media-store/README.md create mode 100644 packages/core/media/README.md create mode 100644 packages/core/playback-engine/README.md create mode 100644 packages/html/html-icons/README.md create mode 100644 packages/html/html-media-elements/README.md create mode 100644 packages/html/html-media-store/README.md create mode 100644 packages/html/html/README.md create mode 100644 packages/react/react-media-elements/README.md create mode 100644 packages/react/react-media-store/README.md create mode 100644 packages/react/react/README.md diff --git a/README.md b/README.md index fff2084e..6bb84880 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ # VJS-10 Monorepo -A monorepo for Video.js 10 related library packages, organized by platform and runtime environment. +> Modern, modular media player framework for web, React, and React Native + +[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) +[![pnpm](https://img.shields.io/badge/maintained%20with-pnpm-cc00ff.svg)](https://pnpm.io/) + +A monorepo for Video.js 10 related library packages, organized by platform and runtime environment with a clean dependency hierarchy. --- @@ -28,6 +33,44 @@ Thank you! --- +## Quick Start + +### HTML / Vanilla JavaScript + +```bash +npm install @vjs-10/html +``` + +```html + +``` + +### React + +```bash +npm install @vjs-10/react +``` + +```jsx +import { VideoPlayer } from '@vjs-10/react'; + + +``` + +### React Native + +```bash +npm install @vjs-10/react-native +``` + +```jsx +import { VideoPlayer } from '@vjs-10/react-native'; + + +``` + +--- + ## Structure ```bash @@ -60,30 +103,47 @@ vjs-10-monorepo/ ### Core Packages (Runtime Agnostic) -- **@vjs-10/media-store** - State management for media players -- **@vjs-10/playback-engine** - Abstraction layer for media engines (HLS.js, Dash.js, etc.) -- **@vjs-10/media** - HTMLMediaElement contracts and utilities -- **@vjs-10/icons** - SVG icon definitions and utilities +Foundation packages that work in any JavaScript environment. + +| Package | Description | Links | +|---------|-------------|-------| +| **@vjs-10/media-store** | Reactive state management for media players | [README](packages/core/media-store/README.md) | +| **@vjs-10/playback-engine** | Abstraction layer for streaming engines (HLS.js, Dash.js) | [README](packages/core/playback-engine/README.md) | +| **@vjs-10/media** | HTMLMediaElement contracts and utilities | [README](packages/core/media/README.md) | +| **@vjs-10/icons** | SVG icon source library | [README](packages/core/icons/README.md) | +| **@vjs-10/core** | Core UI components (sliders, utilities) | [README](packages/core/core/README.md) | ### HTML/DOM Packages -- **@vjs-10/html-icons** - Web component icon elements -- **@vjs-10/html-media-elements** - Web component media elements -- **@vjs-10/html-media-store** - DOM integration for media store -- **@vjs-10/html** - Complete HTML media player UI library +Web Components and DOM-specific implementations. + +| Package | Description | Links | +|---------|-------------|-------| +| **@vjs-10/html-icons** | Web Component icon elements | [README](packages/html/html-icons/README.md) | +| **@vjs-10/html-media-elements** | Enhanced media element Web Components | [README](packages/html/html-media-elements/README.md) | +| **@vjs-10/html-media-store** | DOM integration for media store | [README](packages/html/html-media-store/README.md) | +| **@vjs-10/html** | **Complete HTML media player library** | [README](packages/html/html/README.md) | ### React Packages -- **@vjs-10/react-icons** - React icon components -- **@vjs-10/react-media-elements** - React media element components -- **@vjs-10/react-media-store** - React hooks and context for media state -- **@vjs-10/react** - Complete React media player UI library +React components, hooks, and integrations. + +| Package | Description | Links | +|---------|-------------|-------| +| **@vjs-10/react-icons** | React icon components | [README](packages/react/react-icons/README.md) | +| **@vjs-10/react-media-elements** | React media element components and hooks | [README](packages/react/react-media-elements/README.md) | +| **@vjs-10/react-media-store** | React hooks and context for media state | [README](packages/react/react-media-store/README.md) | +| **@vjs-10/react** | **Complete React media player library** | [README](packages/react/react/README.md) | ### React Native Packages -- **@vjs-10/react-native-icons** - React Native icon components (requires react-native-svg) -- **@vjs-10/react-native-media-elements** - React Native media components (requires react-native-video) -- **@vjs-10/react-native** - Complete React Native media player UI library +React Native components and integrations (coming soon). + +| Package | Description | +|---------|-------------| +| **@vjs-10/react-native-icons** | React Native icon components (requires react-native-svg) | +| **@vjs-10/react-native-media-elements** | React Native media components (requires react-native-video) | +| **@vjs-10/react-native** | **Complete React Native media player library** | ## Getting Started @@ -144,21 +204,139 @@ pnpm dev:react # React demo pnpm dev:website # Website (docs & blog) ``` -## Package Dependencies +## Architecture & Design Philosophy -The packages are designed with clear dependency relationships: +### Dependency Hierarchy +The monorepo follows a strict dependency hierarchy to ensure modularity and prevent circular dependencies: + +``` +Core Packages (runtime-agnostic) + ↓ +Platform Packages (HTML, React, React Native) + ↓ +Complete UI Libraries +``` + +**Rules:** - **Core packages** have no dependencies on other vjs-10 packages - **HTML packages** depend only on core packages - **React packages** depend only on core packages (peer dependency on React) -- **React Native packages** depend only on core packages (peer dependencies on React Native, react-native-video, react-native-svg) +- **React Native packages** depend only on core packages (peer dependencies on React Native ecosystem) -This ensures maximum reusability and prevents circular dependencies. +This ensures: +- Maximum code reusability across platforms +- Clear separation of concerns +- No circular dependencies +- Tree-shakeable, modular architecture + +### Key Design Decisions + +**State Management** - Built on [nanostores](https://github.com/nanostores/nanostores) for minimal, reactive state that works across all platforms. + +**Streaming Support** - HLS.js integration for adaptive bitrate streaming, with extensible design for DASH.js and other engines. + +**Web Components** - Standards-based custom elements for HTML/DOM implementation, ensuring framework-agnostic usage. + +**TypeScript First** - Full TypeScript support with strict type checking across all packages. + +**Accessibility** - WCAG 2.1 AA compliance with keyboard navigation, ARIA attributes, and screen reader support. ## TypeScript All packages are written in TypeScript and use project references for efficient compilation. The monorepo uses a shared `tsconfig.base.json` for consistent compiler options across all packages. +Key TypeScript features: +- Strict mode enabled with additional checks +- Path mappings for all `@vjs-10/*` packages +- Composite builds for incremental compilation +- Full type definitions included + +## Features + +- ✅ **HLS Streaming** - Built-in support via HLS.js +- ✅ **Web Components** - Standards-based custom elements +- ✅ **React Integration** - Full React component library +- ✅ **State Management** - Reactive state with nanostores +- ✅ **TypeScript** - Complete type definitions +- ✅ **Accessible** - WCAG 2.1 AA compliant +- ✅ **SSR Ready** - Works with Next.js, Remix, etc. +- ✅ **Tree-shakeable** - Modular architecture +- 🚧 **DASH Streaming** - Coming soon +- 🚧 **React Native** - Coming soon +- 🚧 **Vue Components** - Coming soon +- 🚧 **Svelte Components** - Coming soon + +## Contributing + +Contributions are welcome! Please read our [CLAUDE.md](CLAUDE.md) for development guidelines and architecture details. + +### Development Workflow + +1. **Clone the repository** + ```bash + git clone https://github.com/videojs/vjs-10-monorepo.git + cd vjs-10-monorepo + ``` + +2. **Install dependencies** + ```bash + pnpm install + ``` + +3. **Build packages** + ```bash + pnpm build + ``` + +4. **Run development servers** + ```bash + pnpm dev # All demos in parallel + pnpm dev:html # HTML demo only + pnpm dev:react # React demo only + pnpm dev:website # Website only + ``` + +5. **Make your changes** + - Follow [Conventional Commits](https://www.conventionalcommits.org/) for commit messages + - Add tests if applicable + - Update documentation as needed + +6. **Submit a pull request** + +### Commit Message Format + +We use [Conventional Commits](https://www.conventionalcommits.org/): + +``` +[optional scope]: + +[optional body] + +[optional footer(s)] +``` + +**Types:** `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore` + +**Examples:** +- `feat(react): add picture-in-picture component` +- `fix(media-store): correct time sync issue` +- `docs(html): update component API documentation` + +## Getting Help + +- **Documentation** - [Website](https://videojs.github.io/vjs-10-monorepo/) (coming soon) +- **GitHub Discussions** - [v10 Discussion](https://github.com/videojs/video.js/discussions/9035) +- **Issues** - [Report bugs or request features](https://github.com/videojs/vjs-10-monorepo/issues) + +## Related Projects + +- [Video.js](https://github.com/videojs/video.js) - Video.js 8.x (current stable) +- [HLS.js](https://github.com/video-dev/hls.js) - HLS streaming library +- [nanostores](https://github.com/nanostores/nanostores) - State management + ## License Apache-2.0 + +Copyright (c) Video.js Contributors diff --git a/eslint.config.mjs b/eslint.config.mjs index 97b5edb5..09fcb870 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -47,4 +47,32 @@ export default antfu( 'style/max-len': 'off', }, }, + { + files: ['**/*.md/**'], + rules: { + // Disable rules that conflict with documentation code examples in markdown + 'ts/no-unsafe-function-type': 'off', + 'ts/method-signature-style': 'off', + 'node/handle-callback-err': 'off', + 'react-refresh/only-export-components': 'off', + 'react-dom/no-missing-button-type': 'off', + 'react/no-array-index-key': 'off', + 'react-hooks/rules-of-hooks': 'off', + 'jsx-a11y/click-events-have-key-events': 'off', + 'jsx-a11y/interactive-supports-focus': 'off', + 'jsx-a11y/no-noninteractive-element-interactions': 'off', + 'unused-imports/no-unused-vars': 'off', + 'no-undef': 'off', + 'no-unused-vars': 'off', + 'import/first': 'off', + 'import/newline-after-import': 'off', + 'unicorn/prefer-node-protocol': 'off', + 'format/prettier': 'off', + 'perfectionist/sort-named-imports': 'off', + 'style/quotes': 'off', + 'style/semi': 'off', + 'style/member-delimiter-style': 'off', + 'style/jsx-one-expression-per-line': 'off', + }, + }, ); diff --git a/packages/core/core/README.md b/packages/core/core/README.md new file mode 100644 index 00000000..ee5d0d83 --- /dev/null +++ b/packages/core/core/README.md @@ -0,0 +1,286 @@ +# @vjs-10/core + +> Core components and utilities for Video.js + +[![npm](https://img.shields.io/badge/npm-%40vjs--10%2Fcore-blue)](https://www.npmjs.com/package/@vjs-10/core) + +**Status:** Early Development + +> **⚠️ PROTOTYPE - SUBJECT TO CHANGE** +> +> This package is in early prototype phase. Expect significant changes including: +> +> - Package restructuring and naming +> - Breaking API changes +> - Major architectural updates +> - Incomplete or experimental features +> +> Not recommended for production use. + +## Overview + +`@vjs-10/core` provides runtime-agnostic core components and utilities shared across Video.js packages. These are foundational building blocks used by platform-specific implementations (HTML, React, React Native) to create consistent media player experiences. + +## Key Features + +- **Core UI Components** - Platform-agnostic slider components +- **Shared Utilities** - Common helpers for time ranges, formatting, etc. +- **State Management** - Built on nanostores for reactive state +- **Runtime Agnostic** - Works in any JavaScript environment +- **Type Safe** - Full TypeScript support + +## Installation + +```bash +npm install @vjs-10/core +``` + +## Components + +### TimeSlider + +A time range slider component for seeking through media. + +```typescript +import { TimeSlider } from '@vjs-10/core'; + +// Create time slider state +const slider = new TimeSlider({ + min: 0, + max: 100, + value: 50, + step: 0.1, +}); + +// Subscribe to value changes +slider.value.subscribe((currentValue) => { + console.log('Slider value:', currentValue); +}); + +// Update value +slider.setValue(75); + +// Get current state +const state = slider.getState(); +console.log(state); // { min, max, value, step, percentage } +``` + +### VolumeSlider + +A volume slider component for audio level control. + +```typescript +import { VolumeSlider } from '@vjs-10/core'; + +// Create volume slider state +const volumeSlider = new VolumeSlider({ + min: 0, + max: 1, + value: 0.8, + step: 0.01, +}); + +// Subscribe to volume changes +volumeSlider.value.subscribe((volume) => { + console.log('Volume level:', volume); +}); + +// Mute/unmute handling +volumeSlider.setValue(0); // Mute +volumeSlider.setValue(0.8); // Restore volume +``` + +## Slider API + +Both `TimeSlider` and `VolumeSlider` share a common API: + +### Constructor Options + +```typescript +interface SliderOptions { + min?: number; // Minimum value (default: 0) + max?: number; // Maximum value (default: 100) + value?: number; // Initial value (default: 0) + step?: number; // Step increment (default: 1) +} +``` + +### Methods + +```typescript +interface SliderMethods { + // Set slider value + setValue(newValue: number): void + + // Get current value + getValue(): number + + // Get complete slider state + getState(): SliderState + + // Reset to initial value + reset(): void + + // Destroy slider instance + destroy(): void +} +``` + +### State Properties + +```typescript +interface SliderState { + min: number; // Minimum value + max: number; // Maximum value + value: number; // Current value + step: number; // Step increment + percentage: number; // Value as percentage (0-100) +} + +// Access state atoms directly +slider.value.get(); // Current value +slider.percentage.get(); // Percentage representation +``` + +### Reactive Subscriptions + +```typescript +// Subscribe to value changes +const unsubscribe = slider.value.subscribe((value) => { + console.log('Value changed:', value); +}); + +// Subscribe to percentage changes +slider.percentage.subscribe((pct) => { + console.log('Percentage:', pct); +}); + +// Clean up subscription +unsubscribe(); +``` + +## Use Cases + +### Media Progress Bar + +```typescript +import { TimeSlider } from '@vjs-10/core'; + +const progressBar = new TimeSlider({ + min: 0, + max: videoDuration, + value: 0, + step: 0.1, +}); + +// Update as video plays +videoElement.ontimeupdate = () => { + progressBar.setValue(videoElement.currentTime); +}; + +// Seek when user drags slider +progressBar.value.subscribe((time) => { + if (userIsDragging) { + videoElement.currentTime = time; + } +}); +``` + +### Volume Control + +```typescript +import { VolumeSlider } from '@vjs-10/core'; + +const volumeControl = new VolumeSlider({ + min: 0, + max: 1, + value: 0.8, + step: 0.01, +}); + +// Sync with media element +volumeControl.value.subscribe((volume) => { + videoElement.volume = volume; +}); + +// Keyboard shortcuts +document.addEventListener('keydown', (e) => { + if (e.key === 'ArrowUp') { + const current = volumeControl.getValue(); + volumeControl.setValue(Math.min(1, current + 0.1)); + } +}); +``` + +## Architecture + +This package provides the **logical core** that platform implementations build upon: + +``` +@vjs-10/core (logic/state) + ↓ + ├─→ @vjs-10/html (DOM implementation) + ├─→ @vjs-10/react (React implementation) + └─→ @vjs-10/react-native (React Native implementation) +``` + +Platform packages add: + +- UI rendering (DOM elements, React components, etc.) +- Event handling (mouse, touch, keyboard) +- Styling and theming +- Accessibility features + +## Utilities + +### Time Range Utilities + +```typescript +import { formatTimeRange, parseTimeRange } from '@vjs-10/core'; + +// Format time ranges for display +formatTimeRange(0, 100); // "0:00 - 1:40" + +// Parse time range strings +parseTimeRange('0:00 - 1:40'); // { start: 0, end: 100 } +``` + +## Package Dependencies + +- **Dependencies:** `nanostores` (for reactive state) +- **Used by:** `@vjs-10/html`, `@vjs-10/react`, platform UI packages + +## Development + +```bash +# Build the package +pnpm build + +# Watch mode for development +pnpm dev + +# Run tests +pnpm test + +# Clean build artifacts +pnpm clean +``` + +## Related Packages + +- **[@vjs-10/media-store](../media-store)** - Media state management +- **[@vjs-10/html](../../../html/html)** - HTML/DOM implementation +- **[@vjs-10/react](../../../react/react)** - React implementation + +## Design Philosophy + +Core components follow these principles: + +- **Logic over presentation** - Focus on behavior, not rendering +- **Reactive state** - Leverage nanostores for efficiency +- **Platform agnostic** - No DOM or React dependencies +- **Composable** - Build complex UIs from simple primitives + +## License + +Apache-2.0 diff --git a/packages/core/icons/README.md b/packages/core/icons/README.md new file mode 100644 index 00000000..f47d70c9 --- /dev/null +++ b/packages/core/icons/README.md @@ -0,0 +1,234 @@ +# @vjs-10/icons + +> SVG icon library for Video.js media players + +[![npm](https://img.shields.io/badge/npm-%40vjs--10%2Fmedia--store-blue)](https://www.npmjs.com/package/@vjs-10/icons) + +**Status:** Early Development + +> **⚠️ PROTOTYPE - SUBJECT TO CHANGE** +> +> This package is in early prototype phase. Expect significant changes including: +> +> - Package restructuring and naming +> - Breaking API changes +> - Major architectural updates +> - Incomplete or experimental features +> +> Not recommended for production use. + +## Overview + +`@vjs-10/icons` is a curated collection of SVG icons designed specifically for media player interfaces. This package serves as the single source of truth for all Video.js icons, providing raw SVG assets that platform-specific packages transform into their respective component formats. + +## Key Features + +- **Curated Media Icons** - Comprehensive set of media player interface icons +- **SVG Source Files** - Raw SVG assets optimized for transformation +- **Platform Agnostic** - Icons serve as source for HTML, React, React Native implementations +- **Optimized Assets** - Clean, minimal SVG markup +- **Consistent Design** - Cohesive visual language across all icons + +## Installation + +```bash +npm install @vjs-10/icons +``` + +## Icon Catalog + +### Playback Controls + +- `play.svg` - Play button +- `pause.svg` - Pause button +- `replay.svg` - Replay/restart button +- `forward.svg` - Skip forward +- `backward.svg` - Skip backward + +### Volume Controls + +- `volume-high.svg` - High volume indicator +- `volume-medium.svg` - Medium volume indicator +- `volume-low.svg` - Low volume indicator +- `volume-off.svg` / `mute.svg` - Muted state + +### Playback Features + +- `fullscreen.svg` - Enter fullscreen +- `fullscreen-exit.svg` - Exit fullscreen +- `settings.svg` - Settings menu +- `captions.svg` - Closed captions +- `picture-in-picture.svg` - PiP mode + +### Additional Controls + +- `airplay.svg` - AirPlay casting +- `chromecast.svg` - Chromecast +- `download.svg` - Download media +- `share.svg` - Share functionality + +## Usage + +This package is typically used as a dependency by platform-specific icon packages rather than directly by applications. + +### Direct SVG Access + +```typescript +import { getIconPath } from '@vjs-10/icons'; + +// Get path to SVG file +const playIconPath = getIconPath('play'); + +// In Node.js or build tools +import { readFileSync } from 'fs'; +const playSvg = readFileSync(playIconPath, 'utf-8'); +``` + +### With Platform Packages + +**For Web Components:** + +```bash +npm install @vjs-10/html-icons +``` + +**For React:** + +```bash +npm install @vjs-10/react-icons +``` + +**For React Native:** + +```bash +npm install @vjs-10/react-native-icons +``` + +## Icon Format Standards + +All icons in this package follow these guidelines: + +- **Format:** SVG 1.1 +- **Viewbox:** `0 0 24 24` (standardized 24×24 grid) +- **Stroke:** None (filled icons) +- **Color:** `currentColor` (inherits from context) +- **Optimization:** Minified, cleaned paths +- **Accessibility:** Semantic, descriptive file names + +## Architecture + +``` +@vjs-10/icons (source SVGs) + ↓ + ├─→ @vjs-10/html-icons (Web Components) + ├─→ @vjs-10/react-icons (React Components) + └─→ @vjs-10/react-native-icons (React Native Components) +``` + +This package serves as: + +- **Single source of truth** for all icon designs +- **Asset library** consumed by platform-specific generators +- **Design system foundation** ensuring visual consistency + +## Adding New Icons + +1. **Design Requirements:** + - 24×24 viewBox + - Single color (will be replaced with `currentColor`) + - Minimal, clean paths + - Optimized file size + +2. **File Naming:** + - Use kebab-case: `volume-high.svg` + - Descriptive, clear names + - Avoid abbreviations + +3. **Process:** + + ```bash + # Add SVG to assets directory + cp new-icon.svg packages/core/icons/assets/ + + # Regenerate platform packages + cd packages/react/react-icons + pnpm generate + + cd packages/html/html-icons + pnpm generate + ``` + +## Development + +```bash +# Build the package +pnpm build + +# Watch mode for development +pnpm dev + +# Clean build artifacts +pnpm clean +``` + +## Package Dependencies + +- **Dependencies:** None (pure SVG assets) +- **Used by:** `@vjs-10/html-icons`, `@vjs-10/react-icons`, `@vjs-10/react-native-icons` + +## Platform Integration + +### HTML Icons + +Generates Web Component icon elements from SVG sources. + +```bash +npm install @vjs-10/html-icons +``` + +### React Icons + +Generates React components with SVGR from SVG sources. + +```bash +npm install @vjs-10/react-icons +``` + +See **[@vjs-10/react-icons](../../../react/react-icons)** for detailed usage. + +### React Native Icons + +Generates React Native SVG components from SVG sources. + +```bash +npm install @vjs-10/react-native-icons +``` + +## Design Philosophy + +Icons follow Video.js design principles: + +- **Clarity** - Instantly recognizable at small sizes +- **Consistency** - Uniform stroke weight and visual density +- **Accessibility** - Clear, distinguishable shapes +- **Simplicity** - Minimal visual noise + +## Related Packages + +- **[@vjs-10/html-icons](../../../html/html-icons)** - Web Component implementation +- **[@vjs-10/react-icons](../../../react/react-icons)** - React component implementation +- **[@vjs-10/core](../core)** - Core Video.js components + +## Contributing + +When contributing new icons: + +1. Follow the design guidelines above +2. Optimize SVGs (remove unnecessary metadata) +3. Test icon clarity at 16×16, 24×24, and 32×32 sizes +4. Ensure `currentColor` is used for fill/stroke +5. Provide context in PR description + +## License + +Apache-2.0 diff --git a/packages/core/media-store/README.md b/packages/core/media-store/README.md new file mode 100644 index 00000000..8d5efd43 --- /dev/null +++ b/packages/core/media-store/README.md @@ -0,0 +1,205 @@ +# @vjs-10/media-store + +> Runtime-agnostic state management for media players + +[![npm](https://img.shields.io/badge/npm-%40vjs--10%2Fmedia--store-blue)](https://www.npmjs.com/package/@vjs-10/media-store) + +**Status:** Early Development + +> **⚠️ PROTOTYPE - SUBJECT TO CHANGE** +> +> This package is in early prototype phase. Expect significant changes including: +> +> - Package restructuring and naming +> - Breaking API changes +> - Major architectural updates +> - Incomplete or experimental features +> +> Not recommended for production use. + +## Overview + +`@vjs-10/media-store` provides a lightweight, reactive state management system for media players built on [nanostores](https://github.com/nanostores/nanostores). It's designed to be runtime-agnostic, making it suitable for use across web, React, React Native, and other JavaScript environments. + +## Key Features + +- **Runtime Agnostic** - Works in any JavaScript environment +- **Reactive State** - Built on nanostores for efficient reactivity +- **Component State Definitions** - Pre-built state models for common UI components +- **State Mediators** - Coordinated state management for playable, audible, and temporal concerns +- **Time Utilities** - Format and parse media time values +- **Type Safe** - Full TypeScript support + +## Installation + +```bash +npm install @vjs-10/media-store +``` + +## Quick Start + +```typescript +import { createMediaStore } from '@vjs-10/media-store'; + +// Create a media store instance +const store = createMediaStore(); + +// Subscribe to state changes +store.paused.subscribe((paused) => { + console.log('Player paused:', paused); +}); + +// Update state +store.paused.set(false); // Start playing +``` + +## Core Concepts + +### Media Store + +The central store manages all media-related state: + +```typescript +import { createMediaStore } from '@vjs-10/media-store'; + +const store = createMediaStore(); + +// Access individual state atoms +store.currentTime.set(30); // Seek to 30 seconds +store.volume.set(0.5); // Set volume to 50% +store.muted.set(true); // Mute audio +``` + +### Component State Definitions + +Pre-configured state models for common media UI components: + +```typescript +import { + createPlayButtonState, + createMuteButtonState, + createTimeSliderState, + createVolumeSliderState, +} from '@vjs-10/media-store'; + +// Create component-specific state +const playButtonState = createPlayButtonState(store); +const muteButtonState = createMuteButtonState(store); +const timeSliderState = createTimeSliderState(store); +const volumeSliderState = createVolumeSliderState(store); +``` + +Available component state definitions: + +- `createPlayButtonState` - Play/pause button state +- `createMuteButtonState` - Mute/unmute button state +- `createFullscreenButtonState` - Fullscreen toggle state +- `createTimeSliderState` - Progress/seek bar state +- `createVolumeSliderState` - Volume control state +- `createCurrentTimeDisplayState` - Current time display state +- `createDurationDisplayState` - Duration display state +- `createPreviewTimeDisplayState` - Preview time on hover state + +### State Mediators + +Coordinate related state changes: + +```typescript +import { + createPlayableMediator, + createAudibleMediator, + createTemporalMediator, +} from '@vjs-10/media-store'; + +// Playable mediator - manages play/pause/ended states +const playableMediator = createPlayableMediator(store, mediaElement); + +// Audible mediator - manages volume/muted states +const audibleMediator = createAudibleMediator(store, mediaElement); + +// Temporal mediator - manages time-related states +const temporalMediator = createTemporalMediator(store, mediaElement); +``` + +### Time Utilities + +Format and parse time values: + +```typescript +import { formatTime, parseTime } from '@vjs-10/media-store'; + +// Format seconds to HH:MM:SS or MM:SS +formatTime(90); // "1:30" +formatTime(3661); // "1:01:01" + +// Parse time string to seconds +parseTime("1:30"); // 90 +parseTime("1:01:01"); // 3661 +``` + +## Architecture + +This package is part of the Video.js 10 monorepo and follows the core package philosophy: + +- **No platform dependencies** - Pure JavaScript/TypeScript +- **Foundation for other packages** - Used by `@vjs-10/html-media-store`, `@vjs-10/react-media-store`, etc. +- **Nanostores-based** - Leverages the excellent nanostores library for minimal, fast reactivity + +## Package Dependencies + +- **Dependencies:** `nanostores` (for reactive state) +- **Used by:** `@vjs-10/html-media-store`, `@vjs-10/react-media-store`, platform-specific integrations + +## Development + +```bash +# Build the package +pnpm build + +# Watch mode for development +pnpm dev + +# Run tests +pnpm test + +# Clean build artifacts +pnpm clean +``` + +## API Overview + +### Store Creation + +- `createMediaStore()` - Creates a new media store instance + +### Component State Definitions + +- `createPlayButtonState(store)` - Play/pause button state +- `createMuteButtonState(store)` - Mute button state +- `createFullscreenButtonState(store)` - Fullscreen button state +- `createTimeSliderState(store)` - Time slider state +- `createVolumeSliderState(store)` - Volume slider state +- `createCurrentTimeDisplayState(store)` - Current time display state +- `createDurationDisplayState(store)` - Duration display state +- `createPreviewTimeDisplayState(store)` - Preview time display state + +### State Mediators + +- `createPlayableMediator(store, element)` - Manages playback state +- `createAudibleMediator(store, element)` - Manages audio state +- `createTemporalMediator(store, element)` - Manages time-based state + +### Utilities + +- `formatTime(seconds)` - Format seconds to time string +- `parseTime(timeString)` - Parse time string to seconds + +## Related Packages + +- **[@vjs-10/html-media-store](../../../html/html-media-store)** - HTML/DOM integration +- **[@vjs-10/react-media-store](../../../react/react-media-store)** - React hooks and context +- **[@vjs-10/core](../core)** - Shared core components + +## License + +Apache-2.0 diff --git a/packages/core/media/README.md b/packages/core/media/README.md new file mode 100644 index 00000000..1e3f2210 --- /dev/null +++ b/packages/core/media/README.md @@ -0,0 +1,293 @@ +# @vjs-10/media + +> HTMLMediaElement contracts, utilities, and playback engine integration + +[![npm](https://img.shields.io/badge/npm-%40vjs--10%2Fmedia-blue)](https://www.npmjs.com/package/@vjs-10/media) + +**Status:** Early Development + +> **⚠️ PROTOTYPE - SUBJECT TO CHANGE** +> +> This package is in early prototype phase. Expect significant changes including: +> +> - Package restructuring and naming +> - Breaking API changes +> - Major architectural updates +> - Incomplete or experimental features +> +> Not recommended for production use. + +## Overview + +`@vjs-10/media` provides contracts, utilities, and integration helpers for working with HTMLMediaElement and playback engines. It bridges the gap between native media elements and advanced streaming capabilities, offering a consistent interface for media playback across different scenarios. + +## Key Features + +- **HTMLMediaElement Contracts** - TypeScript interfaces and types for media elements +- **Playback Engine Integration** - Seamless integration with `@vjs-10/playback-engine` +- **Media Utilities** - Helper functions for common media operations +- **Source Management** - Intelligent media source loading and switching +- **Runtime Agnostic** - Works in any JavaScript environment +- **Type Safe** - Full TypeScript support + +## Installation + +```bash +npm install @vjs-10/media +``` + +## Quick Start + +### Basic Media Setup + +```typescript +import { setupMedia } from '@vjs-10/media'; + +const videoElement = document.querySelector('video'); + +// Setup media element with automatic engine selection +const mediaController = setupMedia(videoElement, { + src: 'https://example.com/video.mp4', + autoplay: false, + preload: 'metadata', +}); + +// Load source +mediaController.load(); + +// Clean up +mediaController.destroy(); +``` + +### With HLS Streaming + +```typescript +import { setupMedia } from '@vjs-10/media'; + +const videoElement = document.querySelector('video'); + +// HLS source automatically uses HlsJSPlaybackEngine +const mediaController = setupMedia(videoElement, { + src: 'https://example.com/stream.m3u8', +}); + +mediaController.load(); +``` + +### Source Switching + +```typescript +import { setupMedia } from '@vjs-10/media'; + +const mediaController = setupMedia(videoElement, { + src: 'https://example.com/video1.mp4', +}); + +// Switch to different source +mediaController.setSrc('https://example.com/video2.mp4'); + +// Switch to HLS stream +mediaController.setSrc('https://example.com/stream.m3u8'); +``` + +## Core Concepts + +### Media Contracts + +TypeScript interfaces for media element properties and behavior: + +```typescript +import type { MediaElement, MediaSource, MediaState } from '@vjs-10/media'; + +// MediaElement - Extended HTMLMediaElement interface +const element: MediaElement = videoElement; + +// MediaSource - Source configuration +const source: MediaSource = { + src: 'https://example.com/video.mp4', + type: 'video/mp4', +}; + +// MediaState - Represents media playback state +const state: MediaState = { + currentTime: 0, + duration: 0, + paused: true, + volume: 1, + muted: false, +}; +``` + +### Engine Integration + +Automatic playback engine selection based on source type: + +```typescript +import { setupMedia } from '@vjs-10/media'; + +// Native playback for standard formats +setupMedia(videoElement, { src: 'video.mp4' }); + +// Automatic HLS engine for .m3u8 +setupMedia(videoElement, { src: 'stream.m3u8' }); + +// Explicit engine selection +setupMedia(videoElement, { + src: 'stream.m3u8', + engine: 'hls', // or 'native', 'dash', etc. +}); +``` + +### Media Controller + +The media controller provides a unified API: + +```typescript +const controller = setupMedia(videoElement, options); + +// Lifecycle +controller.load(); // Load the source +controller.destroy(); // Clean up resources + +// Source management +controller.setSrc(newSrc); // Switch source +controller.getSrc(); // Get current source + +// Events +controller.on('ready', () => {}); +controller.on('error', (error) => {}); +controller.on('sourcechange', (src) => {}); +``` + +## API Overview + +### Functions + +```typescript +// Setup media element with configuration +function setupMedia( + element: HTMLMediaElement, + options: MediaOptions +): MediaController + +// Detect media type from URL +function detectMediaType(src: string): 'hls' | 'dash' | 'native' + +// Check if source requires playback engine +function requiresEngine(src: string): boolean +``` + +### Types + +```typescript +interface MediaOptions { + src: string; + type?: string; + engine?: 'auto' | 'native' | 'hls' | 'dash'; + autoplay?: boolean; + preload?: 'none' | 'metadata' | 'auto'; + crossOrigin?: 'anonymous' | 'use-credentials'; +} + +interface MediaController { + load: () => void; + destroy: () => void; + setSrc: (src: string) => void; + getSrc: () => string; + on: (event: string, handler: Function) => void; + off: (event: string, handler: Function) => void; +} +``` + +## Use Cases + +### Progressive vs. Adaptive Streaming + +```typescript +import { detectMediaType, setupMedia } from '@vjs-10/media'; + +const src = getUserSelectedSource(); +const type = detectMediaType(src); + +if (type === 'hls') { + console.log('Using adaptive streaming'); +} else { + console.log('Using progressive download'); +} + +const controller = setupMedia(videoElement, { src }); +``` + +### Multi-Quality Source Selection + +```typescript +import { setupMedia } from '@vjs-10/media'; + +const sources = [ + { src: 'video-4k.mp4', quality: '4K' }, + { src: 'video-1080p.mp4', quality: '1080p' }, + { src: 'video-720p.mp4', quality: '720p' }, +]; + +const selectedSource = selectSourceByQuality(sources, userPreference); +const controller = setupMedia(videoElement, selectedSource); +``` + +### Error Recovery + +```typescript +const controller = setupMedia(videoElement, { src: primarySource }); + +controller.on('error', (error) => { + console.error('Playback error:', error); + + // Fallback to alternate source + controller.setSrc(fallbackSource); + controller.load(); +}); +``` + +## Architecture + +This package serves as the bridge between: + +- **Native media elements** (`