@effect/atom-react 4.0.0-beta.7 → 4.0.0-beta.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,37 +1,34 @@
1
1
  import type * as Atom from "effect/unstable/reactivity/Atom";
2
2
  import * as React from "react";
3
3
  /**
4
- * @since 1.0.0
5
- * @category Type IDs
6
- *
7
4
  * Type identifier for ScopedAtom.
5
+ *
6
+ * @category type IDs
7
+ * @since 4.0.0
8
8
  */
9
9
  export type TypeId = "~@effect/atom-react/ScopedAtom";
10
10
  /**
11
- * @since 1.0.0
12
- * @category Type IDs
13
- *
14
11
  * Type identifier for ScopedAtom.
12
+ *
13
+ * @category type IDs
14
+ * @since 4.0.0
15
15
  */
16
16
  export declare const TypeId: TypeId;
17
17
  /**
18
- * @since 1.0.0
19
- * @category models
20
- *
21
18
  * Scoped Atom interface with a provider-backed instance.
22
19
  *
23
- * @example
20
+ * **Example** (Providing and reading a scoped atom)
21
+ *
24
22
  * ```ts
25
- * import * as Atom from "effect/unstable/reactivity/Atom"
23
+ * import * as AtomReact from "@effect/atom-react"
24
+ * import { Atom } from "effect/unstable/reactivity"
26
25
  * import * as React from "react"
27
- * import * as ScopedAtom from "@effect/atom-react/ScopedAtom"
28
- * import { useAtomValue } from "@effect/atom-react"
29
26
  *
30
- * const Counter = ScopedAtom.make(() => Atom.make(0))
27
+ * const Counter = AtomReact.make(() => Atom.make(0))
31
28
  *
32
29
  * function View() {
33
30
  * const atom = Counter.use()
34
- * const value = useAtomValue(atom)
31
+ * const value = AtomReact.useAtomValue(atom)
35
32
  * return React.createElement("div", null, value)
36
33
  * }
37
34
  *
@@ -39,11 +36,14 @@ export declare const TypeId: TypeId;
39
36
  * return React.createElement(Counter.Provider, null, React.createElement(View))
40
37
  * }
41
38
  * ```
39
+ *
40
+ * @category models
41
+ * @since 4.0.0
42
42
  */
43
43
  export interface ScopedAtom<A extends Atom.Atom<any>, Input = never> {
44
44
  readonly [TypeId]: TypeId;
45
45
  use(): A;
46
- Provider: Input extends never ? React.FC<{
46
+ Provider: [Input] extends [never] ? React.FC<{
47
47
  readonly children?: React.ReactNode | undefined;
48
48
  }> : React.FC<{
49
49
  readonly children?: React.ReactNode | undefined;
@@ -52,23 +52,20 @@ export interface ScopedAtom<A extends Atom.Atom<any>, Input = never> {
52
52
  Context: React.Context<A>;
53
53
  }
54
54
  /**
55
- * @since 1.0.0
56
- * @category constructors
57
- *
58
55
  * Creates a ScopedAtom from a factory function.
59
56
  *
60
- * @example
57
+ * **Example** (Creating a scoped atom with input)
58
+ *
61
59
  * ```ts
62
- * import * as Atom from "effect/unstable/reactivity/Atom"
60
+ * import * as AtomReact from "@effect/atom-react"
61
+ * import { Atom } from "effect/unstable/reactivity"
63
62
  * import * as React from "react"
64
- * import * as ScopedAtom from "@effect/atom-react/ScopedAtom"
65
- * import { useAtomValue } from "@effect/atom-react"
66
63
  *
67
- * const User = ScopedAtom.make((name: string) => Atom.make(name))
64
+ * const User = AtomReact.make((name: string) => Atom.make(name))
68
65
  *
69
66
  * function UserName() {
70
67
  * const atom = User.use()
71
- * const value = useAtomValue(atom)
68
+ * const value = AtomReact.useAtomValue(atom)
72
69
  * return React.createElement("span", null, value)
73
70
  * }
74
71
  *
@@ -80,6 +77,9 @@ export interface ScopedAtom<A extends Atom.Atom<any>, Input = never> {
80
77
  * )
81
78
  * }
82
79
  * ```
80
+ *
81
+ * @category constructors
82
+ * @since 4.0.0
83
83
  */
84
84
  export declare const make: <A extends Atom.Atom<any>, Input = never>(f: (() => A) | ((input: Input) => A)) => ScopedAtom<A, Input>;
85
85
  //# sourceMappingURL=ScopedAtom.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ScopedAtom.d.ts","sourceRoot":"","sources":["../src/ScopedAtom.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,IAAI,MAAM,iCAAiC,CAAA;AAC5D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,gCAAgC,CAAA;AAErD;;;;;GAKG;AACH,eAAO,MAAM,MAAM,EAAE,MAAyC,CAAA;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK;IACjE,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACzB,GAAG,IAAI,CAAC,CAAA;IACR,QAAQ,EAAE,KAAK,SAAS,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAA;KAAE,CAAC,GACzF,KAAK,CAAC,EAAE,CAAC;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAA;IACxF,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,EAC1D,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,CAAC,CAAC,KACnC,UAAU,CAAC,CAAC,EAAE,KAAK,CA6BrB,CAAA"}
1
+ {"version":3,"file":"ScopedAtom.d.ts","sourceRoot":"","sources":["../src/ScopedAtom.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,KAAK,IAAI,MAAM,iCAAiC,CAAA;AAC5D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,gCAAgC,CAAA;AAErD;;;;;GAKG;AACH,eAAO,MAAM,MAAM,EAAE,MAAyC,CAAA;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK;IACjE,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACzB,GAAG,IAAI,CAAC,CAAA;IACR,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAA;KAAE,CAAC,GAC7F,KAAK,CAAC,EAAE,CAAC;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAA;IACxF,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,EAC1D,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,CAAC,CAAC,KACnC,UAAU,CAAC,CAAC,EAAE,KAAK,CA6BrB,CAAA"}
@@ -1,34 +1,48 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * The `ScopedAtom` module provides a small React integration for creating atom
3
+ * instances that are scoped to a component subtree. A scoped atom bundles a
4
+ * React provider, context, and `use` accessor so each mounted provider owns its
5
+ * own atom instance instead of sharing a single module-level atom.
6
+ *
7
+ * Use `ScopedAtom` when an atom needs to be isolated per feature, route,
8
+ * component instance, test harness, or provider input. The provider may receive
9
+ * an initial `value` that is passed to the atom factory, making it useful for
10
+ * state that should be seeded from React props while still being consumed by the
11
+ * atom hooks in descendants.
12
+ *
13
+ * **Gotchas**
14
+ *
15
+ * - `use` must be called under the matching provider or it throws.
16
+ * - The provider creates the atom once for its lifetime; changing the provider
17
+ * `value` prop after mount does not recreate the atom.
18
+ *
19
+ * @since 4.0.0
3
20
  */
4
21
  "use client";
5
22
 
6
23
  import * as React from "react";
7
24
  /**
8
- * @since 1.0.0
9
- * @category Type IDs
10
- *
11
25
  * Type identifier for ScopedAtom.
26
+ *
27
+ * @category type IDs
28
+ * @since 4.0.0
12
29
  */
13
30
  export const TypeId = "~@effect/atom-react/ScopedAtom";
14
31
  /**
15
- * @since 1.0.0
16
- * @category constructors
17
- *
18
32
  * Creates a ScopedAtom from a factory function.
19
33
  *
20
- * @example
34
+ * **Example** (Creating a scoped atom with input)
35
+ *
21
36
  * ```ts
22
- * import * as Atom from "effect/unstable/reactivity/Atom"
37
+ * import * as AtomReact from "@effect/atom-react"
38
+ * import { Atom } from "effect/unstable/reactivity"
23
39
  * import * as React from "react"
24
- * import * as ScopedAtom from "@effect/atom-react/ScopedAtom"
25
- * import { useAtomValue } from "@effect/atom-react"
26
40
  *
27
- * const User = ScopedAtom.make((name: string) => Atom.make(name))
41
+ * const User = AtomReact.make((name: string) => Atom.make(name))
28
42
  *
29
43
  * function UserName() {
30
44
  * const atom = User.use()
31
- * const value = useAtomValue(atom)
45
+ * const value = AtomReact.useAtomValue(atom)
32
46
  * return React.createElement("span", null, value)
33
47
  * }
34
48
  *
@@ -40,6 +54,9 @@ export const TypeId = "~@effect/atom-react/ScopedAtom";
40
54
  * )
41
55
  * }
42
56
  * ```
57
+ *
58
+ * @category constructors
59
+ * @since 4.0.0
43
60
  */
44
61
  export const make = f => {
45
62
  const Context = React.createContext(undefined);
@@ -1 +1 @@
1
- {"version":3,"file":"ScopedAtom.js","names":["React","TypeId","make","f","Context","createContext","undefined","use","atom","useContext","Error","Provider","props","useRef","current","value","createElement","children"],"sources":["../src/ScopedAtom.ts"],"sourcesContent":[null],"mappings":"AAAA;;;AAGA,YAAY;;AAGZ,OAAO,KAAKA,KAAK,MAAM,OAAO;AAU9B;;;;;;AAMA,OAAO,MAAMC,MAAM,GAAW,gCAAgC;AAoC9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,OAAO,MAAMC,IAAI,GACfC,CAAoC,IACZ;EACxB,MAAMC,OAAO,GAAGJ,KAAK,CAACK,aAAa,CAAIC,SAAyB,CAAC;EAEjE,MAAMC,GAAG,GAAGA,CAAA,KAAQ;IAClB,MAAMC,IAAI,GAAGR,KAAK,CAACS,UAAU,CAACL,OAAO,CAAC;IACtC,IAAII,IAAI,KAAKF,SAAS,EAAE;MACtB,MAAM,IAAII,KAAK,CAAC,yCAAyC,CAAC;IAC5D;IACA,OAAOF,IAAI;EACb,CAAC;EAED,MAAMG,QAAQ,GAA2FC,KAAK,IAAI;IAChH,MAAMJ,IAAI,GAAGR,KAAK,CAACa,MAAM,CAAW,IAAI,CAAC;IACzC,IAAIL,IAAI,CAACM,OAAO,KAAK,IAAI,EAAE;MACzB,IAAI,OAAO,IAAIF,KAAK,EAAE;QACpBJ,IAAI,CAACM,OAAO,GAAIX,CAAyB,CAACS,KAAK,CAACG,KAAc,CAAC;MACjE,CAAC,MAAM;QACLP,IAAI,CAACM,OAAO,GAAIX,CAAa,EAAE;MACjC;IACF;IACA,OAAOH,KAAK,CAACgB,aAAa,CAACZ,OAAO,CAACO,QAAQ,EAAE;MAAEI,KAAK,EAAEP,IAAI,CAACM;IAAO,CAAE,EAAEF,KAAK,CAACK,QAAQ,CAAC;EACvF,CAAC;EAED,OAAO;IACL,CAAChB,MAAM,GAAGA,MAAM;IAChBM,GAAG;IACHI,QAAQ,EAAEA,QAAe;IACzBP;GACD;AACH,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"ScopedAtom.js","names":["React","TypeId","make","f","Context","createContext","undefined","use","atom","useContext","Error","Provider","props","useRef","current","value","createElement","children"],"sources":["../src/ScopedAtom.ts"],"sourcesContent":[null],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;AAoBA,YAAY;;AAGZ,OAAO,KAAKA,KAAK,MAAM,OAAO;AAU9B;;;;;;AAMA,OAAO,MAAMC,MAAM,GAAW,gCAAgC;AAoC9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,OAAO,MAAMC,IAAI,GACfC,CAAoC,IACZ;EACxB,MAAMC,OAAO,GAAGJ,KAAK,CAACK,aAAa,CAAIC,SAAyB,CAAC;EAEjE,MAAMC,GAAG,GAAGA,CAAA,KAAQ;IAClB,MAAMC,IAAI,GAAGR,KAAK,CAACS,UAAU,CAACL,OAAO,CAAC;IACtC,IAAII,IAAI,KAAKF,SAAS,EAAE;MACtB,MAAM,IAAII,KAAK,CAAC,yCAAyC,CAAC;IAC5D;IACA,OAAOF,IAAI;EACb,CAAC;EAED,MAAMG,QAAQ,GAA2FC,KAAK,IAAI;IAChH,MAAMJ,IAAI,GAAGR,KAAK,CAACa,MAAM,CAAW,IAAI,CAAC;IACzC,IAAIL,IAAI,CAACM,OAAO,KAAK,IAAI,EAAE;MACzB,IAAI,OAAO,IAAIF,KAAK,EAAE;QACpBJ,IAAI,CAACM,OAAO,GAAIX,CAAyB,CAACS,KAAK,CAACG,KAAc,CAAC;MACjE,CAAC,MAAM;QACLP,IAAI,CAACM,OAAO,GAAIX,CAAa,EAAE;MACjC;IACF;IACA,OAAOH,KAAK,CAACgB,aAAa,CAACZ,OAAO,CAACO,QAAQ,EAAE;MAAEI,KAAK,EAAEP,IAAI,CAACM;IAAO,CAAE,EAAEF,KAAK,CAACK,QAAQ,CAAC;EACvF,CAAC;EAED,OAAO;IACL,CAAChB,MAAM,GAAGA,MAAM;IAChBM,GAAG;IACHI,QAAQ,EAAEA,QAAe;IACzBP;GACD;AACH,CAAC","ignoreList":[]}
package/dist/index.d.ts CHANGED
@@ -1,20 +1,20 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * @since 4.0.0
3
3
  */
4
4
  /**
5
- * @since 1.0.0
5
+ * @since 4.0.0
6
6
  */
7
7
  export * from "./Hooks.ts";
8
8
  /**
9
- * @since 1.0.0
9
+ * @since 4.0.0
10
10
  */
11
11
  export * from "./RegistryContext.ts";
12
12
  /**
13
- * @since 1.0.0
13
+ * @since 4.0.0
14
14
  */
15
15
  export * from "./ReactHydration.ts";
16
16
  /**
17
- * @since 1.0.0
17
+ * @since 4.0.0
18
18
  */
19
19
  export * from "./ScopedAtom.ts";
20
20
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,20 +1,20 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * @since 4.0.0
3
3
  */
4
4
  /**
5
- * @since 1.0.0
5
+ * @since 4.0.0
6
6
  */
7
7
  export * from "./Hooks.js";
8
8
  /**
9
- * @since 1.0.0
9
+ * @since 4.0.0
10
10
  */
11
11
  export * from "./RegistryContext.js";
12
12
  /**
13
- * @since 1.0.0
13
+ * @since 4.0.0
14
14
  */
15
15
  export * from "./ReactHydration.js";
16
16
  /**
17
- * @since 1.0.0
17
+ * @since 4.0.0
18
18
  */
19
19
  export * from "./ScopedAtom.js";
20
20
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect/atom-react",
3
- "version": "4.0.0-beta.7",
3
+ "version": "4.0.0-beta.70",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "React bindings for the Effect Atom modules",
@@ -45,21 +45,21 @@
45
45
  "peerDependencies": {
46
46
  "react": "^19.2.4",
47
47
  "scheduler": "*",
48
- "effect": "^4.0.0-beta.7"
48
+ "effect": "^4.0.0-beta.70"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@testing-library/dom": "^10.4.1",
52
52
  "@testing-library/jest-dom": "^6.9.1",
53
- "@testing-library/react": "^16.3.0",
54
- "@types/react": "^19.2.2",
53
+ "@testing-library/react": "^16.3.2",
54
+ "@types/react": "^19.2.14",
55
55
  "@types/react-dom": "^19.2.2",
56
56
  "@types/scheduler": "^0.26.0",
57
- "jsdom": "^27.1.0",
58
- "react": "19.2.3",
59
- "react-dom": "19.2.3",
60
- "react-error-boundary": "^6.0.0",
57
+ "jsdom": "^29.1.1",
58
+ "react": "19.2.6",
59
+ "react-dom": "19.2.6",
60
+ "react-error-boundary": "^6.1.1",
61
61
  "scheduler": "^0.27.0",
62
- "effect": "^4.0.0-beta.7"
62
+ "effect": "^4.0.0-beta.70"
63
63
  },
64
64
  "scripts": {
65
65
  "build": "tsc -b tsconfig.json && pnpm babel",
package/src/Hooks.ts CHANGED
@@ -1,5 +1,23 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * React hooks for reading, writing, mounting, refreshing, and subscribing to
3
+ * Effect atoms from the registry provided by `RegistryContext`.
4
+ *
5
+ * **Common tasks**
6
+ *
7
+ * - Read atom values in React components with {@link useAtomValue}
8
+ * - Read and write writable atoms with {@link useAtom}
9
+ * - Write without subscribing to the value with {@link useAtomSet}
10
+ * - Seed registry-local initial values with {@link useAtomInitialValues}
11
+ * - Integrate `AsyncResult` atoms with React Suspense through {@link useAtomSuspense}
12
+ * - Subscribe to atom changes or derive stable `AtomRef` properties
13
+ *
14
+ * **Gotchas**
15
+ *
16
+ * - Hooks use the current `RegistryContext`, so each provider has an independent atom registry
17
+ * - Writable atoms are mounted by the write-oriented hooks before updates are sent
18
+ * - Suspense support throws promises for initial or waiting `AsyncResult` values and defects for failures unless `includeFailure` is enabled
19
+ *
20
+ * @since 4.0.0
3
21
  */
4
22
  "use client"
5
23
 
@@ -55,8 +73,15 @@ function useStore<A>(registry: AtomRegistry.AtomRegistry, atom: Atom.Atom<A>): A
55
73
  const initialValuesSet = new WeakMap<AtomRegistry.AtomRegistry, WeakSet<Atom.Atom<any>>>()
56
74
 
57
75
  /**
58
- * @since 1.0.0
76
+ * Seeds initial atom values in the current React atom registry.
77
+ *
78
+ * **Details**
79
+ *
80
+ * Each atom is initialized at most once for a given registry, so subsequent
81
+ * renders do not overwrite values that have already been established.
82
+ *
59
83
  * @category hooks
84
+ * @since 4.0.0
60
85
  */
61
86
  export const useAtomInitialValues = (initialValues: Iterable<readonly [Atom.Atom<any>, any]>): void => {
62
87
  const registry = React.useContext(RegistryContext)
@@ -74,18 +99,27 @@ export const useAtomInitialValues = (initialValues: Iterable<readonly [Atom.Atom
74
99
  }
75
100
 
76
101
  /**
77
- * @since 1.0.0
102
+ * Subscribes to an atom in the current React registry and returns its current
103
+ * value, optionally mapped through a selector.
104
+ *
78
105
  * @category hooks
106
+ * @since 4.0.0
79
107
  */
80
108
  export const useAtomValue: {
81
109
  /**
82
- * @since 1.0.0
110
+ * Subscribes to an atom in the current React registry and returns its current
111
+ * value, optionally mapped through a selector.
112
+ *
83
113
  * @category hooks
114
+ * @since 4.0.0
84
115
  */
85
116
  <A>(atom: Atom.Atom<A>): A
86
117
  /**
87
- * @since 1.0.0
118
+ * Subscribes to an atom in the current React registry and returns its current
119
+ * value, optionally mapped through a selector.
120
+ *
88
121
  * @category hooks
122
+ * @since 4.0.0
89
123
  */
90
124
  <A, B>(atom: Atom.Atom<A>, f: (_: A) => B): B
91
125
  } = <A>(atom: Atom.Atom<A>, f?: (_: A) => A): A => {
@@ -137,8 +171,11 @@ const flattenExit = <A, E>(exit: Exit.Exit<A, E>): A => {
137
171
  }
138
172
 
139
173
  /**
140
- * @since 1.0.0
174
+ * Mounts an atom in the current React registry for the lifetime of the
175
+ * component.
176
+ *
141
177
  * @category hooks
178
+ * @since 4.0.0
142
179
  */
143
180
  export const useAtomMount = <A>(atom: Atom.Atom<A>): void => {
144
181
  const registry = React.useContext(RegistryContext)
@@ -146,8 +183,10 @@ export const useAtomMount = <A>(atom: Atom.Atom<A>): void => {
146
183
  }
147
184
 
148
185
  /**
149
- * @since 1.0.0
186
+ * Mounts a writable atom and returns a setter without subscribing to its value.
187
+ *
150
188
  * @category hooks
189
+ * @since 4.0.0
151
190
  */
152
191
  export const useAtomSet = <
153
192
  R,
@@ -172,8 +211,11 @@ export const useAtomSet = <
172
211
  }
173
212
 
174
213
  /**
175
- * @since 1.0.0
214
+ * Mounts an atom and returns a callback that refreshes it in the current React
215
+ * registry.
216
+ *
176
217
  * @category hooks
218
+ * @since 4.0.0
177
219
  */
178
220
  export const useAtomRefresh = <A>(atom: Atom.Atom<A>): () => void => {
179
221
  const registry = React.useContext(RegistryContext)
@@ -184,8 +226,11 @@ export const useAtomRefresh = <A>(atom: Atom.Atom<A>): () => void => {
184
226
  }
185
227
 
186
228
  /**
187
- * @since 1.0.0
229
+ * Subscribes to a writable atom and returns its current value together with a
230
+ * setter for updating it.
231
+ *
188
232
  * @category hooks
233
+ * @since 4.0.0
189
234
  */
190
235
  export const useAtom = <R, W, const Mode extends "value" | "promise" | "promiseExit" = never>(
191
236
  atom: Atom.Writable<R, W>,
@@ -251,8 +296,11 @@ function atomResultOrSuspend<A, E>(
251
296
  }
252
297
 
253
298
  /**
254
- * @since 1.0.0
299
+ * Reads an `AsyncResult` atom through React Suspense, suspending while the
300
+ * result is initial or configured as waiting.
301
+ *
255
302
  * @category hooks
303
+ * @since 4.0.0
256
304
  */
257
305
  export const useAtomSuspense = <A, E, const IncludeFailure extends boolean = false>(
258
306
  atom: Atom.Atom<AsyncResult.AsyncResult<A, E>>,
@@ -270,8 +318,11 @@ export const useAtomSuspense = <A, E, const IncludeFailure extends boolean = fal
270
318
  }
271
319
 
272
320
  /**
273
- * @since 1.0.0
321
+ * Subscribes a callback to an atom in the current React registry for the
322
+ * component lifetime.
323
+ *
274
324
  * @category hooks
325
+ * @since 4.0.0
275
326
  */
276
327
  export const useAtomSubscribe = <A>(
277
328
  atom: Atom.Atom<A>,
@@ -286,8 +337,10 @@ export const useAtomSubscribe = <A>(
286
337
  }
287
338
 
288
339
  /**
289
- * @since 1.0.0
340
+ * Subscribes to an atom ref and returns its latest value.
341
+ *
290
342
  * @category hooks
343
+ * @since 4.0.0
291
344
  */
292
345
  export const useAtomRef = <A>(ref: AtomRef.ReadonlyRef<A>): A => {
293
346
  const [, setValue] = React.useState(ref.value)
@@ -296,15 +349,20 @@ export const useAtomRef = <A>(ref: AtomRef.ReadonlyRef<A>): A => {
296
349
  }
297
350
 
298
351
  /**
299
- * @since 1.0.0
352
+ * Returns a memoized atom ref for a property of another atom ref.
353
+ *
300
354
  * @category hooks
355
+ * @since 4.0.0
301
356
  */
302
357
  export const useAtomRefProp = <A, K extends keyof A>(ref: AtomRef.AtomRef<A>, prop: K): AtomRef.AtomRef<A[K]> =>
303
358
  React.useMemo(() => ref.prop(prop), [ref, prop])
304
359
 
305
360
  /**
306
- * @since 1.0.0
361
+ * Subscribes to a property ref derived from an atom ref and returns its current
362
+ * value.
363
+ *
307
364
  * @category hooks
365
+ * @since 4.0.0
308
366
  */
309
367
  export const useAtomRefPropValue = <A, K extends keyof A>(ref: AtomRef.AtomRef<A>, prop: K): A[K] =>
310
368
  useAtomRef(useAtomRefProp(ref, prop))
@@ -1,5 +1,26 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * React helpers for hydrating Atom registry state that was serialized on the
3
+ * server or produced by a previous render. This module exposes
4
+ * {@link HydrationBoundary}, a client component that receives dehydrated Atom
5
+ * values and applies them to the nearest {@link RegistryContext} before
6
+ * rendering children when it is safe to do so.
7
+ *
8
+ * **Common use cases**
9
+ *
10
+ * - Reusing Atom values that were collected during server rendering
11
+ * - Restoring client-side Atom state around a routed subtree
12
+ * - Keeping Atom-backed React trees consistent during hydration and transitions
13
+ *
14
+ * **React gotchas**
15
+ *
16
+ * - New Atom values can be hydrated during render so children see them
17
+ * immediately.
18
+ * - Existing Atom values are queued until after commit to avoid updating the
19
+ * current UI with transition data that might later be discarded.
20
+ * - Hydration is idempotent, so repeated or older dehydrated values are safe to
21
+ * pass through the boundary.
22
+ *
23
+ * @since 4.0.0
3
24
  */
4
25
  "use client"
5
26
  import * as Hydration from "effect/unstable/reactivity/Hydration"
@@ -7,8 +28,11 @@ import * as React from "react"
7
28
  import { RegistryContext } from "./RegistryContext.ts"
8
29
 
9
30
  /**
10
- * @since 1.0.0
31
+ * Props for a boundary that applies dehydrated Atom values to the nearest
32
+ * {@link RegistryContext} while rendering its children.
33
+ *
11
34
  * @category components
35
+ * @since 4.0.0
12
36
  */
13
37
  export interface HydrationBoundaryProps {
14
38
  state?: Iterable<Hydration.DehydratedAtom>
@@ -16,8 +40,17 @@ export interface HydrationBoundaryProps {
16
40
  }
17
41
 
18
42
  /**
19
- * @since 1.0.0
43
+ * Hydrates dehydrated Atom values into the current Atom registry for a React
44
+ * subtree.
45
+ *
46
+ * **Details**
47
+ *
48
+ * New Atom values are hydrated during render so descendants can read them
49
+ * immediately, while values for existing Atoms are deferred until after commit
50
+ * so transition data does not update the current UI before React accepts it.
51
+ *
20
52
  * @category components
53
+ * @since 4.0.0
21
54
  */
22
55
  export const HydrationBoundary: React.FC<HydrationBoundaryProps> = ({
23
56
  children,
@@ -1,5 +1,27 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * The `RegistryContext` module provides the React context used by Effect Atom
3
+ * hooks to share an `AtomRegistry` across a component tree. The registry owns
4
+ * atom state, scheduling, and idle cleanup, so components that read or write
5
+ * atoms can coordinate through the same runtime instead of each creating an
6
+ * isolated registry.
7
+ *
8
+ * **Common tasks**
9
+ *
10
+ * - Use {@link RegistryProvider} to scope atom state to a React subtree
11
+ * - Seed atoms for tests, stories, or server-provided data with `initialValues`
12
+ * - Override scheduling or idle timing for custom rendering environments
13
+ * - Read {@link RegistryContext} when integrating lower-level atom APIs
14
+ *
15
+ * **Gotchas**
16
+ *
17
+ * - This is a client module because it depends on React runtime hooks and the
18
+ * scheduler package
19
+ * - A provider keeps the registry stable across renders and disposes it shortly
20
+ * after unmount, allowing React remounts to reuse the same registry
21
+ * - Overriding `scheduleTask` changes when atom work is flushed, so it should
22
+ * return a cancellation function compatible with React unmounts
23
+ *
24
+ * @since 4.0.0
3
25
  */
4
26
  "use client"
5
27
 
@@ -9,8 +31,11 @@ import * as React from "react"
9
31
  import * as Scheduler from "scheduler"
10
32
 
11
33
  /**
12
- * @since 1.0.0
34
+ * Schedules Atom registry work with React's scheduler at low priority and
35
+ * returns a cancellation function for the scheduled task.
36
+ *
13
37
  * @category context
38
+ * @since 4.0.0
14
39
  */
15
40
  export function scheduleTask(f: () => void): () => void {
16
41
  const node = Scheduler.unstable_scheduleCallback(Scheduler.unstable_LowPriority, f)
@@ -18,8 +43,12 @@ export function scheduleTask(f: () => void): () => void {
18
43
  }
19
44
 
20
45
  /**
21
- * @since 1.0.0
46
+ * React context that supplies the `AtomRegistry` used by Atom hooks and
47
+ * hydration helpers, defaulting to a standalone registry when no provider is
48
+ * present.
49
+ *
22
50
  * @category context
51
+ * @since 4.0.0
23
52
  */
24
53
  export const RegistryContext = React.createContext<AtomRegistry.AtomRegistry>(AtomRegistry.make({
25
54
  scheduleTask,
@@ -27,8 +56,11 @@ export const RegistryContext = React.createContext<AtomRegistry.AtomRegistry>(At
27
56
  }))
28
57
 
29
58
  /**
30
- * @since 1.0.0
59
+ * Provides a stable `AtomRegistry` to a React subtree, optionally seeding
60
+ * initial atom values and overriding registry scheduling or idle settings.
61
+ *
31
62
  * @category context
63
+ * @since 4.0.0
32
64
  */
33
65
  export const RegistryProvider = (options: {
34
66
  readonly children?: React.ReactNode | undefined