{"version":3,"sources":["../src/index.ts","../src/AudioPlayerProvider.tsx","../src/useAudioPlayer.ts","../src/howlCache.ts","../src/HowlStore.ts"],"sourcesContent":["export * from \"./AudioPlayerProvider\"\nexport * from \"./useAudioPlayer\"\nexport * from \"./types\"\n","import { type ComponentProps, createContext, useContext } from \"react\"\nimport { type AudioPlayer, useAudioPlayer } from \"./useAudioPlayer\"\n\nexport const context = createContext<AudioPlayer | null>(null)\n\nexport const useAudioPlayerContext = () => {\n    const ctx = useContext(context)\n    if (ctx === null) {\n        throw new Error(\n            \"useAudioPlayerContext must be used within an AudioPlayerProvider\"\n        )\n    }\n\n    return ctx\n}\n\ntype Props = Omit<ComponentProps<typeof context.Provider>, \"value\">\n\nexport function AudioPlayerProvider({ children }: Props) {\n    const player = useAudioPlayer()\n\n    return <context.Provider value={player}>{children}</context.Provider>\n}\n","import { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\"\nimport type { Howl } from \"howler\"\n\nimport { type Snapshot, HowlStore, defaultState } from \"./HowlStore\"\nimport type { AudioControls, AudioLoadOptions } from \"./types\"\n\nexport type AudioPlayer = AudioControls &\n    Snapshot & {\n        /** A reference to the underlying Howl object.\n         * Use as an escape hatch for behavior not provided by useAudioPlayer. Please refer to Howler [documentation](https://github.com/goldfire/howler.js#documentation)\n         * Manipulating the audio directly through the Howl may cause state to desynchronize\n         * */\n        player: Howl | null\n        src: string | null\n        /** A way to explicitly load an audio resource */\n        load: (...args: [string, AudioLoadOptions | undefined]) => void\n        /** Removes event listeners, resets state and unloads the internal Howl object */\n        cleanup: () => void\n    }\n\nexport function useAudioPlayer(\n    src: string,\n    options?: AudioLoadOptions\n): Omit<AudioPlayer, \"load\">\nexport function useAudioPlayer(): AudioPlayer\n\n/**\n * @param {string} src - The src path of the audio resource. Changing this will cause a new sound to immediately load\n * @param {AudioLoadOptions} options - Options for the loaded audio including initial properties and configuration. These can later be changed through the API.\n * @return {AudioPlayer} The audio player instance with methods for controlling playback and state.\n */\nexport function useAudioPlayer(src?: string, options?: AudioLoadOptions) {\n    const audioRef = useRef(new HowlStore())\n\n    // when the src param is used, load a new sound whenever the value changes\n    if (src && audioRef.current && src !== audioRef.current.src) {\n        audioRef.current.load({\n            src,\n            format: options?.format,\n            html5: options?.html5,\n            autoplay: options?.autoplay,\n            loop: options?.loop,\n            volume: options?.initialVolume,\n            mute: options?.initialMute,\n            rate: options?.initialRate,\n            // event callbacks\n            ...options\n        })\n    }\n\n    // need to bind functions back to the howl since they will be called from the context of React\n    const state = useSyncExternalStore(\n        audioRef.current.subscribe.bind(audioRef.current),\n        audioRef.current.getSnapshot.bind(audioRef.current),\n        () => defaultState\n    )\n\n    useEffect(() => {\n        // load the sound on mount if the src param is being used\n        // this is required for StrictMode when React may remount the hook\n        if (src && audioRef.current.src === null) {\n            audioRef.current.load({\n                src,\n                format: options?.format,\n                html5: options?.html5,\n                autoplay: options?.autoplay,\n                loop: options?.loop,\n                volume: options?.initialVolume,\n                mute: options?.initialMute,\n                rate: options?.initialRate,\n                // event callbacks\n                ...options\n            })\n        }\n\n        // cleans up the sound when hook unmounts\n        return () => {\n            if (audioRef.current) {\n                audioRef.current.destroy()\n            }\n        }\n    }, [])\n\n    const load: AudioPlayer[\"load\"] = useCallback((src, options) => {\n        audioRef.current.load({\n            src,\n            format: options?.format,\n            html5: options?.html5,\n            autoplay: options?.autoplay,\n            loop: options?.loop,\n            volume: options?.initialVolume,\n            mute: options?.initialMute,\n            rate: options?.initialRate,\n            // event callbacks\n            ...options\n        })\n    }, [])\n\n    return {\n        ...state,\n        player: audioRef.current.howl,\n        src: audioRef.current.src,\n        load: src ? undefined : load,\n        // AudioControls interface\n        play: audioRef.current.play.bind(audioRef.current),\n        pause: audioRef.current.pause.bind(audioRef.current),\n        togglePlayPause: audioRef.current.togglePlayPause.bind(\n            audioRef.current\n        ),\n        stop: audioRef.current.stop.bind(audioRef.current),\n        setVolume: audioRef.current.setVolume.bind(audioRef.current),\n        fade: audioRef.current.fade.bind(audioRef.current),\n        mute: audioRef.current.mute.bind(audioRef.current),\n        unmute: audioRef.current.unmute.bind(audioRef.current),\n        toggleMute: audioRef.current.toggleMute.bind(audioRef.current),\n        setRate: audioRef.current.setRate.bind(audioRef.current),\n        seek: audioRef.current.seek.bind(audioRef.current),\n        loopOn: audioRef.current.loopOn.bind(audioRef.current),\n        loopOff: audioRef.current.loopOff.bind(audioRef.current),\n        toggleLoop: audioRef.current.toggleLoop.bind(audioRef.current),\n        getPosition: audioRef.current.getPosition.bind(audioRef.current),\n        cleanup: audioRef.current.destroy.bind(audioRef.current)\n    }\n}\n","import { Howl, type HowlOptions as BaseHowlOptions } from \"howler\"\n\nexport type HowlOptions = BaseHowlOptions & {\n    src: string // override src property to only be a single string\n}\n\n/**\n * A cache that tracks all the instances of AudioSources created by the library\n * An instance is cached based on the src attribute it was created with\n *\n * This prevents duplicate instances of audio being created in certain edge cases\n * React StrictMode being one such scenario\n */\nclass HowlCache {\n    private _cache: Map<string, Howl> = new Map()\n\n    public create(options: HowlOptions): Howl {\n        const key = options.src\n        if (this._cache.has(key)) {\n            return this._cache.get(key)!\n        }\n\n        const howl = new Howl(options)\n        this._cache.set(key, howl)\n        return howl\n    }\n\n    public set(key: string, howl: Howl) {\n        this._cache.set(key, howl)\n    }\n\n    public get(key: string) {\n        return this._cache.get(key)\n    }\n\n    public clear(key: string) {\n        this._cache.delete(key)\n    }\n\n    public destroy(key: string) {\n        const howl = this.get(key)\n        if (howl) {\n            howl.unload()\n            this.clear(key)\n        }\n    }\n\n    public reset() {\n        this._cache.values().forEach((audio) => audio.unload())\n        this._cache.clear()\n    }\n}\n\nconst howlCache = new HowlCache()\n\nexport default howlCache\n","import type { Howl } from \"howler\"\nimport howlCache from \"./howlCache\"\nimport type { AudioControls } from \"./types\"\n\ntype Subscriber = () => void\n\ntype CreateOptions = Parameters<typeof howlCache.create>[0]\n\n/**\n * The state (snapshot) managed by the store\n * Mutations to the state will be broadcast to all subscribers.\n */\nexport type Snapshot = {\n    /** Indicates whether the audio is in an unloaded state. */\n    readonly isUnloaded: boolean\n    /** Indicates whether the audio is currently loading. */\n    readonly isLoading: boolean\n    /** Indicates whether the audio is loaded and ready to play. */\n    readonly isReady: boolean\n    /** Represents the total duration of the audio in seconds. 0 until a sound is loaded */\n    readonly duration: number\n    /** The playback rate of the audio. A value of 1 indicates normal playback speed. */\n    readonly rate: number\n    /** The volume level of the audio, typically between 0 (muted) and 1 (full volume). */\n    readonly volume: number\n    /** An error message, if an issue occurred with the audio. */\n    readonly error?: string\n    /** Indicates whether the audio is set to loop after reaching its end. */\n    readonly isLooping: boolean\n    /** Indicates whether the audio is currently paused. */\n    readonly isPaused: boolean\n    /** Indicates whether the audio is currently stopped. */\n    readonly isStopped: boolean\n    /** Indicates whether the audio is currently playing. */\n    readonly isPlaying: boolean\n    /** Indicates whether the audio is currently muted. */\n    readonly isMuted: boolean\n}\n\nexport const defaultState: Snapshot = {\n    isUnloaded: true,\n    isLoading: false,\n    isReady: false,\n    isLooping: false,\n    isPlaying: false,\n    isStopped: false,\n    isPaused: false,\n    duration: 0,\n    rate: 1,\n    volume: 1,\n    isMuted: false,\n    error: undefined\n}\n\nexport class HowlStore implements AudioControls {\n    public howl: Howl | null\n    public src: string | null\n\n    private subscriptions: Set<Subscriber>\n    private snapshot: Snapshot\n\n    /**\n     * Merges changes to the AudioSnapshot with the instnace variable and invokes all subscriber callbacks\n     */\n    private updateSnapshot(update: Partial<Snapshot>) {\n        this.snapshot = {\n            ...this.snapshot,\n            ...update\n        }\n\n        this.subscriptions.forEach((cb) => cb())\n    }\n\n    /**\n     * Initiates a snapshot update from a Howl instance\n     */\n    private updateSnapshotFromHowlState(howl: Howl) {\n        this.updateSnapshot({\n            ...this.getSnapshotFromHowl(howl)\n        })\n    }\n\n    /**\n     * Initializes the store with a new instance of a Howl\n     *   - creates a new Howl instance\n     *   - updates the AudioSnapshot instance\n     *   - sets up Howl event listeners to synchronize AudioSnapshot\n     */\n    private initHowl(options: CreateOptions) {\n        const newHowl = howlCache.create(options)\n        this.src = options.src\n        this.howl = newHowl\n\n        this.updateSnapshot({\n            ...this.getSnapshotFromHowl(newHowl),\n            // reset error on creation of new Howl\n            error: undefined\n        })\n\n        /*\n            Howler places the Howl in a \"loading\" state when HTML5 audio is seeked.\n            This is likely done in case the user agent needs to buffer more of the resource.\n            However, it may be a bug in Howler that the load event is not emitted following this state change.\n            This leaves this hook hanging in an \"isLoading\" state.\n            As a temporary (hopefully) workaround we can hijack the HTML5 Audio element from Howler\n             and trigger a state update once the Audio element has buffered.\n         */\n        if (newHowl._html5 && newHowl._sounds[0]?._node) {\n            const htmlAudioNode = newHowl._sounds[0]?._node\n            htmlAudioNode.addEventListener(\"canplaythrough\", () => {\n                this.updateSnapshotFromHowlState(newHowl)\n            })\n        }\n\n        // Howl event listeners and state mutations\n        newHowl.on(\"load\", () => this.updateSnapshotFromHowlState(newHowl))\n        newHowl.on(\"play\", () => this.updateSnapshotFromHowlState(newHowl))\n        newHowl.on(\"end\", () => this.updateSnapshotFromHowlState(newHowl))\n        newHowl.on(\"pause\", () => this.updateSnapshotFromHowlState(newHowl))\n        newHowl.on(\"stop\", () => this.updateSnapshotFromHowlState(newHowl))\n        newHowl.on(\"mute\", () => this.updateSnapshotFromHowlState(newHowl))\n        newHowl.on(\"volume\", () => this.updateSnapshotFromHowlState(newHowl))\n        newHowl.on(\"rate\", () => this.updateSnapshotFromHowlState(newHowl))\n        newHowl.on(\"seek\", () => this.updateSnapshotFromHowlState(newHowl))\n        newHowl.on(\"fade\", () => this.updateSnapshotFromHowlState(newHowl))\n\n        newHowl.on(\"loaderror\", (_: number, errorCode: unknown) => {\n            console.error(`Howl load error: ${errorCode}`)\n            this.updateSnapshotFromHowlState(newHowl)\n            this.updateSnapshot({\n                error: \"Failed to load audio source\"\n            })\n        })\n\n        newHowl.on(\"playerror\", (_: number, errorCode: unknown) => {\n            console.error(`Howl playback error: ${errorCode}`)\n            this.updateSnapshotFromHowlState(newHowl)\n            this.updateSnapshot({\n                error: \"Failed to play audio source\"\n            })\n        })\n    }\n\n    private getSnapshotFromHowl(howl: Howl): Snapshot {\n        if (howl.state() === \"unloaded\") {\n            return defaultState\n        }\n\n        const howlState = howl.state()\n        const isPlaying = howl.playing()\n        const muteReturn = howl.mute()\n        return {\n            isUnloaded: howlState === \"unloaded\",\n            isLoading: howlState === \"loading\",\n            isReady: howlState === \"loaded\",\n            isLooping: howl.loop(),\n            isPlaying,\n            isStopped: !isPlaying && howl.seek() === 0,\n            isPaused: !isPlaying && howl.seek() > 0,\n            duration: howl.duration(),\n            rate: howl.rate(),\n            volume: howl.volume(),\n            // the Howl#mute method sometimes returns the Howl (i.e. this) instead of the boolean\n            isMuted: typeof muteReturn === \"object\" ? false : muteReturn\n        }\n    }\n\n    constructor(options?: CreateOptions) {\n        this.howl = null\n        this.src = null\n\n        this.subscriptions = new Set()\n        this.snapshot = defaultState\n\n        if (options !== undefined) {\n            this.initHowl(options)\n        }\n    }\n\n    public load(options: CreateOptions) {\n        if (this.howl !== null) {\n            this.destroy()\n        }\n\n        this.initHowl(options)\n    }\n\n    public destroy() {\n        if (this.src && this.howl) {\n            // guarantees that event listeners can no longer be called\n            this.howl.off(\"load\")\n            this.howl.off(\"play\")\n            this.howl.off(\"end\")\n            this.howl.off(\"pause\")\n            this.howl.off(\"stop\")\n            this.howl.off(\"mute\")\n            this.howl.off(\"volume\")\n            this.howl.off(\"rate\")\n            this.howl.off(\"seek\")\n            this.howl.off(\"fade\")\n            this.howl.off(\"loaderror\")\n            this.howl.off(\"playerror\")\n\n            howlCache.destroy(this.src)\n\n            this.src = null\n            this.howl = null\n        }\n    }\n\n    public subscribe(cb: Subscriber) {\n        this.subscriptions.add(cb)\n        return () => this.subscriptions.delete(cb)\n    }\n\n    public getSnapshot() {\n        return this.snapshot\n    }\n\n    public play() {\n        if (this.howl) {\n            // prevents the Howl from spinning up a new \"Sound\" from the loaded audio resource\n            if (this.howl.playing()) {\n                return\n            }\n\n            this.howl.play()\n        }\n    }\n\n    public pause() {\n        if (this.howl) {\n            this.howl.pause()\n        }\n    }\n\n    public togglePlayPause() {\n        if (this.snapshot.isPlaying) {\n            this.pause()\n        } else {\n            this.play()\n        }\n    }\n\n    public stop() {\n        if (this.howl) {\n            this.howl.stop()\n        }\n    }\n\n    public setVolume(vol: number) {\n        if (this.howl) {\n            this.howl.volume(vol)\n        }\n    }\n\n    public setRate(rate: number) {\n        if (this.howl) {\n            this.howl.rate(rate)\n        }\n    }\n\n    public loopOn() {\n        if (this.howl) {\n            this.howl.loop(true)\n            // there is no loop even to listen for on Howl so calling the sync operation manually\n            this.updateSnapshotFromHowlState(this.howl)\n        }\n    }\n\n    public loopOff() {\n        if (this.howl) {\n            this.howl.loop(false)\n            // there is no loop even to listen for on Howl so calling the sync operation manually\n            this.updateSnapshotFromHowlState(this.howl)\n        }\n    }\n\n    public toggleLoop() {\n        if (this.snapshot.isLooping) {\n            this.loopOff()\n        } else {\n            this.loopOn()\n        }\n    }\n\n    public mute() {\n        if (this.howl) {\n            this.howl.mute(true)\n        }\n    }\n\n    public unmute() {\n        if (this.howl) {\n            this.howl.mute(false)\n        }\n    }\n\n    public toggleMute() {\n        if (this.snapshot.isMuted) {\n            this.unmute()\n        } else {\n            this.mute()\n        }\n    }\n\n    public seek(seconds: number) {\n        // if audio resource is being streamed then it's duration will be Infinity\n        if (this.howl && this.snapshot.duration !== Infinity) {\n            this.howl.seek(seconds)\n        }\n    }\n\n    public getPosition(): number {\n        if (this.howl) {\n            return this.howl.seek()\n        }\n\n        return 0\n    }\n\n    public fade(startVolume: number, endVolume: number, durationMs: number) {\n        if (this.howl) {\n            this.howl.fade(startVolume, endVolume, durationMs)\n        }\n    }\n}\n"],"mappings":"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","names":["index_exports","__export","AudioPlayerProvider","context","useAudioPlayer","useAudioPlayerContext","__toCommonJS","import_react","import_react","import_howler","HowlCache","options","key","howl","audio","howlCache","howlCache_default","defaultState","HowlStore","update","__spreadValues","cb","howl","options","_a","_b","newHowl","howlCache_default","__spreadProps","_","errorCode","howlState","isPlaying","muteReturn","vol","rate","seconds","startVolume","endVolume","durationMs","useAudioPlayer","src","options","audioRef","HowlStore","__spreadValues","state","defaultState","load","__spreadProps","import_jsx_runtime","context","useAudioPlayerContext","ctx","AudioPlayerProvider","children","player","useAudioPlayer"]}