@jswork/howler-audio-manager 1.0.1 → 1.0.2
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 +64 -0
- package/dist/index.cjs.js +137 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.mts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.esm.js +146 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +166 -3
- package/dist/index.umd.js.map +1 -1
- package/package.json +46 -31
- package/src/index.ts +2 -0
- package/src/manager.ts +4 -0
- package/src/react.tsx +98 -0
package/src/manager.ts
CHANGED
|
@@ -287,6 +287,10 @@ export class AudioManager<K extends string | number = string> {
|
|
|
287
287
|
}
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
+
getGlobalVolume(): number {
|
|
291
|
+
return this.globalVolume;
|
|
292
|
+
}
|
|
293
|
+
|
|
290
294
|
setGlobalVolume(volume: number): void {
|
|
291
295
|
this.globalVolume = volume;
|
|
292
296
|
this.HowlerInstance.volume(volume);
|
package/src/react.tsx
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import { AudioManager } from './manager';
|
|
4
|
+
import type { AudioEventType, AudioEventPayload } from './types';
|
|
5
|
+
|
|
6
|
+
const AudioManagerContext = createContext<AudioManager<any> | null>(null);
|
|
7
|
+
|
|
8
|
+
export interface AudioManagerProviderProps<K extends string | number = string> {
|
|
9
|
+
manager: AudioManager<K>;
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function AudioManagerProvider<K extends string | number = string>({
|
|
14
|
+
manager,
|
|
15
|
+
children
|
|
16
|
+
}: AudioManagerProviderProps<K>) {
|
|
17
|
+
return (
|
|
18
|
+
<AudioManagerContext.Provider value={manager}>
|
|
19
|
+
{children}
|
|
20
|
+
</AudioManagerContext.Provider>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function useAudio<K extends string | number = string>(): AudioManager<K> {
|
|
25
|
+
const manager = useContext(AudioManagerContext);
|
|
26
|
+
if (!manager) {
|
|
27
|
+
throw new Error('useAudio must be used within an <AudioManagerProvider>.');
|
|
28
|
+
}
|
|
29
|
+
return manager as unknown as AudioManager<K>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function useAudioEvent<K extends string | number = string>(
|
|
33
|
+
event: AudioEventType,
|
|
34
|
+
handler: (payload: AudioEventPayload<K>) => void
|
|
35
|
+
): void {
|
|
36
|
+
const manager = useAudio<K>();
|
|
37
|
+
const handlerRef = useRef(handler);
|
|
38
|
+
handlerRef.current = handler;
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const subscription = manager.on(event, (payload) => handlerRef.current(payload));
|
|
42
|
+
return () => subscription.destroy();
|
|
43
|
+
}, [manager, event]);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function useGlobalVolume(): [number, (volume: number) => void] {
|
|
47
|
+
const manager = useAudio();
|
|
48
|
+
const [volume, setVolumeState] = useState(() => manager.getGlobalVolume());
|
|
49
|
+
|
|
50
|
+
const setVolume = useCallback(
|
|
51
|
+
(next: number) => {
|
|
52
|
+
manager.setGlobalVolume(next);
|
|
53
|
+
setVolumeState(next);
|
|
54
|
+
},
|
|
55
|
+
[manager]
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return [volume, setVolume];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface PreloadState {
|
|
62
|
+
status: 'idle' | 'loading' | 'loaded' | 'error';
|
|
63
|
+
error: unknown;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function usePreload(urls: string[]): PreloadState {
|
|
67
|
+
const manager = useAudio();
|
|
68
|
+
const urlsKey = JSON.stringify(urls);
|
|
69
|
+
const [state, setState] = useState<PreloadState>({ status: 'idle', error: null });
|
|
70
|
+
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
const list: string[] = JSON.parse(urlsKey);
|
|
73
|
+
if (list.length === 0) {
|
|
74
|
+
setState({ status: 'idle', error: null });
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let cancelled = false;
|
|
79
|
+
setState({ status: 'loading', error: null });
|
|
80
|
+
|
|
81
|
+
manager.preloadUrls(list).then(
|
|
82
|
+
() => {
|
|
83
|
+
if (!cancelled) setState({ status: 'loaded', error: null });
|
|
84
|
+
},
|
|
85
|
+
(error) => {
|
|
86
|
+
if (!cancelled) setState({ status: 'error', error });
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return () => {
|
|
91
|
+
cancelled = true;
|
|
92
|
+
};
|
|
93
|
+
}, [manager, urlsKey]);
|
|
94
|
+
|
|
95
|
+
return state;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|