mirror of
https://github.com/zoriya/v10.git
synced 2026-08-15 02:14:06 +00:00
4.7 KiB
4.7 KiB
Features
Features are the primary abstraction. They bundle related state and requests.
Feature Definition
createFeature
import { createFeature } from '@videojs/store';
const playbackFeature = createFeature<HTMLMediaElement>()({
name: 'playback',
initialState: {
paused: true,
ended: false
},
getSnapshot: ({ target }) => ({
paused: target.paused,
ended: target.ended,
}),
subscribe: ({ target, update, signal }) => {
target.addEventListener('play', update, { signal });
target.addEventListener('pause', update, { signal });
target.addEventListener('ended', update, { signal });
},
request: {
play: (_, { target }) => target.play(),
pause: (_, { target }) => target.pause(),
toggle: (_, { target }) => target.paused ? target.play() : target.pause(),
},
});
Config Properties
| Property | Type | Description |
|---|---|---|
key |
symbol (optional) |
Unique identifier. Auto-generated if not provided. |
name |
string |
Human-readable name for debugging |
initialState |
object |
Initial state before target attached |
getSnapshot |
(ctx) => State |
Derive state from target |
subscribe |
(ctx) => void |
Set up subscriptions, call update() on changes |
request |
Record<string, RequestHandler> |
Actions that modify target |
Context Object
Both getSnapshot, subscribe, and request handlers receive a context:
interface FeatureContext {
target: Target; // HTMLMediaElement or PlayerTarget
store: Store; // Access other features via store.get()
signal: AbortSignal; // For cleanup (subscribe only)
update: () => void; // Trigger re-snapshot (subscribe only)
}
Feature Keys
Features can define a custom key for identity and type-carrying.
Pattern
// Define key
const PLAYBACK_KEY = Symbol.for('@videojs/playback');
// Create feature with key
const playbackFeature = createFeature({
key: PLAYBACK_KEY,
name: 'playback',
// ...
});
// Export typed key
export const playbackKey: FeatureKey<typeof playbackFeature> = PLAYBACK_KEY;
// Export feature
export { playbackFeature };
Usage
// Import just the key (smaller bundle, no feature code)
import { playbackKey } from '@videojs/core/features';
// Typed access
const playback = store.get(playbackKey); // PlaybackSlice | undefined
FeatureKey Type
// Type carrier — key holds the feature's type info
type FeatureKey<F extends Feature> = symbol & { __feature?: F };
Why Keys?
- Smaller imports — Import just the key when you don't need the feature definition
- Cross-realm identity —
Symbol.for()works across module boundaries - Type inference —
FeatureKey<F>carries the feature type forstore.get()
Feature Bundles
Bundles are sugar for common feature combinations.
Base Bundles
// Video player base
features.video = [
features.playback,
features.volume,
features.time,
features.presentation,
features.userActivity,
];
// Audio player base
features.audio = [
features.playback,
features.volume,
features.time,
];
Additional Bundles (Beta+)
features.streaming = [
features.qualitySelection,
features.audioTracks,
features.textTracks,
];
features.ads = [
features.adMarkers,
features.adSkip,
features.adCountdown,
];
features.live = [
features.liveIndicator,
features.lowLatency,
features.seekToLive,
features.dvr,
];
Granular vs Bundled
// Granular — import individual features
import '@videojs/html/feature/quality-selection';
import '@videojs/html/feature/audio-tracks';
// Bundled — sugar for above + more
import '@videojs/html/feature/streaming';
Extending Bundles
createPlayer({
features: [features.video, features.streaming, myCustomFeature]
});
Media vs Player Features
Media Features
Target HTMLMediaElement. Handle playback, volume, time, etc.
const volumeFeature = createMediaFeature({
name: 'volume',
initialState: {
volume: 1,
muted: false
},
getSnapshot: ({ target }) => ({
volume: target.volume,
muted: target.muted,
}),
// ...
});
Player Features
Target the container element. Have access to media store via store.get().
createPlayerFeature({
subscribe: ({ store, target, update, signal }) => {
// Access media features from player store
const playback = store.get(features.playback);
});