oddysee-react 0.2.0-canary.3 → 0.2.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.
Files changed (2) hide show
  1. package/README.md +59 -0
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -80,6 +80,16 @@ interface UseHlsAudioPlayerResult {
80
80
  pause: () => void;
81
81
  setVolume: (volume: number) => void;
82
82
  setCurrentTime: (time: number) => void;
83
+ beginSeek: () => void;
84
+ updateSeek: (time: number) => void;
85
+ commitSeek: () => void;
86
+ };
87
+ scrub: {
88
+ isScrubbing: boolean;
89
+ displayTime: number;
90
+ begin: () => void;
91
+ update: (time: number) => void;
92
+ commit: (time?: number) => void;
83
93
  };
84
94
  }
85
95
  ```
@@ -184,6 +194,54 @@ export default function BasicPlayer() {
184
194
  }
185
195
  ```
186
196
 
197
+ ### Deferred Seeking (Scrubber)
198
+
199
+ The hook provides a `scrub` object that wraps the three-phase seek model (`beginSeek` / `updateSeek` / `commitSeek`). This separates the user's drag gesture from the actual media seek so audio doesn't glitch while scrubbing.
200
+
201
+ ```tsx
202
+ import { useHlsAudioPlayer } from 'oddysee-react';
203
+
204
+ export default function ScrubberPlayer() {
205
+ const { state, controls, scrub, isPlaying } = useHlsAudioPlayer({
206
+ src: { url: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8' },
207
+ });
208
+
209
+ return (
210
+ <div className="player">
211
+ <button onClick={() => isPlaying ? controls.pause() : controls.play()}>
212
+ {isPlaying ? 'Pause' : 'Play'}
213
+ </button>
214
+
215
+ <input
216
+ type="range"
217
+ min={0}
218
+ max={state.duration ?? 0}
219
+ value={scrub.displayTime}
220
+ onMouseDown={() => scrub.begin()}
221
+ onTouchStart={() => scrub.begin()}
222
+ onChange={(e) => scrub.update(parseFloat(e.target.value))}
223
+ onMouseUp={() => scrub.commit()}
224
+ onTouchEnd={() => scrub.commit()}
225
+ />
226
+ <span>
227
+ {scrub.displayTime.toFixed(0)}s / {state.duration?.toFixed(0) ?? '--'}s
228
+ </span>
229
+ </div>
230
+ );
231
+ }
232
+ ```
233
+
234
+ `scrub.displayTime` automatically switches between the live scrub position (while dragging) and `state.currentTime` (during normal playback), so your UI stays in sync without any extra logic.
235
+
236
+ You can also call the low-level methods directly via `controls`:
237
+
238
+ ```tsx
239
+ // Programmatic skip forward 10s
240
+ controls.beginSeek();
241
+ controls.updateSeek(state.currentTime + 10);
242
+ controls.commitSeek();
243
+ ```
244
+
187
245
  ### Playlist Player
188
246
 
189
247
  ```tsx
@@ -338,6 +396,7 @@ export default function EventHandlingPlayer() {
338
396
  }
339
397
  ```
340
398
 
399
+
341
400
  ## Features
342
401
 
343
402
  - **Simple Hook Interface**: Just call `useHlsAudioPlayer()` and get everything you need
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.2.0-canary.3",
7
+ "version": "0.2.0",
8
8
  "type": "module",
9
9
  "author": "Karelle Hofler",
10
10
  "main": "dist/index.js",
@@ -30,7 +30,7 @@
30
30
  "pub:test": "npm run build && npm publish --tag test"
31
31
  },
32
32
  "dependencies": {
33
- "oddysee-typescript": "^0.2.0-canary.3",
33
+ "oddysee-typescript": "^0.2.0",
34
34
  "react": "^19.2.0",
35
35
  "react-dom": "^19.2.0"
36
36
  },