import { createContext, useContext } from 'solid-js' import type { JSX, ParentProps } from 'solid-js' /** * Creates a typed Solid context for sharing a bundle of atoms and stores with a * subtree. * * The returned `StoreProvider` only transports the provided object through * Solid context. Consumers destructure the contextual atoms and stores, then * compose them with the existing hooks like {@link useSelector} and * {@link useAtom}. * * The object shape is preserved exactly, so keyed atoms and stores remain fully * typed when read back with `useStoreContext()`. * * @example * ```tsx * const { StoreProvider, useStoreContext } = createStoreContext<{ * countAtom: Atom * totalsStore: Store<{ count: number }> * }>() * * function CountButton() { * const { countAtom, totalsStore } = useStoreContext() * const count = useSelector(countAtom) * const total = useSelector(totalsStore, (state) => state.count) * * return ( * * ) * } * ``` * * @throws When `useStoreContext()` is called outside the matching `StoreProvider`. */ export function createStoreContext(): { StoreProvider: (props: ParentProps<{ value: TValue }>) => JSX.Element useStoreContext: () => TValue } { const Context = createContext() function StoreProvider(props: ParentProps<{ value: TValue }>) { return ( {props.children} ) } function useStoreContext(): TValue { const value = useContext(Context) if (value === undefined) { throw new Error('Missing StoreProvider for StoreContext') } return value } return { StoreProvider, useStoreContext, } }