@sigrea/react 0.3.0 → 0.4.0

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.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  - **Signal subscriptions.** `useSignal` subscribes to signals and computed values, triggering re-renders when they change.
6
6
  - **Computed subscriptions.** `useComputed` subscribes to computed values and memoizes them per component instance.
7
7
  - **Deep signal subscriptions.** `useDeepSignal` subscribes to deep signal objects and exposes them for direct mutation.
8
- - **Molecule lifecycles.** `useMolcule` mounts molecule factories and binds their lifecycles to React components.
8
+ - **Molecule lifecycles.** `useMolecule` mounts molecule factories and binds their lifecycles to React components.
9
9
 
10
10
  ## Table of Contents
11
11
 
@@ -18,8 +18,9 @@
18
18
  - [useSignal](#usesignal)
19
19
  - [useComputed](#usecomputed)
20
20
  - [useDeepSignal](#usedeepsignal)
21
- - [useMolcule](#usemolcule)
21
+ - [useMolecule](#usemolecule)
22
22
  - [Testing](#testing)
23
+ - [Handling Scope Cleanup Errors](#handling-scope-cleanup-errors)
23
24
  - [Development](#development)
24
25
  - [License](#license)
25
26
 
@@ -51,7 +52,7 @@ export function CounterLabel() {
51
52
 
52
53
  ```tsx
53
54
  import { molecule, signal } from "@sigrea/core";
54
- import { useMolcule, useSignal } from "@sigrea/react";
55
+ import { useMolecule, useSignal } from "@sigrea/react";
55
56
 
56
57
  const CounterMolecule = molecule((props: { initialCount: number }) => {
57
58
  const count = signal(props.initialCount);
@@ -68,7 +69,7 @@ const CounterMolecule = molecule((props: { initialCount: number }) => {
68
69
  });
69
70
 
70
71
  export function Counter(props: { initialCount: number }) {
71
- const counter = useMolcule(CounterMolcule, props);
72
+ const counter = useMolecule(CounterMolecule, props);
72
73
  const value = useSignal(counter.count);
73
74
 
74
75
  return (
@@ -132,10 +133,10 @@ function useDeepSignal<T extends object>(signal: DeepSignal<T>): T
132
133
 
133
134
  Exposes a deep signal object for direct mutation within the component. Updates to nested properties trigger re-renders, and the subscription is cleaned up when the component unmounts.
134
135
 
135
- ### useMolcule
136
+ ### useMolecule
136
137
 
137
138
  ```tsx
138
- function useMolcule<TProps, TReturn>(
139
+ function useMolecule<TProps, TReturn>(
139
140
  molecule: MoleculeFactory<TProps, TReturn>,
140
141
  props?: TProps
141
142
  ): TReturn
@@ -160,15 +161,54 @@ it("increments and displays the updated count", () => {
160
161
  });
161
162
  ```
162
163
 
164
+ ## Handling Scope Cleanup Errors
165
+
166
+ For global error handling configuration, see [@sigrea/core - Handling Scope Cleanup Errors](https://github.com/sigrea/core#handling-scope-cleanup-errors).
167
+
168
+ In React apps, configure the handler in your application entry point before rendering:
169
+
170
+ ```tsx
171
+ // index.tsx or main.tsx
172
+ import { setScopeCleanupErrorHandler } from "@sigrea/core";
173
+ import { createRoot } from "react-dom/client";
174
+ import { App } from "./App";
175
+
176
+ setScopeCleanupErrorHandler((error, context) => {
177
+ console.error(`Cleanup failed:`, error);
178
+
179
+ // Forward to monitoring service
180
+ if (typeof Sentry !== "undefined") {
181
+ Sentry.captureException(error, {
182
+ tags: { scopeId: context.scopeId, phase: context.phase },
183
+ });
184
+ }
185
+ });
186
+
187
+ createRoot(document.getElementById("root")!).render(<App />);
188
+ ```
189
+
163
190
  ## Development
164
191
 
165
- Development scripts prefer pnpm. npm or yarn work too, but pnpm keeps dependency resolution identical to CI.
192
+ This repo targets Node.js 20 or later.
193
+
194
+ If you use mise:
195
+
196
+ - `mise trust -y` — trust `mise.toml` (first run only).
197
+ - `mise run ci` — run CI-equivalent checks locally.
198
+ - `mise run notes` — preview release notes (optional).
199
+
200
+ You can also run pnpm scripts directly:
166
201
 
167
202
  - `pnpm install` — install dependencies.
168
203
  - `pnpm test` — run the Vitest suite once (no watch).
204
+ - `pnpm typecheck` — run TypeScript type checking.
205
+ - `pnpm test:coverage` — collect coverage.
169
206
  - `pnpm build` — compile via unbuild to produce dual CJS/ESM bundles.
207
+ - `pnpm cicheck` — run CI checks locally.
170
208
  - `pnpm dev` — launch the playground counter demo.
171
209
 
210
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for workflow details.
211
+
172
212
  ## License
173
213
 
174
214
  MIT — see [LICENSE](./LICENSE).
package/dist/index.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  const react = require('react');
4
4
  const core = require('@sigrea/core');
5
5
 
6
- function useMolcule(molecule, ...args) {
6
+ function useMolecule(molecule, ...args) {
7
7
  const props = args.length === 0 ? void 0 : args[0];
8
8
  const stateRef = react.useRef(
9
9
  void 0
@@ -29,7 +29,7 @@ function useMolcule(molecule, ...args) {
29
29
  const state = stateRef.current;
30
30
  if (state === void 0) {
31
31
  throw new Error(
32
- "useMolcule failed to mount the requested molecule instance."
32
+ "useMolecule failed to mount the requested molecule instance."
33
33
  );
34
34
  }
35
35
  const instance = state.instance;
@@ -106,6 +106,6 @@ function useDeepSignal(source) {
106
106
 
107
107
  exports.useComputed = useComputed;
108
108
  exports.useDeepSignal = useDeepSignal;
109
- exports.useMolcule = useMolcule;
109
+ exports.useMolecule = useMolecule;
110
110
  exports.useSignal = useSignal;
111
111
  exports.useSnapshot = useSnapshot;
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { MoleculeFactory, MoleculeArgs, MoleculeInstance, Signal, ReadonlySignal, Computed, DeepSignal, SnapshotHandler } from '@sigrea/core';
2
2
 
3
- declare function useMolcule<TReturn extends object, TProps = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
3
+ declare function useMolecule<TReturn extends object, TProps = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
4
4
 
5
5
  type ReadableSignal<T> = Signal<T> | ReadonlySignal<T>;
6
6
  declare function useSignal<T>(source: ReadableSignal<T>): T;
@@ -11,4 +11,4 @@ declare function useDeepSignal<T extends object>(source: DeepSignal<T>): T;
11
11
 
12
12
  declare function useSnapshot<T>(handler: SnapshotHandler<T>): T;
13
13
 
14
- export { useComputed, useDeepSignal, useMolcule, useSignal, useSnapshot };
14
+ export { useComputed, useDeepSignal, useMolecule, useSignal, useSnapshot };
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { MoleculeFactory, MoleculeArgs, MoleculeInstance, Signal, ReadonlySignal, Computed, DeepSignal, SnapshotHandler } from '@sigrea/core';
2
2
 
3
- declare function useMolcule<TReturn extends object, TProps = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
3
+ declare function useMolecule<TReturn extends object, TProps = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
4
4
 
5
5
  type ReadableSignal<T> = Signal<T> | ReadonlySignal<T>;
6
6
  declare function useSignal<T>(source: ReadableSignal<T>): T;
@@ -11,4 +11,4 @@ declare function useDeepSignal<T extends object>(source: DeepSignal<T>): T;
11
11
 
12
12
  declare function useSnapshot<T>(handler: SnapshotHandler<T>): T;
13
13
 
14
- export { useComputed, useDeepSignal, useMolcule, useSignal, useSnapshot };
14
+ export { useComputed, useDeepSignal, useMolecule, useSignal, useSnapshot };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { MoleculeFactory, MoleculeArgs, MoleculeInstance, Signal, ReadonlySignal, Computed, DeepSignal, SnapshotHandler } from '@sigrea/core';
2
2
 
3
- declare function useMolcule<TReturn extends object, TProps = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
3
+ declare function useMolecule<TReturn extends object, TProps = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
4
4
 
5
5
  type ReadableSignal<T> = Signal<T> | ReadonlySignal<T>;
6
6
  declare function useSignal<T>(source: ReadableSignal<T>): T;
@@ -11,4 +11,4 @@ declare function useDeepSignal<T extends object>(source: DeepSignal<T>): T;
11
11
 
12
12
  declare function useSnapshot<T>(handler: SnapshotHandler<T>): T;
13
13
 
14
- export { useComputed, useDeepSignal, useMolcule, useSignal, useSnapshot };
14
+ export { useComputed, useDeepSignal, useMolecule, useSignal, useSnapshot };
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { useRef, useEffect, useCallback, useSyncExternalStore, useMemo } from 'react';
2
2
  import { disposeMolecule, createSignalHandler, createComputedHandler, createDeepSignalHandler } from '@sigrea/core';
3
3
 
4
- function useMolcule(molecule, ...args) {
4
+ function useMolecule(molecule, ...args) {
5
5
  const props = args.length === 0 ? void 0 : args[0];
6
6
  const stateRef = useRef(
7
7
  void 0
@@ -27,7 +27,7 @@ function useMolcule(molecule, ...args) {
27
27
  const state = stateRef.current;
28
28
  if (state === void 0) {
29
29
  throw new Error(
30
- "useMolcule failed to mount the requested molecule instance."
30
+ "useMolecule failed to mount the requested molecule instance."
31
31
  );
32
32
  }
33
33
  const instance = state.instance;
@@ -102,4 +102,4 @@ function useDeepSignal(source) {
102
102
  return useSnapshot(handler);
103
103
  }
104
104
 
105
- export { useComputed, useDeepSignal, useMolcule, useSignal, useSnapshot };
105
+ export { useComputed, useDeepSignal, useMolecule, useSignal, useSnapshot };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigrea/react",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "React adapter bindings for Sigrea molecule modules.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -49,10 +49,11 @@
49
49
  "test:coverage": "vitest --coverage",
50
50
  "typecheck": "tsc -p tsconfig.json --noEmit",
51
51
  "format": "biome check .",
52
- "format:fix": "biome check --write ."
52
+ "format:fix": "biome check --write .",
53
+ "cicheck": "pnpm test && pnpm typecheck && pnpm format:fix"
53
54
  },
54
55
  "peerDependencies": {
55
- "@sigrea/core": "^0.4.0",
56
+ "@sigrea/core": "^0.4.3",
56
57
  "react": "^18.0.0 || ^19.0.0",
57
58
  "react-dom": "^18.0.0 || ^19.0.0"
58
59
  },