Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
import { useContext } from "react";
import {
REACT_AUDIO_CODES,
ReactAudioError,
} from "../error-codes/error-codes.js";
import {
type AudioContextValue,
AudioReactContext,
type ProviderState,
} from "../provider/audio-context.js";
/**
* Internal helper: returns the resolved `ProviderState`, throwing
* `REACT_AUDIO.NO_PROVIDER` if rendered outside `<AudioProvider>`
* and `REACT_AUDIO.PROVIDER_PENDING` if the engine has not yet
* finished its async init.
*
* Implementation note: `useContext` is the only React hook called by
* this helper, so any downstream hook that uses it can register its
* own `useCallback`/`useMemo`/`useSyncExternalStore` hooks
* unconditionally without violating the Rules of Hooks. The throws
* happen *after* the context read, so the hook count is the same
* across the pending → ready transition.
*/
export function useProviderStateOrThrow(): ProviderState {
const ctx = useContext(AudioReactContext);
if (ctx === null) {
throw new ReactAudioError(
REACT_AUDIO_CODES.NO_PROVIDER,
"react-audio.no-provider"
);
}
if (ctx.state === null) {
throw new ReactAudioError(
REACT_AUDIO_CODES.PROVIDER_PENDING,
"react-audio.provider-pending",
{ context: { engineState: ctx.engineState } }
);
}
return ctx.state;
}
/**
* Internal helper: returns the raw context value (without throwing
* on pending), throwing `REACT_AUDIO.NO_PROVIDER` if the consumer
* is outside `<AudioProvider>`. Used by `useEngineState`.
*/
export function useAudioContextOrThrow(): AudioContextValue {
const ctx = useContext(AudioReactContext);
if (ctx === null) {
throw new ReactAudioError(
REACT_AUDIO_CODES.NO_PROVIDER,
"react-audio.no-provider"
);
}
return ctx;
}