@mediafox/react 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # @mediafox/react
2
+
3
+ React hooks for [MediaFox](https://github.com/wiedymi/mediafox) Media Player.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @mediafox/react @mediafox/core
9
+ # or
10
+ bun add @mediafox/react @mediafox/core
11
+ # or
12
+ yarn add @mediafox/react @mediafox/core
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Basic Example
18
+
19
+ ```tsx
20
+ import { useRef, useEffect } from 'react';
21
+ import { useMediaFox } from '@mediafox/react';
22
+
23
+ function VideoPlayer() {
24
+ const canvasRef = useRef<HTMLCanvasElement>(null);
25
+ const { state, play, pause, load } = useMediaFox({
26
+ renderTarget: canvasRef.current,
27
+ onError: (error) => console.error('Player error:', error),
28
+ });
29
+
30
+ useEffect(() => {
31
+ load('/path/to/video.mp4');
32
+ }, [load]);
33
+
34
+ return (
35
+ <div>
36
+ <canvas ref={canvasRef} />
37
+ <div>
38
+ <button onClick={play} disabled={!state?.canPlay}>
39
+ Play
40
+ </button>
41
+ <button onClick={pause}>Pause</button>
42
+ <p>
43
+ {state?.currentTime.toFixed(2)}s / {state?.duration.toFixed(2)}s
44
+ </p>
45
+ </div>
46
+ </div>
47
+ );
48
+ }
49
+ ```
50
+
51
+ ### With Event Handlers
52
+
53
+ ```tsx
54
+ import { useMediaFox } from '@mediafox/react';
55
+
56
+ function VideoPlayer() {
57
+ const canvasRef = useRef<HTMLCanvasElement>(null);
58
+ const { state, play, pause, seek, load } = useMediaFox({
59
+ renderTarget: canvasRef.current,
60
+ volume: 0.8,
61
+ onPlay: () => console.log('Playing'),
62
+ onPause: () => console.log('Paused'),
63
+ onEnded: () => console.log('Ended'),
64
+ onTimeUpdate: ({ currentTime }) => console.log('Time:', currentTime),
65
+ });
66
+
67
+ // ... rest of component
68
+ }
69
+ ```
70
+
71
+ ## API
72
+
73
+ ### `useMediaFox(options?)`
74
+
75
+ Returns an object with:
76
+
77
+ - `player` - The MediaFox instance (or null if not initialized)
78
+ - `state` - Current player state (reactive)
79
+ - `load(source, options?)` - Load a media source
80
+ - `play()` - Start playback
81
+ - `pause()` - Pause playback
82
+ - `seek(time, options?)` - Seek to time in seconds
83
+ - `stop()` - Stop playback and reset to start
84
+ - `screenshot(options?)` - Capture current frame
85
+ - `setRenderTarget(canvas)` - Update render target
86
+
87
+ ### Options
88
+
89
+ All `PlayerOptions` from `@mediafox/core` plus event handlers:
90
+
91
+ - `onLoadStart`, `onLoadedMetadata`, `onLoadedData`
92
+ - `onCanPlay`, `onCanPlayThrough`
93
+ - `onPlay`, `onPause`, `onPlaying`, `onEnded`
94
+ - `onTimeUpdate`, `onDurationChange`
95
+ - `onVolumeChange`, `onRateChange`
96
+ - `onSeeking`, `onSeeked`, `onWaiting`
97
+ - `onProgress`, `onError`, `onWarning`
98
+ - `onTrackChange`, `onStateChange`
99
+
100
+ ## Features
101
+
102
+ - ✅ Automatic cleanup on unmount
103
+ - ✅ Optimized with `useSyncExternalStore` for React 18+
104
+ - ✅ SSR safe (lazy loads MediaFox)
105
+ - ✅ Fully typed with TypeScript
106
+ - ✅ Framework-agnostic core
107
+
108
+ ## License
109
+
110
+ MIT
@@ -0,0 +1,4 @@
1
+ export type { AudioTrackInfo, LoadOptions, MediaInfo, MediaSource, PlayerEventListener, PlayerEventMap, PlayerOptions, PlayerState, PlayerStateData, QualityLevel, ScreenshotOptions, SeekOptions, SubtitleTrackInfo, TimeRange, VideoTrackInfo, } from '@mediafox/core';
2
+ export type { UseMediaFoxOptions, UseMediaFoxReturn } from './useMediaFox';
3
+ export { useMediaFox } from './useMediaFox';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,cAAc,EACd,WAAW,EACX,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,WAAW,EACX,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ var m=Object.create;var{getPrototypeOf:E,defineProperty:B,getOwnPropertyNames:w}=Object;var O=Object.prototype.hasOwnProperty;var v=(x,I,F)=>{F=x!=null?m(E(x)):{};let U=I||!x||!x.__esModule?B(F,"default",{value:x,enumerable:!0}):F;for(let V of w(x))if(!O.call(U,V))B(U,V,{get:()=>x[V],enumerable:!0});return U};var S=((x)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(x,{get:(I,F)=>(typeof require<"u"?require:I)[F]}):x)(function(x){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+x+'" is not supported')});import{useCallback as T,useEffect as G,useMemo as k,useRef as j,useSyncExternalStore as C}from"react";function h(x={}){let I=j(null),F=j(null),U=j(new Set),V=k(()=>({renderTarget:x.renderTarget,audioContext:x.audioContext,volume:x.volume,muted:x.muted,playbackRate:x.playbackRate,autoplay:x.autoplay,preload:x.preload,crossOrigin:x.crossOrigin,maxCacheSize:x.maxCacheSize,renderer:x.renderer}),[x.renderTarget,x.audioContext,x.volume,x.muted,x.playbackRate,x.autoplay,x.preload,x.crossOrigin,x.maxCacheSize,x.renderer]);G(()=>{import("@mediafox/core").then(({MediaFox:L})=>{let M=new L(V);I.current=M;let P=M.subscribe((D)=>{F.current=D;for(let Q of U.current)Q()});F.current=M.getState();for(let D of U.current)D();return()=>{P.unsubscribe(),M.destroy(),I.current=null,F.current=null}})},[V]),G(()=>{let L=I.current;if(!L)return;let M=[],P=(D,Q)=>{if(Q)L.on(D,Q),M.push([D,Q])};return P("loadstart",x.onLoadStart),P("loadedmetadata",x.onLoadedMetadata),P("loadeddata",x.onLoadedData),P("canplay",x.onCanPlay),P("canplaythrough",x.onCanPlayThrough),P("play",x.onPlay),P("pause",x.onPause),P("playing",x.onPlaying),P("ended",x.onEnded),P("timeupdate",x.onTimeUpdate),P("durationchange",x.onDurationChange),P("volumechange",x.onVolumeChange),P("ratechange",x.onRateChange),P("seeking",x.onSeeking),P("seeked",x.onSeeked),P("waiting",x.onWaiting),P("progress",x.onProgress),P("error",x.onError),P("warning",x.onWarning),P("trackchange",x.onTrackChange),P("statechange",x.onStateChange),P("rendererchange",x.onRendererChange),P("rendererfallback",x.onRendererFallback),()=>{for(let[D,Q]of M)L.off(D,Q)}},[x.onLoadStart,x.onLoadedMetadata,x.onLoadedData,x.onCanPlay,x.onCanPlayThrough,x.onPlay,x.onPause,x.onPlaying,x.onEnded,x.onTimeUpdate,x.onDurationChange,x.onVolumeChange,x.onRateChange,x.onSeeking,x.onSeeked,x.onWaiting,x.onProgress,x.onError,x.onWarning,x.onTrackChange,x.onStateChange,x.onRendererChange,x.onRendererFallback]);let J=T((L)=>{return U.current.add(L),()=>{U.current.delete(L)}},[]),q=T(()=>F.current,[]),A=C(J,q,q),K=T(async(L,M)=>{if(!I.current)throw Error("Player not initialized");return I.current.load(L,M)},[]),N=T(async()=>{if(!I.current)throw Error("Player not initialized");return I.current.play()},[]),W=T(()=>{if(!I.current)throw Error("Player not initialized");I.current.pause()},[]),X=T(async(L,M)=>{if(!I.current)throw Error("Player not initialized");return I.current.seek(L,M)},[]),Y=T(async()=>{if(!I.current)throw Error("Player not initialized");return I.current.stop()},[]),Z=T(async(L)=>{if(!I.current)throw Error("Player not initialized");return I.current.screenshot(L)},[]),_=T(async(L)=>{if(!I.current)throw Error("Player not initialized");return I.current.setRenderTarget(L)},[]),$=T(async(L)=>{if(!I.current)throw Error("Player not initialized");return I.current.switchRenderer(L)},[]),z=A?.rendererType??null;return{player:I.current,state:A,load:K,play:N,pause:W,seek:X,stop:Y,screenshot:Z,setRenderTarget:_,switchRenderer:$,rendererType:z}}export{h as useMediaFox};
@@ -0,0 +1,68 @@
1
+ import type { LoadOptions, MediaFox, MediaSource, PlayerEventListener, PlayerOptions, PlayerStateData, RendererType, ScreenshotOptions, SeekOptions } from '@mediafox/core';
2
+ export interface UseMediaFoxOptions extends PlayerOptions {
3
+ onLoadStart?: PlayerEventListener<'loadstart'>;
4
+ onLoadedMetadata?: PlayerEventListener<'loadedmetadata'>;
5
+ onLoadedData?: PlayerEventListener<'loadeddata'>;
6
+ onCanPlay?: PlayerEventListener<'canplay'>;
7
+ onCanPlayThrough?: PlayerEventListener<'canplaythrough'>;
8
+ onPlay?: PlayerEventListener<'play'>;
9
+ onPause?: PlayerEventListener<'pause'>;
10
+ onPlaying?: PlayerEventListener<'playing'>;
11
+ onEnded?: PlayerEventListener<'ended'>;
12
+ onTimeUpdate?: PlayerEventListener<'timeupdate'>;
13
+ onDurationChange?: PlayerEventListener<'durationchange'>;
14
+ onVolumeChange?: PlayerEventListener<'volumechange'>;
15
+ onRateChange?: PlayerEventListener<'ratechange'>;
16
+ onSeeking?: PlayerEventListener<'seeking'>;
17
+ onSeeked?: PlayerEventListener<'seeked'>;
18
+ onWaiting?: PlayerEventListener<'waiting'>;
19
+ onProgress?: PlayerEventListener<'progress'>;
20
+ onError?: PlayerEventListener<'error'>;
21
+ onWarning?: PlayerEventListener<'warning'>;
22
+ onTrackChange?: PlayerEventListener<'trackchange'>;
23
+ onStateChange?: PlayerEventListener<'statechange'>;
24
+ onRendererChange?: PlayerEventListener<'rendererchange'>;
25
+ onRendererFallback?: PlayerEventListener<'rendererfallback'>;
26
+ }
27
+ export interface UseMediaFoxReturn {
28
+ player: MediaFox | null;
29
+ state: PlayerStateData | null;
30
+ load: (source: MediaSource, options?: LoadOptions) => Promise<void>;
31
+ play: () => Promise<void>;
32
+ pause: () => void;
33
+ seek: (time: number, options?: SeekOptions) => Promise<void>;
34
+ stop: () => Promise<void>;
35
+ screenshot: (options?: ScreenshotOptions) => Promise<Blob | null>;
36
+ setRenderTarget: (canvas: HTMLCanvasElement | OffscreenCanvas) => Promise<void>;
37
+ switchRenderer: (type: RendererType) => Promise<void>;
38
+ rendererType: RendererType | null;
39
+ }
40
+ /**
41
+ * React hook for MediaFox media player.
42
+ * Creates and manages a MediaFox instance with automatic cleanup.
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * function VideoPlayer() {
47
+ * const canvasRef = useRef<HTMLCanvasElement>(null);
48
+ * const { player, state, play, pause, load } = useMediaFox({
49
+ * renderTarget: canvasRef.current,
50
+ * onError: (error) => console.error(error)
51
+ * });
52
+ *
53
+ * useEffect(() => {
54
+ * load('/video.mp4');
55
+ * }, [load]);
56
+ *
57
+ * return (
58
+ * <div>
59
+ * <canvas ref={canvasRef} />
60
+ * <button onClick={play}>Play</button>
61
+ * <button onClick={pause}>Pause</button>
62
+ * </div>
63
+ * );
64
+ * }
65
+ * ```
66
+ */
67
+ export declare function useMediaFox(options?: UseMediaFoxOptions): UseMediaFoxReturn;
68
+ //# sourceMappingURL=useMediaFox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMediaFox.d.ts","sourceRoot":"","sources":["../src/useMediaFox.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@mediafox/react",
3
+ "version": "1.0.0",
4
+ "description": "React hooks for MediaFox media player",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "dev": "bun run --watch src/index.ts",
20
+ "build": "bun run build:js && bun run build:types",
21
+ "build:js": "bun build src/index.ts --outdir=dist --target=browser --format=esm --minify --external react --external @mediafox/core",
22
+ "build:types": "tsc --emitDeclarationOnly",
23
+ "test": "bun test",
24
+ "lint": "biome lint ./src",
25
+ "format": "biome format ./src",
26
+ "check": "biome check ./src",
27
+ "typecheck": "tsc --noEmit",
28
+ "prepublishOnly": "bun run build"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "peerDependencies": {
34
+ "@mediafox/core": "^1.0.0",
35
+ "react": ">=18.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/bun": "latest",
39
+ "@types/react": "^18.3.18"
40
+ },
41
+ "keywords": [
42
+ "react",
43
+ "hooks",
44
+ "video",
45
+ "player",
46
+ "mediafox",
47
+ "mediabunny"
48
+ ],
49
+ "author": "",
50
+ "license": "MIT",
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "https://github.com/wiedymi/mediafox.git",
54
+ "directory": "packages/react"
55
+ },
56
+ "bugs": {
57
+ "url": "https://github.com/wiedymi/mediafox/issues"
58
+ },
59
+ "homepage": "https://github.com/wiedymi/mediafox#readme"
60
+ }