import { packedResourceManager as defaultSingleton } from "@suaveplan/packer-browser/singleton"; import type { MessageResolver } from "@suaveplan/types"; import { createContext, type ReactElement, type ReactNode, useContext, useMemo, } from "react"; import type { PackedResourceManager, PackedResourceProviderValue, } from "../../types/react-packer.types.js"; /** * React context that carries a `PackedResourceManager` (and optionally a * `MessageResolver`) down the tree to every `usePackedResource*` hook. * The context default is `null` — hooks then resolve the manager via * the documented singleton fallback so consumers who don't need DI get * a zero-config experience. */ const PackedResourceContext = createContext( null ); /** * Mount this provider once at the root of any React subtree that wants * to share a `PackedResourceManager` across hooks. Mount multiple * providers if different subtrees need different managers — child * providers shadow parents normally. */ export function PackedResourceProvider(props: { readonly value: PackedResourceProviderValue; readonly children?: ReactNode; }): ReactElement { // Memoise so child consumers don't re-render when the parent // re-renders without changing the manager identity. const value = useMemo( () => props.value, [props.value.manager, props.value.messageResolver, props.value] ); return ( {props.children} ); } /** * Resolve the active `PackedResourceManager`. Returns the provider's * manager when one is mounted; otherwise returns the module-singleton * exported by `@suaveplan/packer-browser/singleton`. */ export function usePackedResourceManager(): PackedResourceManager { const ctx = useContext(PackedResourceContext); if (ctx !== null) return ctx.manager; return defaultSingleton; } /** * Resolve the active `MessageResolver`, if any. Returns the * provider-supplied resolver when one is mounted; otherwise returns * `undefined` so the underlying error class falls through to its * default message-key behaviour. */ export function usePackedMessageResolver(): MessageResolver | undefined { const ctx = useContext(PackedResourceContext); return ctx?.messageResolver; }