chore(claude): add skills system (#310)

This commit is contained in:
rahim
2026-01-19 19:57:01 +11:00
committed by GitHub
parent 17ed67a1f7
commit 8015c30210
72 changed files with 15076 additions and 1133 deletions
@@ -0,0 +1,332 @@
# AI/Agent Readiness Pattern
How to make documentation consumable by AI assistants and coding agents.
## llms.txt
Provide documentation in a single, AI-optimized file.
### Structure
```markdown
# Video.js 10
> A framework-agnostic media player library.
## Quick Start
npm install @videojs/core
import { createPlayer } from '@videojs/core';
const player = createPlayer({ src: 'video.mp4' });
## Core Concepts
- [State Management](/docs/concepts/state.md)
- [Requests](/docs/concepts/requests.md)
- [Events](/docs/concepts/events.md)
## API Reference
- [createPlayer](/docs/api/create-player.md)
- [Player](/docs/api/player.md)
## Adapters
- [React](/docs/adapters/react.md)
- [Vue](/docs/adapters/vue.md)
- [Svelte](/docs/adapters/svelte.md)
```
### Sizes
Provide multiple versions for different context windows:
| File | Size | Content |
|------|------|---------|
| `llms.txt` | ~10k tokens | Overview + links |
| `llms-small.txt` | ~5k tokens | Quick ref only |
| `llms-full.txt` | ~50k tokens | Complete docs |
### URL Pattern
```
https://videojs.com/llms.txt
https://videojs.com/llms-small.txt
https://videojs.com/llms-full.txt
https://videojs.com/docs/api/player.md # Direct markdown
```
## AGENTS.md
Include in package root for AI coding agents.
```markdown
# AGENTS.md
## Project
Video.js 10 - Framework-agnostic media player.
## Structure
packages/
├── core/ # Framework-agnostic logic
├── dom/ # Vanilla JS components
├── react/ # React adapter
├── vue/ # Vue adapter
├── svelte/ # Svelte adapter
└── solid/ # Solid adapter
## Commands
# Install dependencies
pnpm install
# Build all packages
pnpm build
# Run tests
pnpm test
# Lint
pnpm lint
# Type check
pnpm typecheck
## Code Style
- TypeScript strict mode
- Prefer `const` over `let`
- Use named exports
- Document public APIs with TSDoc
- Test files: `*.test.ts`
## Key Files
- `packages/core/src/player.ts` — Main player class
- `packages/core/src/state.ts` — State management
- `packages/core/src/request.ts` — Request system
## Testing
# Run all tests
pnpm test
# Run specific package
pnpm --filter @videojs/core test
# Watch mode
pnpm test --watch
```
## TSDoc/JSDoc
Document all public exports:
```ts
/**
* Creates a new player instance.
*
* @param options - Configuration options
* @returns A new Player instance
*
* @example
* ```ts
* import { createPlayer } from '@videojs/core';
*
* const player = createPlayer({
* src: 'video.mp4',
* autoplay: true,
* });
* ```
*
* @remarks
* The player must be attached to a media element before playback.
* Use {@link Player.attach} to connect to an element.
*
* @see {@link PlayerOptions} for all configuration options
* @see {@link Player} for the returned instance type
*/
export function createPlayer(options: PlayerOptions): Player {
// ...
}
```
### Required Tags
| Tag | Usage |
|-----|-------|
| `@param` | Every parameter |
| `@returns` | Non-void return |
| `@example` | At least one |
| `@throws` | If can throw |
| `@see` | Related items |
### Optional Tags
| Tag | Usage |
|-----|-------|
| `@remarks` | Implementation details |
| `@defaultValue` | Default values |
| `@deprecated` | Deprecation notice |
| `@since` | Version introduced |
| `@beta` / `@alpha` | Stability |
## Self-Contained Examples
AI agents need examples that work without external context:
```ts
// ❌ Bad — requires context
player.play();
// ✅ Good — self-contained
import { createPlayer } from '@videojs/core';
const video = document.querySelector('video');
const player = createPlayer({ src: 'video.mp4' });
await player.attach(video);
await player.play();
```
### Include All Imports
```ts
// ❌ Assumes imports exist
const player = createPlayer(options);
// ✅ Shows exactly what to import
import { createPlayer } from '@videojs/core';
import type { PlayerOptions } from '@videojs/core';
const options: PlayerOptions = { src: 'video.mp4' };
const player = createPlayer(options);
```
### Show Expected Output
```ts
console.log(player.state);
// Output:
// {
// currentTime: 0,
// duration: 120,
// paused: true,
// volume: 1,
// muted: false,
// }
```
### Include Error Cases
```ts
try {
await player.play();
} catch (error) {
// Error: NotAllowedError - Autoplay blocked by browser
}
```
## Markdown Export
Every documentation page should be available as raw markdown:
```markdown
## Viewing as Markdown
This page is available in markdown format:
[View as Markdown](/docs/api/player.md)
```
Or automatic via URL suffix:
```
/docs/api/player → HTML page
/docs/api/player.md → Raw markdown
```
## Context Window Optimization
Write docs that work within token limits:
### Chunk by Concept
```markdown
<!-- Good: One concept per section -->
## State
The player state is a readonly object...
## Requests
Requests are used to change state...
```
### Avoid Redundancy
```markdown
<!-- Bad: Repeats information -->
The `play()` method plays the video. When you call `play()`,
the video will start playing.
<!-- Good: Concise -->
`play()` starts playback.
```
### Front-Load Important Info
```markdown
<!-- Good: Key info first -->
## createPlayer
Creates a player instance. Returns `Player`.
const player = createPlayer({ src: 'video.mp4' });
### Options
...
```
## MCP Server
For advanced integration, provide an MCP server:
```json
{
"name": "videojs-docs",
"version": "1.0.0",
"tools": [
{
"name": "search_docs",
"description": "Search Video.js documentation",
"parameters": {
"query": { "type": "string" }
}
},
{
"name": "get_api",
"description": "Get API reference for a symbol",
"parameters": {
"symbol": { "type": "string" }
}
}
]
}
```
## Testing AI Readability
Checklist for AI-friendly docs:
- [ ] llms.txt at docs root
- [ ] AGENTS.md in package root
- [ ] All exports have TSDoc
- [ ] Examples include imports
- [ ] Examples are runnable
- [ ] Pages available as markdown
- [ ] No broken internal links
- [ ] Code blocks have language tags
- [ ] Types are documented or inferrable
@@ -0,0 +1,343 @@
# Code Examples Pattern
How to write effective code examples for documentation.
## Core Principles
1. **Self-contained** — include all imports
2. **Copy-paste ready** — works immediately
3. **TypeScript-first** — show types, leverage inference
4. **Minimal** — only what's needed to demonstrate the concept
5. **Real** — use realistic values, not `foo`/`bar`
## Self-Contained Examples
```tsx
// ❌ Missing imports — won't work when copied
function App() {
const player = usePlayer();
return <Player src="video.mp4" />;
}
// ✅ Complete — copy, paste, run
import { Player, usePlayer } from '@videojs/react';
function App() {
const player = usePlayer();
return <Player src="video.mp4" />;
}
```
## TypeScript Best Practices
### Show Type Inference
```ts
// ✅ Let inference work — cleaner
const player = createPlayer({
src: 'video.mp4',
autoplay: true,
});
// player is inferred as Player
// ❌ Redundant annotation
const player: Player = createPlayer({
src: 'video.mp4',
autoplay: true,
});
```
### Annotate When Helpful
```ts
// ✅ Annotation clarifies complex return
function usePlayerState(): {
state: PlayerState;
request: RequestAPI;
} {
// ...
}
// ✅ Annotation shows expected shape
const options: PlayerOptions = {
src: 'video.mp4',
tracks: [
{ kind: 'subtitles', src: 'en.vtt', label: 'English' },
],
};
```
### Show Type Imports
```ts
// ✅ Show type imports for complex types
import type { PlayerOptions, TextTrack } from '@videojs/core';
const tracks: TextTrack[] = [
{ kind: 'subtitles', src: 'en.vtt', label: 'English' },
];
```
## Framework Tabs
Use tabs for multi-framework examples:
````markdown
<Tabs>
<Tab label="React">
```tsx
import { Player } from '@videojs/react';
function App() {
return <Player src="video.mp4" />;
}
```
</Tab>
<Tab label="Vue">
```vue
<script setup>
import { Player } from '@videojs/vue';
</script>
<template>
<Player src="video.mp4" />
</template>
```
</Tab>
<Tab label="Svelte">
```svelte
<script>
import { Player } from '@videojs/svelte';
</script>
<Player src="video.mp4" />
```
</Tab>
<Tab label="Vanilla">
```ts
import { createPlayer } from '@videojs/core';
const player = createPlayer({
target: document.getElementById('player'),
src: 'video.mp4',
});
```
</Tab>
</Tabs>
````
## Progressive Examples
Start simple, add complexity:
```markdown
## Basic Usage
const player = createPlayer({ src: 'video.mp4' });
## With Options
const player = createPlayer({
src: 'video.mp4',
autoplay: true,
muted: true,
});
## With Event Handling
const player = createPlayer({
src: 'video.mp4',
onPlay: () => console.log('Playing'),
onError: (e) => console.error(e),
});
## Full Configuration
const player = createPlayer({
src: 'video.mp4',
autoplay: true,
muted: true,
loop: false,
preload: 'metadata',
tracks: [
{ kind: 'subtitles', src: 'en.vtt', label: 'English', default: true },
],
onPlay: () => analytics.track('video_play'),
onError: (e) => errorReporter.capture(e),
});
```
## Highlight Key Lines
Use comments to draw attention:
```ts
const player = createPlayer({
src: 'video.mp4',
// highlight-next-line
autoplay: true, // ← Starts playing automatically
});
```
Or diff-style:
```ts
const player = createPlayer({
src: 'video.mp4',
- autoplay: false,
+ autoplay: true,
});
```
## Show Output
Include expected output as comments:
```ts
console.log(player.state.currentTime);
// => 0
await player.request.seek(30);
console.log(player.state.currentTime);
// => 30
```
## Error Examples
Show what errors look like:
```ts
// This will throw:
player.play();
// => Error: Player not attached to media element
// Do this instead:
await player.attach(videoElement);
player.play();
```
## Interactive Examples
Link to StackBlitz/CodeSandbox:
```markdown
```tsx
import { Player } from '@videojs/react';
function App() {
return <Player src="video.mp4" />;
}
```
[Open in StackBlitz →](https://stackblitz.com/edit/videojs-react-basic)
```
## Copy Buttons
All code blocks should have copy functionality. In MDX:
```mdx
<CodeBlock copy>
const player = createPlayer({ src: 'video.mp4' });
</CodeBlock>
```
## Filename Headers
Show which file the code belongs to:
````markdown
```tsx title="App.tsx"
import { Player } from '@videojs/react';
export function App() {
return <Player src="video.mp4" />;
}
```
```css title="player.css"
.player {
--player-accent-color: #3b82f6;
}
```
````
## Do/Don't Examples
Show contrast:
```markdown
### Event Handling
// ❌ Don't — inline handlers get recreated
<Player
onTimeUpdate={(t) => setTime(t)}
/>
// ✅ Do — stable callback reference
const handleTimeUpdate = useCallback((t) => setTime(t), []);
<Player onTimeUpdate={handleTimeUpdate} />
```
## Realistic Values
```ts
// ❌ Meaningless
const foo = createBar({ baz: 'qux' });
// ✅ Realistic
const player = createPlayer({
src: 'https://example.com/video.mp4',
poster: 'https://example.com/poster.jpg',
});
```
## Console Examples
For CLI documentation:
```bash
# Install the package
npm install @videojs/core
# Or with other package managers
pnpm add @videojs/core
yarn add @videojs/core
```
## API Response Examples
For async operations:
```ts
const result = await player.request.play();
// => { success: true, state: 'playing' }
const error = await player.request.play();
// => { success: false, error: { code: 'NOT_ALLOWED', message: '...' } }
```
## Configuration Comparison
Show equivalent configs:
```markdown
### JavaScript
const player = createPlayer({
src: 'video.mp4',
autoplay: true,
});
### HTML Data Attributes
<video
data-player
data-src="video.mp4"
data-autoplay
></video>
### React Props
<Player src="video.mp4" autoplay />
```
+274
View File
@@ -0,0 +1,274 @@
# Error Documentation Pattern
Document store errors consistently across Video.js packages.
---
## Error Code Reference Table
Always document errors in this format:
| Code | Meaning | Recovery |
| ------------ | ------------------------------------------- | ---------------------------------------------- |
| `ABORTED` | Request aborted via signal | Expected during cleanup — no action needed |
| `CANCELLED` | Cancelled by another request's `cancel: []` | Check request coordination |
| `SUPERSEDED` | Same-key request replaced this one | Expected during rapid input — no action needed |
| `REJECTED` | Guard returned falsy | Check preconditions, show user feedback |
| `TIMEOUT` | Guard timed out | Increase timeout or check target readiness |
| `NO_TARGET` | No target attached | Call `attach()` before making requests |
| `DETACHED` | Target was detached | Re-attach or abort operation |
| `DESTROYED` | Store was destroyed | Create new store instance |
---
## Expected vs Unexpected Errors
Document which errors are "normal" vs programming errors:
| Code | Expected? | Notes |
| ------------ | --------- | --------------------------------------------- |
| `SUPERSEDED` | Often | Rapid user input (scrubbing, repeated clicks) |
| `ABORTED` | Often | Component unmount, navigation |
| `CANCELLED` | Sometimes | Intentional coordination between requests |
| `REJECTED` | Sometimes | Guard logic blocking execution |
| `TIMEOUT` | Rarely | Slow media load, network issues |
| `NO_TARGET` | Never | Programming error — attach before use |
| `DETACHED` | Rarely | Lifecycle timing issue |
| `DESTROYED` | Never | Programming error — don't use after destroy |
---
## Error Handling Patterns
### Global Handler (store config)
```ts
const store = createStore({
slices: [playbackSlice, volumeSlice],
onError: ({ error, request }) => {
if (request) {
console.error(`${request.name} failed:`, error.code);
}
// Report to analytics, show toast, etc.
},
});
```
### Local Handler (try/catch)
```ts
import { isStoreError } from '@videojs/store';
try {
await store.request.play();
} catch (error) {
if (isStoreError(error)) {
switch (error.code) {
case 'SUPERSEDED':
// Another request took over — expected, ignore
break;
case 'REJECTED':
// Guard blocked execution — show feedback
showMessage('Cannot play right now');
break;
case 'TIMEOUT':
// Took too long — retry or show error
showMessage('Media not ready');
break;
default:
console.error(`[${error.code}]`, error.message);
}
} else {
throw error; // Re-throw unknown errors
}
}
```
### Type Guard Pattern
Always show the type guard:
```ts
import { isStoreError } from '@videojs/store';
function handleError(error: unknown) {
if (isStoreError(error)) {
// error is StoreError — has .code, .message
return { code: error.code, message: error.message };
}
throw error;
}
```
---
## Troubleshooting Section Format
### Structure
1. Error code/message as heading
2. **Cause:** One sentence
3. **Solution:** Code example
### Examples
#### NO_TARGET
**Cause:** Request made before `attach()` was called.
**Solution:**
```ts
// ❌ Wrong
const store = createStore({ slices: [playbackSlice] });
await store.request.play(); // Error: NO_TARGET
// ✅ Correct
const store = createStore({ slices: [playbackSlice] });
store.attach(videoElement);
await store.request.play();
```
#### SUPERSEDED
**Cause:** Another request with the same key started before this one finished.
**Solution:** This is usually expected behavior. If you need the result, check before making a new request:
```ts
// If you need to know the final state
const result = await store.request.play();
// Result may be from a later request if superseded
// If you want to prevent supersession, use unique keys
request: {
trackEvent: {
key: () => Symbol(), // Each call gets unique key
handler: (data) => analytics.log(data),
},
}
```
#### REJECTED
**Cause:** A guard returned a falsy value.
**Solution:** Check what condition the guard expects:
```ts
// Guard that checks readyState
const canPlay: Guard<HTMLMediaElement> = ({ target }) => {
return target.readyState >= HTMLMediaElement.HAVE_ENOUGH_DATA;
};
// If rejected, media isn't ready — wait for canplay event
player.on('canplay', () => {
// Now safe to request play
store.request.play();
});
```
#### TIMEOUT
**Cause:** A guard didn't resolve within the timeout period.
**Solution:** Increase the timeout or ensure the target is ready:
```ts
import { timeout } from '@videojs/store';
request: {
play: {
// Increase timeout for slow connections
guard: timeout(canMediaPlay, 10000), // 10 seconds
handler: async (_, { target }) => {
await target.play();
},
},
}
```
#### ABORTED
**Cause:** The abort signal was triggered (usually from component unmount).
**Solution:** This is expected behavior. Ensure cleanup runs:
```ts
// React
useEffect(() => {
const controller = new AbortController();
store.request.play(null, { signal: controller.signal });
return () => controller.abort(); // Cleans up on unmount
}, []);
```
---
## API Reference Format
When documenting error-related APIs:
### isStoreError
Type guard for store errors.
```ts
import { isStoreError } from '@videojs/store';
if (isStoreError(error)) {
console.log(error.code); // 'ABORTED' | 'CANCELLED' | ...
}
```
#### Parameters
| Parameter | Type | Description |
| --------- | --------- | ---------------- |
| `error` | `unknown` | Any caught error |
#### Returns
`error is StoreError` — Type predicate
### StoreError
Error thrown by store operations.
#### Properties
| Property | Type | Description |
| --------- | ---------------- | -------------------------- |
| `code` | `StoreErrorCode` | Error classification |
| `message` | `string` | Human-readable description |
#### StoreErrorCode
```ts
type StoreErrorCode =
| 'ABORTED'
| 'CANCELLED'
| 'DESTROYED'
| 'DETACHED'
| 'NO_TARGET'
| 'REJECTED'
| 'SUPERSEDED'
| 'TIMEOUT';
```
---
## Checklist
When documenting errors:
- [ ] Error code table with all codes
- [ ] Expected vs unexpected classification
- [ ] Global handler example (onError)
- [ ] Local handler example (try/catch)
- [ ] Type guard usage shown
- [ ] Troubleshooting section for common errors
- [ ] Each troubleshooting entry has: Cause + Solution
- [ ] Code examples are self-contained
@@ -0,0 +1,303 @@
# Progressive Disclosure Pattern
How to layer information for different audiences.
## Four-Tier Information Hierarchy
| Tier | Purpose | Audience | Length |
|------|---------|----------|--------|
| **Quick Start** | First success in <5 min | Everyone | 1 page |
| **Concepts** | Mental models | Learning | 2-5 pages |
| **Guides** | Task completion | Building | Per-task |
| **API Reference** | Complete spec | Referencing | Comprehensive |
## Quick Start Pattern
Goal: Working code in under 5 minutes.
```markdown
## Quick Start
### Install
npm install @videojs/react
### Use
import { Player } from '@videojs/react';
function App() {
return <Player src="video.mp4" />;
}
That's it. [See the full guide →](/guides/getting-started)
```
**Rules:**
- Max 3 code blocks
- No configuration options
- No edge cases
- Link to "full guide" for more
## Expandable Sections
Use `<details>` for optional depth:
```markdown
## Configuration
const player = createPlayer({ src: 'video.mp4' });
<details>
<summary>All configuration options</summary>
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `src` | `string` | — | Source URL |
| `autoplay` | `boolean` | `false` | Auto-start |
| `muted` | `boolean` | `false` | Start muted |
| ... | ... | ... | ... |
</details>
```
## Tabbed Complexity
Simple → Advanced in tabs:
```markdown
## Creating a Player
<Tabs>
<Tab label="Basic">
const player = createPlayer({ src: 'video.mp4' });
</Tab>
<Tab label="With Options">
const player = createPlayer({
src: 'video.mp4',
autoplay: true,
muted: true,
tracks: [{ kind: 'subtitles', src: 'en.vtt' }],
});
</Tab>
<Tab label="Full Control">
const player = createPlayer({
src: 'video.mp4',
autoplay: true,
muted: true,
loop: false,
preload: 'metadata',
crossOrigin: 'anonymous',
tracks: [
{ kind: 'subtitles', src: 'en.vtt', label: 'English', default: true },
{ kind: 'subtitles', src: 'es.vtt', label: 'Español' },
],
plugins: [analyticsPlugin(), adsPlugin()],
onPlay: () => console.log('play'),
onError: (e) => console.error(e),
});
</Tab>
</Tabs>
```
## "See Also" Sections
End every page with related content:
```markdown
## See Also
- [Events Guide](/guides/events) — Listen to player events
- [Styling Guide](/guides/styling) — Customize appearance
- [API Reference](/api/player) — Full Player API
```
## Callout Boxes
For important asides without breaking flow:
```markdown
:::note
The player must be attached before calling `play()`.
:::
:::warning
`autoplay` requires `muted` in most browsers.
:::
:::tip
Use `preload="metadata"` for faster initial load.
:::
```
## Inline Links
Link concepts on first mention:
```markdown
Create a [player](/api/player) and attach it to a
[media element](/concepts/media-elements). The player uses
[requests](/concepts/requests) to coordinate state changes.
```
## Layered Examples
Same feature, increasing detail:
```markdown
## Playing Media
### Basic
player.play();
### With Error Handling
try {
await player.play();
} catch (error) {
if (error.name === 'NotAllowedError') {
// Autoplay blocked, show play button
}
}
### With Request API
const result = await player.request.play();
if (!result.success) {
switch (result.error.code) {
case 'NOT_ALLOWED':
// Show play button
break;
case 'NOT_SUPPORTED':
// Show format error
break;
}
}
```
## Feature Flags
Document experimental features separately:
```markdown
## Experimental Features
:::warning
These features may change or be removed.
:::
### Picture-in-Picture
Enable with the `experimentalPiP` flag:
const player = createPlayer({
src: 'video.mp4',
experimentalPiP: true,
});
```
## Version-Specific Content
Show version differences:
```markdown
## Migration from v9
<Tabs>
<Tab label="v9 (Old)">
videojs('player', { sources: [{ src: 'video.mp4' }] });
</Tab>
<Tab label="v10 (New)">
createPlayer({ src: 'video.mp4' });
</Tab>
</Tabs>
### What Changed
| v9 | v10 |
|----|-----|
| `videojs()` function | `createPlayer()` |
| `sources` array | `src` string |
| jQuery-style API | Modern async API |
```
## Audience Markers
Signal who content is for:
```markdown
## Advanced: Custom Tech
> This section is for library authors building custom playback engines.
A Tech is the abstraction layer between the player and the media element...
```
## Prerequisites
State requirements upfront:
```markdown
## Building Plugins
### Prerequisites
- Familiarity with the [Player API](/api/player)
- Understanding of [Events](/concepts/events)
- Node.js 18+
### Before You Start
Complete the [Getting Started](/guides/getting-started) guide first.
```
## Summary Boxes
TL;DR for skimmers:
```markdown
## State Management
:::summary
- State is readonly — use requests to change it
- Requests are async and can fail
- Subscribe to state changes with `subscribe()`
:::
The player uses a unidirectional data flow...
```
## Code Annotations
Explain complex code inline:
```ts
const player = createPlayer({
src: 'video.mp4',
// 1. Autoplay requires muted in most browsers
autoplay: true,
muted: true,
// 2. Preload metadata for faster start
preload: 'metadata',
// 3. Enable CORS for cross-origin sources
crossOrigin: 'anonymous',
});
```
## Skip Links
Let users jump to what they need:
```markdown
## Player Configuration
**Jump to:** [Basic](#basic) | [Sources](#sources) | [Tracks](#tracks) | [Events](#events) | [Plugins](#plugins)
### Basic
...
### Sources
...
```
@@ -0,0 +1,255 @@
# Props Tables Pattern
Consistent formats for documenting props, data attributes, CSS variables, and events.
## Props Table Format
```markdown
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `src` | `string` | — | Media source URL |
| `autoplay` | `boolean` | `false` | Start playing automatically |
| `muted` | `boolean` | `false` | Start muted |
| `loop` | `boolean` | `false` | Loop playback |
| `controls` | `boolean` | `true` | Show default controls |
| `onPlay` | `() => void` | — | Called when playback starts |
```
### Conventions
**Required props:** No default, use `—` or mark with `*`
```markdown
| `src`* | `string` | — | Media source URL (required) |
```
**Optional props:** Always show default
```markdown
| `volume` | `number` | `1` | Initial volume (0-1) |
```
**Callback props:** `on` prefix, show signature
```markdown
| `onTimeUpdate` | `(time: number) => void` | — | Called on time change |
```
**Enum props:** Show all options
```markdown
| `preload` | `'auto' \| 'metadata' \| 'none'` | `'metadata'` | Preload behavior |
```
**Complex types:** Link to type definition
```markdown
| `tracks` | [`TextTrack[]`](#texttrack) | `[]` | Text tracks (captions, subtitles) |
```
## Data Attributes Table Format
```markdown
| Attribute | Values | Description |
|-----------|--------|-------------|
| `data-state` | `'idle' \| 'loading' \| 'ready' \| 'error'` | Current player state |
| `data-playing` | `''` | Present during playback |
| `data-paused` | `''` | Present when paused |
| `data-muted` | `''` | Present when muted |
| `data-fullscreen` | `''` | Present in fullscreen |
| `data-orientation` | `'horizontal' \| 'vertical'` | Slider orientation |
```
### Boolean Attributes
For boolean state, document presence/absence:
```markdown
| `data-playing` | Present when playing, absent when not |
```
### State Attributes
For state machines, show all values:
```markdown
| `data-state` | `'idle'` | Initial state |
| | `'loading'` | Loading media |
| | `'ready'` | Ready to play |
| | `'playing'` | Currently playing |
| | `'paused'` | Paused |
| | `'ended'` | Playback ended |
| | `'error'` | Error occurred |
```
### Usage Examples
Always follow with CSS example:
```css
/* Style based on state */
.player[data-loading] {
opacity: 0.5;
}
.player[data-playing] .play-icon {
display: none;
}
.player[data-paused] .pause-icon {
display: none;
}
```
## CSS Variables Table Format
```markdown
| Variable | Default | Description |
|----------|---------|-------------|
| `--player-accent-color` | `#3b82f6` | Primary accent color |
| `--player-bg` | `#000` | Background color |
| `--player-controls-bg` | `rgba(0,0,0,0.7)` | Controls background |
| `--player-slider-height` | `4px` | Slider track height |
| `--player-thumb-size` | `12px` | Slider thumb size |
```
### With Scoping
Document which component owns the variable:
```markdown
### Player Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `--player-bg` | `#000` | Player background |
### Slider Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `--slider-height` | `4px` | Track height |
```
### Usage Examples
```css
/* Customize theme */
.player {
--player-accent-color: #ef4444;
--player-bg: #1a1a1a;
}
/* Dynamic sizing */
.slider {
--slider-height: 8px;
}
```
## Events Table Format
```markdown
| Event | Payload | Description |
|-------|---------|-------------|
| `play` | `void` | Playback started |
| `pause` | `void` | Playback paused |
| `ended` | `void` | Playback ended |
| `timeupdate` | `{ currentTime: number }` | Current time changed |
| `volumechange` | `{ volume: number, muted: boolean }` | Volume or muted changed |
| `error` | `{ code: number, message: string }` | Error occurred |
| `statechange` | `{ state: PlayerState }` | Any state changed |
```
### Event Payload Types
Link to type definitions:
```markdown
| `error` | [`PlayerError`](#playererror) | Error occurred |
```
### Event Examples
```ts
player.on('timeupdate', ({ currentTime }) => {
console.log(`Time: ${currentTime}s`);
});
player.on('error', ({ code, message }) => {
console.error(`Error ${code}: ${message}`);
});
```
## Methods Table Format
```markdown
| Method | Signature | Description |
|--------|-----------|-------------|
| `play()` | `() => Promise<void>` | Start playback |
| `pause()` | `() => void` | Pause playback |
| `seek()` | `(time: number) => void` | Seek to time |
| `setVolume()` | `(volume: number) => void` | Set volume (0-1) |
| `destroy()` | `() => void` | Cleanup player |
```
## Returns Table Format
For functions/hooks:
```markdown
| Property | Type | Description |
|----------|------|-------------|
| `state` | `PlayerState` | Current state (readonly) |
| `request` | `RequestAPI` | Methods to request changes |
| `subscribe` | `(cb: Callback) => Unsubscribe` | Subscribe to updates |
| `destroy` | `() => void` | Cleanup |
```
## Expandable Types
For complex types, use collapsible details:
```markdown
| `options` | [`PlayerOptions`](#playeroptions) | Configuration |
<details>
<summary>PlayerOptions</summary>
| Property | Type | Default |
|----------|------|---------|
| `src` | `string` | — |
| `autoplay` | `boolean` | `false` |
| `muted` | `boolean` | `false` |
</details>
```
## Framework Variations
### React Props
```markdown
| Prop | Type | Default |
|------|------|---------|
| `ref` | `React.Ref<PlayerRef>` | — |
| `children` | `React.ReactNode` | — |
| `className` | `string \| (state) => string` | — |
```
### Vue Props
```markdown
| Prop | Type | Default |
|------|------|---------|
| `modelValue` | `number` | — |
| `@update:modelValue` | `(value: number) => void` | — |
```
### Svelte Props
```markdown
| Prop | Type | Default |
|------|------|---------|
| `bind:value` | `number` | — |
| `$bindable` | ✓ | Can be bound |
```