@jswork/howler-audio-manager 0.0.0-stage → 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/LICENSE.txt +21 -0
- package/README.md +257 -2
- package/dist/index.cjs.js +747 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.mts +87 -0
- package/dist/index.d.ts +89 -0
- package/dist/index.esm.js +546 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.umd.js +648 -0
- package/dist/index.umd.js.map +1 -0
- package/package.json +66 -4
- package/src/index.ts +5 -0
- package/src/manager.ts +317 -0
- package/src/react.tsx +98 -0
- package/src/types.ts +40 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/afei/github/howler-audio-manager/dist/index.cjs.js","../src/manager.ts","../src/react.tsx"],"names":["Object","defineProperty","exports","value","_nullishCoalesce","lhs","rhsFn","_optionalChain","ops","lastAccessLHS","undefined","i","length","op","fn","args","call","_howler","require","AudioManager","options","inject","effectCache","Map","urlAudioCache","preloadPromises","activeUrlHowl","globalVolume","listeners","HowlConstructor","_","HowlClass","Howl","HowlerInstance","_2","HowlerObj","Howler","_3","defaultVolume","setGlobalVolume","hasEffect","key","has","loadEffect","url","get","unload","howl","src","preload","on","emit","type","_id","error","set","loadEffects","map","keys","forEach","typedKey","isNaN","Number","playEffect","console","warn","String","playing","stop","_4","volume","off","once","soundId","_5","onStart","_6","_7","_8","onEnd","_9","_10","_11","onStop","_12","_13","onError","_14","play","stopEffect","removeEffect","delete","preloadUrl","existing","state","Promise","resolve","pending","createUrlHowl","promise","reject","settle","then","preloadUrls","urls","all","playUrl","isSingleton","_15","singleton","_16","loop","_17","_18","_19","_20","_21","_22","_23","_24","_25","_26","_27","stopUrl","event","handler","Set","add","destroy","payload","err","getGlobalVolume","mute","muted","stopAll","clear","_react","_jsxruntime","AudioManagerContext","createContext","AudioManagerProvider","manager","children","jsx","Provider","useAudio","useContext","Error","useAudioEvent","handlerRef","useRef","current","useEffect","subscription","useGlobalVolume","useState","setVolumeState","setVolume","useCallback","next","usePreload","urlsKey","JSON","stringify","status","setState","list","parse","cancelled","default"],"mappings":"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","sourcesContent":["\"use strict\";Object.defineProperty(exports, \"__esModule\", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }/*!\n * name: @jswork/howler-audio-manager\n * description: Howler.js audio manager, enum-driven sounds for H5.\n * homepage: https://js.work\n * version: 1.0.2\n * date: 2026-10-20 20:03:06\n * license: MIT\n */\n\n\n// src/manager.ts\nvar _howler = require('howler');\nvar AudioManager = class {\n constructor(options, inject) {\n this.effectCache = /* @__PURE__ */ new Map();\n this.urlAudioCache = /* @__PURE__ */ new Map();\n this.preloadPromises = /* @__PURE__ */ new Map();\n this.activeUrlHowl = null;\n this.globalVolume = 1;\n this.listeners = /* @__PURE__ */ new Map();\n this.HowlConstructor = _nullishCoalesce(_optionalChain([inject, 'optionalAccess', _ => _.HowlClass]), () => ( _howler.Howl));\n this.HowlerInstance = _nullishCoalesce(_optionalChain([inject, 'optionalAccess', _2 => _2.HowlerObj]), () => ( _howler.Howler));\n if (typeof _optionalChain([options, 'optionalAccess', _3 => _3.defaultVolume]) === \"number\") {\n this.setGlobalVolume(options.defaultVolume);\n }\n }\n hasEffect(key) {\n return this.effectCache.has(key);\n }\n loadEffect(key, url) {\n if (this.effectCache.has(key)) {\n this.effectCache.get(key).unload();\n }\n const howl = new this.HowlConstructor({\n src: [url],\n preload: true\n });\n howl.on(\"load\", () => {\n this.emit(\"load\", { type: \"effect\", key, url });\n });\n howl.on(\"loaderror\", (_id, error) => {\n this.emit(\"error\", { type: \"effect\", key, url, error });\n });\n this.effectCache.set(key, howl);\n }\n loadEffects(map) {\n Object.keys(map).forEach((key) => {\n const typedKey = isNaN(Number(key)) ? key : Number(key);\n this.loadEffect(typedKey, map[key]);\n });\n }\n playEffect(key, options) {\n const howl = this.effectCache.get(key);\n if (!howl) {\n console.warn(`[AudioManager] Effect not found for key: ${String(key)}.`);\n return void 0;\n }\n if (howl.playing()) {\n howl.stop();\n }\n if (typeof _optionalChain([options, 'optionalAccess', _4 => _4.volume]) === \"number\") {\n howl.volume(options.volume);\n }\n howl.off(\"play\");\n howl.off(\"end\");\n howl.off(\"stop\");\n howl.off(\"playerror\");\n howl.once(\"play\", (soundId) => {\n _optionalChain([options, 'optionalAccess', _5 => _5.onStart, 'optionalCall', _6 => _6(soundId)]);\n this.emit(\"play\", { type: \"effect\", key, soundId });\n });\n howl.once(\"end\", (soundId) => {\n if (typeof _optionalChain([options, 'optionalAccess', _7 => _7.volume]) === \"number\") {\n howl.volume(1);\n }\n _optionalChain([options, 'optionalAccess', _8 => _8.onEnd, 'optionalCall', _9 => _9(soundId)]);\n this.emit(\"end\", { type: \"effect\", key, soundId });\n });\n howl.once(\"stop\", (soundId) => {\n if (typeof _optionalChain([options, 'optionalAccess', _10 => _10.volume]) === \"number\") {\n howl.volume(1);\n }\n _optionalChain([options, 'optionalAccess', _11 => _11.onStop, 'optionalCall', _12 => _12(soundId)]);\n this.emit(\"stop\", { type: \"effect\", key, soundId });\n });\n howl.once(\"playerror\", (soundId, error) => {\n _optionalChain([options, 'optionalAccess', _13 => _13.onError, 'optionalCall', _14 => _14(soundId, error)]);\n this.emit(\"error\", { type: \"effect\", key, soundId, error });\n });\n return howl.play();\n }\n stopEffect(key) {\n const howl = this.effectCache.get(key);\n if (howl) {\n howl.stop();\n }\n }\n removeEffect(key) {\n const howl = this.effectCache.get(key);\n if (howl) {\n howl.unload();\n this.effectCache.delete(key);\n }\n }\n preloadUrl(url) {\n const existing = this.urlAudioCache.get(url);\n if (existing && existing.state() === \"loaded\") {\n return Promise.resolve();\n }\n const pending = this.preloadPromises.get(url);\n if (pending) {\n return pending;\n }\n const howl = existing && existing.state() !== \"unloaded\" ? existing : this.createUrlHowl(url);\n const promise = new Promise((resolve, reject) => {\n howl.once(\"load\", () => {\n resolve();\n });\n howl.once(\"loaderror\", (_id, error) => {\n this.urlAudioCache.delete(url);\n reject(error);\n });\n });\n this.preloadPromises.set(url, promise);\n const settle = () => {\n if (this.preloadPromises.get(url) === promise) {\n this.preloadPromises.delete(url);\n }\n };\n promise.then(settle, settle);\n return promise;\n }\n preloadUrls(urls) {\n return Promise.all(urls.map((url) => this.preloadUrl(url)));\n }\n createUrlHowl(url) {\n const howl = new this.HowlConstructor({\n src: [url],\n preload: true\n });\n howl.on(\"load\", () => {\n this.emit(\"load\", { type: \"url\", url });\n });\n howl.on(\"loaderror\", (_id, error) => {\n this.urlAudioCache.delete(url);\n this.emit(\"error\", { type: \"url\", url, error });\n });\n this.urlAudioCache.set(url, howl);\n return howl;\n }\n playUrl(url, options) {\n const howl = this.urlAudioCache.get(url) || this.createUrlHowl(url);\n const isSingleton = _optionalChain([options, 'optionalAccess', _15 => _15.singleton]) !== false;\n if (isSingleton && this.activeUrlHowl && this.activeUrlHowl !== howl && this.activeUrlHowl.playing()) {\n this.activeUrlHowl.stop();\n }\n if (howl.playing()) {\n howl.stop();\n }\n if (_optionalChain([options, 'optionalAccess', _16 => _16.loop]) !== void 0) {\n howl.loop(options.loop);\n }\n if (typeof _optionalChain([options, 'optionalAccess', _17 => _17.volume]) === \"number\") {\n howl.volume(options.volume);\n }\n if (isSingleton) {\n this.activeUrlHowl = howl;\n }\n howl.off(\"play\");\n howl.off(\"end\");\n howl.off(\"stop\");\n howl.off(\"playerror\");\n howl.once(\"play\", (soundId) => {\n _optionalChain([options, 'optionalAccess', _18 => _18.onStart, 'optionalCall', _19 => _19(soundId)]);\n this.emit(\"play\", { type: \"url\", url, soundId });\n });\n howl.once(\"end\", (soundId) => {\n if (typeof _optionalChain([options, 'optionalAccess', _20 => _20.volume]) === \"number\") {\n howl.volume(1);\n }\n _optionalChain([options, 'optionalAccess', _21 => _21.onEnd, 'optionalCall', _22 => _22(soundId)]);\n this.emit(\"end\", { type: \"url\", url, soundId });\n if (this.activeUrlHowl === howl && !howl.loop()) {\n this.activeUrlHowl = null;\n }\n });\n howl.once(\"stop\", (soundId) => {\n if (typeof _optionalChain([options, 'optionalAccess', _23 => _23.volume]) === \"number\") {\n howl.volume(1);\n }\n _optionalChain([options, 'optionalAccess', _24 => _24.onStop, 'optionalCall', _25 => _25(soundId)]);\n this.emit(\"stop\", { type: \"url\", url, soundId });\n if (this.activeUrlHowl === howl) {\n this.activeUrlHowl = null;\n }\n });\n howl.once(\"playerror\", (soundId, error) => {\n _optionalChain([options, 'optionalAccess', _26 => _26.onError, 'optionalCall', _27 => _27(soundId, error)]);\n this.emit(\"error\", { type: \"url\", url, soundId, error });\n if (this.activeUrlHowl === howl) {\n this.activeUrlHowl = null;\n }\n });\n return howl.play();\n }\n stopUrl(url) {\n const howl = this.urlAudioCache.get(url);\n if (howl) {\n howl.stop();\n }\n }\n on(event, handler) {\n const set = _nullishCoalesce(this.listeners.get(event), () => ( /* @__PURE__ */ new Set()));\n this.listeners.set(event, set);\n set.add(handler);\n return {\n destroy: () => {\n set.delete(handler);\n }\n };\n }\n emit(event, payload) {\n const set = this.listeners.get(event);\n if (set) {\n set.forEach((handler) => {\n try {\n handler(payload);\n } catch (err) {\n console.error(`[AudioManager] Error in event listener for ${event}:`, err);\n }\n });\n }\n }\n getGlobalVolume() {\n return this.globalVolume;\n }\n setGlobalVolume(volume) {\n this.globalVolume = volume;\n this.HowlerInstance.volume(volume);\n }\n mute(muted) {\n this.HowlerInstance.mute(muted);\n }\n stopAll() {\n this.HowlerInstance.stop();\n this.activeUrlHowl = null;\n }\n destroy() {\n this.effectCache.forEach((howl) => howl.unload());\n this.urlAudioCache.forEach((howl) => howl.unload());\n this.effectCache.clear();\n this.urlAudioCache.clear();\n this.preloadPromises.clear();\n this.listeners.clear();\n this.activeUrlHowl = null;\n }\n};\n\n// src/react.tsx\nvar _react = require('react');\nvar _jsxruntime = require('react/jsx-runtime');\nvar AudioManagerContext = _react.createContext.call(void 0, null);\nfunction AudioManagerProvider({\n manager,\n children\n}) {\n return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AudioManagerContext.Provider, { value: manager, children });\n}\nfunction useAudio() {\n const manager = _react.useContext.call(void 0, AudioManagerContext);\n if (!manager) {\n throw new Error(\"useAudio must be used within an <AudioManagerProvider>.\");\n }\n return manager;\n}\nfunction useAudioEvent(event, handler) {\n const manager = useAudio();\n const handlerRef = _react.useRef.call(void 0, handler);\n handlerRef.current = handler;\n _react.useEffect.call(void 0, () => {\n const subscription = manager.on(event, (payload) => handlerRef.current(payload));\n return () => subscription.destroy();\n }, [manager, event]);\n}\nfunction useGlobalVolume() {\n const manager = useAudio();\n const [volume, setVolumeState] = _react.useState.call(void 0, () => manager.getGlobalVolume());\n const setVolume = _react.useCallback.call(void 0, \n (next) => {\n manager.setGlobalVolume(next);\n setVolumeState(next);\n },\n [manager]\n );\n return [volume, setVolume];\n}\nfunction usePreload(urls) {\n const manager = useAudio();\n const urlsKey = JSON.stringify(urls);\n const [state, setState] = _react.useState.call(void 0, { status: \"idle\", error: null });\n _react.useEffect.call(void 0, () => {\n const list = JSON.parse(urlsKey);\n if (list.length === 0) {\n setState({ status: \"idle\", error: null });\n return;\n }\n let cancelled = false;\n setState({ status: \"loading\", error: null });\n manager.preloadUrls(list).then(\n () => {\n if (!cancelled) setState({ status: \"loaded\", error: null });\n },\n (error) => {\n if (!cancelled) setState({ status: \"error\", error });\n }\n );\n return () => {\n cancelled = true;\n };\n }, [manager, urlsKey]);\n return state;\n}\n\n\n\n\n\n\n\n\nexports.AudioManager = AudioManager; exports.AudioManagerProvider = AudioManagerProvider; exports.default = AudioManager; exports.useAudio = useAudio; exports.useAudioEvent = useAudioEvent; exports.useGlobalVolume = useGlobalVolume; exports.usePreload = usePreload;\n","import { Howl, Howler } from 'howler';\nimport type {\n AudioManagerOptions,\n PlayOptions,\n PlayUrlOptions,\n AudioEventType,\n AudioEventPayload,\n EventSubscription,\n SoundResourceMap\n} from './types';\n\nexport class AudioManager<K extends string | number = string> {\n private effectCache = new Map<K, Howl>();\n private urlAudioCache = new Map<string, Howl>();\n private preloadPromises = new Map<string, Promise<void>>();\n private activeUrlHowl: Howl | null = null;\n private globalVolume = 1.0;\n private listeners = new Map<AudioEventType, Set<(payload: AudioEventPayload<K>) => void>>();\n\n private HowlConstructor: typeof Howl;\n private HowlerInstance: typeof Howler;\n\n constructor(\n options?: AudioManagerOptions,\n inject?: { HowlClass?: typeof Howl; HowlerObj?: typeof Howler }\n ) {\n this.HowlConstructor = inject?.HowlClass ?? Howl;\n this.HowlerInstance = inject?.HowlerObj ?? Howler;\n if (typeof options?.defaultVolume === 'number') {\n this.setGlobalVolume(options.defaultVolume);\n }\n }\n\n hasEffect(key: K): boolean {\n return this.effectCache.has(key);\n }\n\n loadEffect(key: K, url: string): void {\n if (this.effectCache.has(key)) {\n this.effectCache.get(key)!.unload();\n }\n const howl = new this.HowlConstructor({\n src: [url],\n preload: true\n });\n howl.on('load', () => {\n this.emit('load', { type: 'effect', key, url });\n });\n howl.on('loaderror', (_id: number, error: unknown) => {\n this.emit('error', { type: 'effect', key, url, error });\n });\n this.effectCache.set(key, howl);\n }\n\n loadEffects(map: SoundResourceMap<K>): void {\n Object.keys(map).forEach((key) => {\n const typedKey = (isNaN(Number(key)) ? key : Number(key)) as K;\n this.loadEffect(typedKey, map[key as any]);\n });\n }\n\n playEffect(key: K, options?: PlayOptions): number | undefined {\n const howl = this.effectCache.get(key);\n if (!howl) {\n console.warn(`[AudioManager] Effect not found for key: ${String(key)}.`);\n return undefined;\n }\n\n if (howl.playing()) {\n howl.stop();\n }\n\n if (typeof options?.volume === 'number') {\n howl.volume(options.volume);\n }\n\n // Clear handlers from previous plays to avoid stale/duplicate callbacks.\n howl.off('play');\n howl.off('end');\n howl.off('stop');\n howl.off('playerror');\n\n howl.once('play', (soundId: number) => {\n options?.onStart?.(soundId);\n this.emit('play', { type: 'effect', key, soundId });\n });\n\n howl.once('end', (soundId: number) => {\n if (typeof options?.volume === 'number') {\n howl.volume(1);\n }\n options?.onEnd?.(soundId);\n this.emit('end', { type: 'effect', key, soundId });\n });\n\n howl.once('stop', (soundId: number) => {\n if (typeof options?.volume === 'number') {\n howl.volume(1);\n }\n options?.onStop?.(soundId);\n this.emit('stop', { type: 'effect', key, soundId });\n });\n\n howl.once('playerror', (soundId: number, error: unknown) => {\n options?.onError?.(soundId, error);\n this.emit('error', { type: 'effect', key, soundId, error });\n });\n\n return howl.play();\n }\n\n stopEffect(key: K): void {\n const howl = this.effectCache.get(key);\n if (howl) {\n howl.stop();\n }\n }\n\n removeEffect(key: K): void {\n const howl = this.effectCache.get(key);\n if (howl) {\n howl.unload();\n this.effectCache.delete(key);\n }\n }\n\n preloadUrl(url: string): Promise<void> {\n const existing = this.urlAudioCache.get(url);\n if (existing && existing.state() === 'loaded') {\n return Promise.resolve();\n }\n\n const pending = this.preloadPromises.get(url);\n if (pending) {\n return pending;\n }\n\n // A howl in a terminal failed state (unloaded after error) must be replaced\n // so a fresh instance can retry the load.\n const howl = existing && existing.state() !== 'unloaded' ? existing : this.createUrlHowl(url);\n\n const promise = new Promise<void>((resolve, reject) => {\n howl.once('load', () => {\n resolve();\n });\n\n howl.once('loaderror', (_id: number, error: unknown) => {\n this.urlAudioCache.delete(url);\n reject(error);\n });\n });\n\n this.preloadPromises.set(url, promise);\n const settle = () => {\n if (this.preloadPromises.get(url) === promise) {\n this.preloadPromises.delete(url);\n }\n };\n promise.then(settle, settle);\n\n return promise;\n }\n\n preloadUrls(urls: string[]): Promise<void[]> {\n return Promise.all(urls.map((url) => this.preloadUrl(url)));\n }\n\n private createUrlHowl(url: string): Howl {\n const howl = new this.HowlConstructor({\n src: [url],\n preload: true\n });\n howl.on('load', () => {\n this.emit('load', { type: 'url', url });\n });\n howl.on('loaderror', (_id: number, error: unknown) => {\n this.urlAudioCache.delete(url);\n this.emit('error', { type: 'url', url, error });\n });\n this.urlAudioCache.set(url, howl);\n return howl;\n }\n\n playUrl(url: string, options?: PlayUrlOptions): number {\n const howl = this.urlAudioCache.get(url) || this.createUrlHowl(url);\n\n // Singleton mutex: stop currently active URL audio if singleton !== false\n const isSingleton = options?.singleton !== false;\n if (\n isSingleton &&\n this.activeUrlHowl &&\n this.activeUrlHowl !== howl &&\n this.activeUrlHowl.playing()\n ) {\n this.activeUrlHowl.stop();\n }\n\n // Overlap prevention on the same audio instance\n if (howl.playing()) {\n howl.stop();\n }\n\n if (options?.loop !== undefined) {\n howl.loop(options.loop);\n }\n\n if (typeof options?.volume === 'number') {\n howl.volume(options.volume);\n }\n\n if (isSingleton) {\n this.activeUrlHowl = howl;\n }\n\n // Clear handlers from previous plays to avoid stale/duplicate callbacks.\n howl.off('play');\n howl.off('end');\n howl.off('stop');\n howl.off('playerror');\n\n howl.once('play', (soundId: number) => {\n options?.onStart?.(soundId);\n this.emit('play', { type: 'url', url, soundId });\n });\n\n howl.once('end', (soundId: number) => {\n if (typeof options?.volume === 'number') {\n howl.volume(1);\n }\n options?.onEnd?.(soundId);\n this.emit('end', { type: 'url', url, soundId });\n if (this.activeUrlHowl === howl && !howl.loop()) {\n this.activeUrlHowl = null;\n }\n });\n\n howl.once('stop', (soundId: number) => {\n if (typeof options?.volume === 'number') {\n howl.volume(1);\n }\n options?.onStop?.(soundId);\n this.emit('stop', { type: 'url', url, soundId });\n if (this.activeUrlHowl === howl) {\n this.activeUrlHowl = null;\n }\n });\n\n howl.once('playerror', (soundId: number, error: unknown) => {\n options?.onError?.(soundId, error);\n this.emit('error', { type: 'url', url, soundId, error });\n if (this.activeUrlHowl === howl) {\n this.activeUrlHowl = null;\n }\n });\n\n return howl.play();\n }\n\n stopUrl(url: string): void {\n const howl = this.urlAudioCache.get(url);\n if (howl) {\n howl.stop();\n }\n }\n\n on(event: AudioEventType, handler: (payload: AudioEventPayload<K>) => void): EventSubscription {\n const set = this.listeners.get(event) ?? new Set<(payload: AudioEventPayload<K>) => void>();\n this.listeners.set(event, set);\n set.add(handler);\n return {\n destroy: () => {\n set.delete(handler);\n }\n };\n }\n\n protected emit(event: AudioEventType, payload: AudioEventPayload<K>): void {\n const set = this.listeners.get(event);\n if (set) {\n set.forEach((handler) => {\n try {\n handler(payload);\n } catch (err) {\n console.error(`[AudioManager] Error in event listener for ${event}:`, err);\n }\n });\n }\n }\n\n getGlobalVolume(): number {\n return this.globalVolume;\n }\n\n setGlobalVolume(volume: number): void {\n this.globalVolume = volume;\n this.HowlerInstance.volume(volume);\n }\n\n mute(muted: boolean): void {\n this.HowlerInstance.mute(muted);\n }\n\n stopAll(): void {\n this.HowlerInstance.stop();\n this.activeUrlHowl = null;\n }\n\n destroy(): void {\n this.effectCache.forEach((howl) => howl.unload());\n this.urlAudioCache.forEach((howl) => howl.unload());\n this.effectCache.clear();\n this.urlAudioCache.clear();\n this.preloadPromises.clear();\n this.listeners.clear();\n this.activeUrlHowl = null;\n }\n}\n","import { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { AudioManager } from './manager';\nimport type { AudioEventType, AudioEventPayload } from './types';\n\nconst AudioManagerContext = createContext<AudioManager<any> | null>(null);\n\nexport interface AudioManagerProviderProps<K extends string | number = string> {\n manager: AudioManager<K>;\n children?: ReactNode;\n}\n\nexport function AudioManagerProvider<K extends string | number = string>({\n manager,\n children\n}: AudioManagerProviderProps<K>) {\n return (\n <AudioManagerContext.Provider value={manager}>\n {children}\n </AudioManagerContext.Provider>\n );\n}\n\nexport function useAudio<K extends string | number = string>(): AudioManager<K> {\n const manager = useContext(AudioManagerContext);\n if (!manager) {\n throw new Error('useAudio must be used within an <AudioManagerProvider>.');\n }\n return manager as unknown as AudioManager<K>;\n}\n\nexport function useAudioEvent<K extends string | number = string>(\n event: AudioEventType,\n handler: (payload: AudioEventPayload<K>) => void\n): void {\n const manager = useAudio<K>();\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n const subscription = manager.on(event, (payload) => handlerRef.current(payload));\n return () => subscription.destroy();\n }, [manager, event]);\n}\n\nexport function useGlobalVolume(): [number, (volume: number) => void] {\n const manager = useAudio();\n const [volume, setVolumeState] = useState(() => manager.getGlobalVolume());\n\n const setVolume = useCallback(\n (next: number) => {\n manager.setGlobalVolume(next);\n setVolumeState(next);\n },\n [manager]\n );\n\n return [volume, setVolume];\n}\n\nexport interface PreloadState {\n status: 'idle' | 'loading' | 'loaded' | 'error';\n error: unknown;\n}\n\nexport function usePreload(urls: string[]): PreloadState {\n const manager = useAudio();\n const urlsKey = JSON.stringify(urls);\n const [state, setState] = useState<PreloadState>({ status: 'idle', error: null });\n\n useEffect(() => {\n const list: string[] = JSON.parse(urlsKey);\n if (list.length === 0) {\n setState({ status: 'idle', error: null });\n return;\n }\n\n let cancelled = false;\n setState({ status: 'loading', error: null });\n\n manager.preloadUrls(list).then(\n () => {\n if (!cancelled) setState({ status: 'loaded', error: null });\n },\n (error) => {\n if (!cancelled) setState({ status: 'error', error });\n }\n );\n\n return () => {\n cancelled = true;\n };\n }, [manager, urlsKey]);\n\n return state;\n}\n\n\n"]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Howl, Howler } from 'howler';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
interface AudioManagerOptions {
|
|
6
|
+
/** Default global volume (0.0 to 1.0), defaults to 1.0 */
|
|
7
|
+
defaultVolume?: number;
|
|
8
|
+
}
|
|
9
|
+
interface PlayOptions {
|
|
10
|
+
/** Play volume override (0.0 to 1.0) */
|
|
11
|
+
volume?: number;
|
|
12
|
+
/** Callback triggered when playback starts */
|
|
13
|
+
onStart?: (soundId: number) => void;
|
|
14
|
+
/** Callback triggered when playback ends */
|
|
15
|
+
onEnd?: (soundId: number) => void;
|
|
16
|
+
/** Callback triggered when playback encounters an error */
|
|
17
|
+
onError?: (soundId: number, error: unknown) => void;
|
|
18
|
+
/** Callback triggered when playback is manually stopped */
|
|
19
|
+
onStop?: (soundId: number) => void;
|
|
20
|
+
}
|
|
21
|
+
interface PlayUrlOptions extends PlayOptions {
|
|
22
|
+
/** Whether to loop the audio, defaults to false */
|
|
23
|
+
loop?: boolean;
|
|
24
|
+
/** Whether to stop currently playing URL audio, defaults to true */
|
|
25
|
+
singleton?: boolean;
|
|
26
|
+
}
|
|
27
|
+
type AudioEventType = 'play' | 'end' | 'stop' | 'pause' | 'error' | 'load';
|
|
28
|
+
interface AudioEventPayload<K = string> {
|
|
29
|
+
type: 'effect' | 'url';
|
|
30
|
+
key?: K;
|
|
31
|
+
url?: string;
|
|
32
|
+
soundId?: number;
|
|
33
|
+
error?: unknown;
|
|
34
|
+
}
|
|
35
|
+
interface EventSubscription {
|
|
36
|
+
destroy: () => void;
|
|
37
|
+
}
|
|
38
|
+
type SoundResourceMap<K extends string | number> = Record<K, string>;
|
|
39
|
+
|
|
40
|
+
declare class AudioManager<K extends string | number = string> {
|
|
41
|
+
private effectCache;
|
|
42
|
+
private urlAudioCache;
|
|
43
|
+
private preloadPromises;
|
|
44
|
+
private activeUrlHowl;
|
|
45
|
+
private globalVolume;
|
|
46
|
+
private listeners;
|
|
47
|
+
private HowlConstructor;
|
|
48
|
+
private HowlerInstance;
|
|
49
|
+
constructor(options?: AudioManagerOptions, inject?: {
|
|
50
|
+
HowlClass?: typeof Howl;
|
|
51
|
+
HowlerObj?: typeof Howler;
|
|
52
|
+
});
|
|
53
|
+
hasEffect(key: K): boolean;
|
|
54
|
+
loadEffect(key: K, url: string): void;
|
|
55
|
+
loadEffects(map: SoundResourceMap<K>): void;
|
|
56
|
+
playEffect(key: K, options?: PlayOptions): number | undefined;
|
|
57
|
+
stopEffect(key: K): void;
|
|
58
|
+
removeEffect(key: K): void;
|
|
59
|
+
preloadUrl(url: string): Promise<void>;
|
|
60
|
+
preloadUrls(urls: string[]): Promise<void[]>;
|
|
61
|
+
private createUrlHowl;
|
|
62
|
+
playUrl(url: string, options?: PlayUrlOptions): number;
|
|
63
|
+
stopUrl(url: string): void;
|
|
64
|
+
on(event: AudioEventType, handler: (payload: AudioEventPayload<K>) => void): EventSubscription;
|
|
65
|
+
protected emit(event: AudioEventType, payload: AudioEventPayload<K>): void;
|
|
66
|
+
getGlobalVolume(): number;
|
|
67
|
+
setGlobalVolume(volume: number): void;
|
|
68
|
+
mute(muted: boolean): void;
|
|
69
|
+
stopAll(): void;
|
|
70
|
+
destroy(): void;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface AudioManagerProviderProps<K extends string | number = string> {
|
|
74
|
+
manager: AudioManager<K>;
|
|
75
|
+
children?: ReactNode;
|
|
76
|
+
}
|
|
77
|
+
declare function AudioManagerProvider<K extends string | number = string>({ manager, children }: AudioManagerProviderProps<K>): react.JSX.Element;
|
|
78
|
+
declare function useAudio<K extends string | number = string>(): AudioManager<K>;
|
|
79
|
+
declare function useAudioEvent<K extends string | number = string>(event: AudioEventType, handler: (payload: AudioEventPayload<K>) => void): void;
|
|
80
|
+
declare function useGlobalVolume(): [number, (volume: number) => void];
|
|
81
|
+
interface PreloadState {
|
|
82
|
+
status: 'idle' | 'loading' | 'loaded' | 'error';
|
|
83
|
+
error: unknown;
|
|
84
|
+
}
|
|
85
|
+
declare function usePreload(urls: string[]): PreloadState;
|
|
86
|
+
|
|
87
|
+
export { type AudioEventPayload, type AudioEventType, AudioManager, type AudioManagerOptions, AudioManagerProvider, type AudioManagerProviderProps, type EventSubscription, type PlayOptions, type PlayUrlOptions, type PreloadState, type SoundResourceMap, AudioManager as default, useAudio, useAudioEvent, useGlobalVolume, usePreload };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Howl, Howler } from 'howler';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
interface AudioManagerOptions {
|
|
6
|
+
/** Default global volume (0.0 to 1.0), defaults to 1.0 */
|
|
7
|
+
defaultVolume?: number;
|
|
8
|
+
}
|
|
9
|
+
interface PlayOptions {
|
|
10
|
+
/** Play volume override (0.0 to 1.0) */
|
|
11
|
+
volume?: number;
|
|
12
|
+
/** Callback triggered when playback starts */
|
|
13
|
+
onStart?: (soundId: number) => void;
|
|
14
|
+
/** Callback triggered when playback ends */
|
|
15
|
+
onEnd?: (soundId: number) => void;
|
|
16
|
+
/** Callback triggered when playback encounters an error */
|
|
17
|
+
onError?: (soundId: number, error: unknown) => void;
|
|
18
|
+
/** Callback triggered when playback is manually stopped */
|
|
19
|
+
onStop?: (soundId: number) => void;
|
|
20
|
+
}
|
|
21
|
+
interface PlayUrlOptions extends PlayOptions {
|
|
22
|
+
/** Whether to loop the audio, defaults to false */
|
|
23
|
+
loop?: boolean;
|
|
24
|
+
/** Whether to stop currently playing URL audio, defaults to true */
|
|
25
|
+
singleton?: boolean;
|
|
26
|
+
}
|
|
27
|
+
type AudioEventType = 'play' | 'end' | 'stop' | 'pause' | 'error' | 'load';
|
|
28
|
+
interface AudioEventPayload<K = string> {
|
|
29
|
+
type: 'effect' | 'url';
|
|
30
|
+
key?: K;
|
|
31
|
+
url?: string;
|
|
32
|
+
soundId?: number;
|
|
33
|
+
error?: unknown;
|
|
34
|
+
}
|
|
35
|
+
interface EventSubscription {
|
|
36
|
+
destroy: () => void;
|
|
37
|
+
}
|
|
38
|
+
type SoundResourceMap<K extends string | number> = Record<K, string>;
|
|
39
|
+
|
|
40
|
+
declare class AudioManager<K extends string | number = string> {
|
|
41
|
+
private effectCache;
|
|
42
|
+
private urlAudioCache;
|
|
43
|
+
private preloadPromises;
|
|
44
|
+
private activeUrlHowl;
|
|
45
|
+
private globalVolume;
|
|
46
|
+
private listeners;
|
|
47
|
+
private HowlConstructor;
|
|
48
|
+
private HowlerInstance;
|
|
49
|
+
constructor(options?: AudioManagerOptions, inject?: {
|
|
50
|
+
HowlClass?: typeof Howl;
|
|
51
|
+
HowlerObj?: typeof Howler;
|
|
52
|
+
});
|
|
53
|
+
hasEffect(key: K): boolean;
|
|
54
|
+
loadEffect(key: K, url: string): void;
|
|
55
|
+
loadEffects(map: SoundResourceMap<K>): void;
|
|
56
|
+
playEffect(key: K, options?: PlayOptions): number | undefined;
|
|
57
|
+
stopEffect(key: K): void;
|
|
58
|
+
removeEffect(key: K): void;
|
|
59
|
+
preloadUrl(url: string): Promise<void>;
|
|
60
|
+
preloadUrls(urls: string[]): Promise<void[]>;
|
|
61
|
+
private createUrlHowl;
|
|
62
|
+
playUrl(url: string, options?: PlayUrlOptions): number;
|
|
63
|
+
stopUrl(url: string): void;
|
|
64
|
+
on(event: AudioEventType, handler: (payload: AudioEventPayload<K>) => void): EventSubscription;
|
|
65
|
+
protected emit(event: AudioEventType, payload: AudioEventPayload<K>): void;
|
|
66
|
+
getGlobalVolume(): number;
|
|
67
|
+
setGlobalVolume(volume: number): void;
|
|
68
|
+
mute(muted: boolean): void;
|
|
69
|
+
stopAll(): void;
|
|
70
|
+
destroy(): void;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface AudioManagerProviderProps<K extends string | number = string> {
|
|
74
|
+
manager: AudioManager<K>;
|
|
75
|
+
children?: ReactNode;
|
|
76
|
+
}
|
|
77
|
+
declare function AudioManagerProvider<K extends string | number = string>({ manager, children }: AudioManagerProviderProps<K>): react.JSX.Element;
|
|
78
|
+
declare function useAudio<K extends string | number = string>(): AudioManager<K>;
|
|
79
|
+
declare function useAudioEvent<K extends string | number = string>(event: AudioEventType, handler: (payload: AudioEventPayload<K>) => void): void;
|
|
80
|
+
declare function useGlobalVolume(): [number, (volume: number) => void];
|
|
81
|
+
interface PreloadState {
|
|
82
|
+
status: 'idle' | 'loading' | 'loaded' | 'error';
|
|
83
|
+
error: unknown;
|
|
84
|
+
}
|
|
85
|
+
declare function usePreload(urls: string[]): PreloadState;
|
|
86
|
+
|
|
87
|
+
// @ts-ignore
|
|
88
|
+
export = AudioManager;
|
|
89
|
+
export { type AudioEventPayload, type AudioEventType, AudioManager, type AudioManagerOptions, AudioManagerProvider, type AudioManagerProviderProps, type EventSubscription, type PlayOptions, type PlayUrlOptions, type PreloadState, type SoundResourceMap, useAudio, useAudioEvent, useGlobalVolume, usePreload };
|