@bouko/react 3.1.8 → 3.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.
@@ -0,0 +1,2 @@
1
+ export * from "./playback";
2
+ export * from "./sound";
@@ -0,0 +1,2 @@
1
+ export * from "./playback";
2
+ export * from "./sound";
@@ -0,0 +1,23 @@
1
+ import type { AudioRef } from "../element/with-audio";
2
+ /**
3
+ * Audio Playback Hook.
4
+ *
5
+ * Internal hook used by the Audio Player context provider to derive
6
+ * reactive playback state from. This hook is not UI-facing. It exists
7
+ * to translate the audio element events into declarative state that
8
+ * can be exposed through context and consumed by multiple components.
9
+ *
10
+ * @param {AudioRef} ref - Audio element owned by the player.
11
+ *
12
+ * @returns
13
+ * - `elapsed` (number): Current playback position (ms).
14
+ * - `duration` (number): Total track duration (ms).
15
+ * - `progress` (number): Normalized playback position (0-1).
16
+ * - `ended` (boolean): Whether the track has finished.
17
+ **/
18
+ export declare function usePlayback(ref: AudioRef): {
19
+ elapsed: number;
20
+ duration: number;
21
+ ended: boolean;
22
+ progress: number;
23
+ };
@@ -0,0 +1,50 @@
1
+ import { useEffect, useState } from "react";
2
+ import { withAudio } from "../element/with-audio";
3
+ /**
4
+ * Audio Playback Hook.
5
+ *
6
+ * Internal hook used by the Audio Player context provider to derive
7
+ * reactive playback state from. This hook is not UI-facing. It exists
8
+ * to translate the audio element events into declarative state that
9
+ * can be exposed through context and consumed by multiple components.
10
+ *
11
+ * @param {AudioRef} ref - Audio element owned by the player.
12
+ *
13
+ * @returns
14
+ * - `elapsed` (number): Current playback position (ms).
15
+ * - `duration` (number): Total track duration (ms).
16
+ * - `progress` (number): Normalized playback position (0-1).
17
+ * - `ended` (boolean): Whether the track has finished.
18
+ **/
19
+ export function usePlayback(ref) {
20
+ const [elapsed, setElapsed] = useState(0);
21
+ const [duration, setDuration] = useState(0);
22
+ const [ended, setEnded] = useState(false);
23
+ useEffect(() => withAudio(ref, (audio) => {
24
+ const onLoadedMetadata = () => {
25
+ const d = Number.isFinite(audio.duration) ? audio.duration : 0;
26
+ setDuration(d * 1000);
27
+ setEnded(false);
28
+ };
29
+ const onTimeUpdate = () => {
30
+ const e = audio.currentTime;
31
+ setElapsed(e * 1000);
32
+ };
33
+ const onPlay = () => setEnded(false);
34
+ const onEnded = () => setEnded(true);
35
+ audio.addEventListener("loadedmetadata", onLoadedMetadata);
36
+ audio.addEventListener("timeupdate", onTimeUpdate);
37
+ audio.addEventListener("play", onPlay);
38
+ audio.addEventListener("ended", onEnded);
39
+ return () => {
40
+ audio.removeEventListener("loadedmetadata", onLoadedMetadata);
41
+ audio.removeEventListener("timeupdate", onTimeUpdate);
42
+ audio.removeEventListener("play", onPlay);
43
+ audio.removeEventListener("ended", onEnded);
44
+ };
45
+ }), [ref]);
46
+ return {
47
+ elapsed, duration, ended,
48
+ progress: elapsed / duration
49
+ };
50
+ }
@@ -1 +1 @@
1
- export default function useSound(filename?: string): import("use-sound/dist/types").PlayFunction | undefined;
1
+ export declare function useSound(filename?: string): import("use-sound/dist/types").PlayFunction | undefined;
@@ -1,5 +1,5 @@
1
1
  import { default as base } from "use-sound";
2
- export default function useSound(filename) {
2
+ export function useSound(filename) {
3
3
  if (!filename)
4
4
  return;
5
5
  return base(filename)[0];
@@ -2,10 +2,8 @@ export { default as useElement } from "./element";
2
2
  export { default as useContainer } from "./element/container";
3
3
  export { default as useResize } from "./element/resize";
4
4
  export { default as useInterval } from "./clock/interval";
5
- export { default as useSound } from "./audio/sound";
6
5
  export { withAudio, type DivRef, type AudioRef } from "./element/with-audio";
7
6
  export * from "./router/params";
8
- export * from "./auth";
9
7
  export declare function useObjectUrl(): {
10
8
  setFromBlob: (blob: Blob) => string;
11
9
  revoke: () => void;
@@ -31,3 +29,5 @@ export declare function useConfig<T>({ fetcher, updater }: ConfigProps<T>): {
31
29
  config: Record<string, T>;
32
30
  update: (id: string, x: T) => Promise<void>;
33
31
  };
32
+ export * from "./auth";
33
+ export * from "./audio/_";
@@ -3,10 +3,8 @@ export { default as useElement } from "./element";
3
3
  export { default as useContainer } from "./element/container";
4
4
  export { default as useResize } from "./element/resize";
5
5
  export { default as useInterval } from "./clock/interval";
6
- export { default as useSound } from "./audio/sound";
7
6
  export { withAudio } from "./element/with-audio";
8
7
  export * from "./router/params";
9
- export * from "./auth";
10
8
  export function useObjectUrl() {
11
9
  const urlRef = useRef(null);
12
10
  const revoke = useCallback(() => {
@@ -54,3 +52,5 @@ export function useConfig({ fetcher, updater }) {
54
52
  };
55
53
  return { config, update };
56
54
  }
55
+ export * from "./auth";
56
+ export * from "./audio/_";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
 
3
3
  "name": "@bouko/react",
4
- "version": "3.1.8",
4
+ "version": "3.2.0",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "license": "MIT",