1/**
2 * Solid context and provider for the Atom registry used by Effect Atom hooks.
3 * The registry stores atom values, schedules update work, and cleans up unused
4 * atoms. Sharing one registry through Solid context lets components and
5 * computations in the same owner tree read and write the same atom state.
6 *
7 * @since 4.0.0
8 */
9import type * as Atom from "effect/reactivity/Atom"
10import * as AtomRegistry from "effect/reactivity/AtomRegistry"
11import type { JSX } from "solid-js"
12import { createComponent, createContext, onCleanup } from "solid-js"
13
14/**
15 * Provides a Solid context that carries the `AtomRegistry` used by atom hooks in the
16 * current owner tree.
17 *
18 * **When to use**
19 *
20 * Use when you need to integrate lower-level Solid context APIs, such as custom
21 * providers or hooks, instead of using the default atom hook setup.
22 *
23 * **Details**
24 *
25 * When no provider is present, the context uses a standalone default registry.
26 *
27 * @see {@link RegistryProvider} for creating and providing a registry for a Solid subtree
28 *
29 * @category context
30 * @since 4.0.0
31 */
32export const RegistryContext = createContext<AtomRegistry.AtomRegistry>(AtomRegistry.make())
33
34/**
35 * Creates an `AtomRegistry` for a Solid subtree, optionally seeding initial atom
36 * values and scheduler settings, and disposes the registry when the owner is
37 * cleaned up.
38 *
39 * **When to use**
40 *
41 * Use to scope atom state, scheduling, and cleanup to a Solid subtree.
42 *
43 * **Details**
44 *
45 * The provider creates an `AtomRegistry` with `AtomRegistry.make`, forwards
46 * `initialValues`, `scheduleTask`, `timeoutResolution`, and
47 * `defaultIdleTTL`, and supplies the registry through `RegistryContext`.
48 *
49 * **Gotchas**
50 *
51 * Provider options are consumed when the registry is created; they are not
52 * reactive updates. A custom `scheduleTask` should return a cancellation
53 * function that is safe to call during Solid cleanup.
54 *
55 * @see {@link RegistryContext} for the context supplied by this provider
56 *
57 * @category context
58 * @since 4.0.0
59 */
60export const RegistryProvider = (options: {
61 readonly children?: JSX.Element | undefined
62 readonly initialValues?: Iterable<readonly [Atom.Atom<any>, any]> | undefined
63 readonly scheduleTask?: ((f: () => void) => () => void) | undefined
64 readonly timeoutResolution?: number | undefined
65 readonly defaultIdleTTL?: number | undefined
66}) => {
67 const registry = AtomRegistry.make({
68 scheduleTask: options.scheduleTask,
69 initialValues: options.initialValues,
70 timeoutResolution: options.timeoutResolution,
71 defaultIdleTTL: options.defaultIdleTTL
72 })
73 onCleanup(() => registry.dispose())
74 return createComponent(RegistryContext.Provider, {
75 value: registry,
76 get children() {
77 return options.children
78 }
79 })
80}