@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 +47 -7
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +3 -3
- package/package.json +4 -3
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.** `
|
|
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
|
-
- [
|
|
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 {
|
|
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 =
|
|
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
|
-
###
|
|
136
|
+
### useMolecule
|
|
136
137
|
|
|
137
138
|
```tsx
|
|
138
|
-
function
|
|
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
|
-
|
|
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
|
|
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
|
-
"
|
|
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.
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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
|
-
"
|
|
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,
|
|
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
|
+
"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.
|
|
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
|
},
|