@atolljs/react 0.1.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 +9 -0
- package/package.json +24 -0
- package/src/index.ts +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# @atolljs/react
|
|
2
|
+
|
|
3
|
+
React bindings for `@atolljs/core` — framework adapter only, no domain code.
|
|
4
|
+
|
|
5
|
+
- `useObservable(source)` — subscribe to any `ObservableValue` via `useSyncExternalStore`.
|
|
6
|
+
- `useSharedValue(memory, key)` — a shared-memory field as React state.
|
|
7
|
+
- `useTask(task)` — an `AsyncTask` snapshot (`data`/`pending`/`settled`/`elapsedMs`/`error`) plus `run`/`runOnce`.
|
|
8
|
+
|
|
9
|
+
The consuming app composes these with its own contracts and tasks.
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atolljs/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React bindings — useObservable, useSharedValue, useTask",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./src/index.ts"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"src"
|
|
11
|
+
],
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"@atolljs/core": "0.1.0",
|
|
17
|
+
"react": "^19.3.0"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/jwhenry3/atolljs",
|
|
22
|
+
"directory": "packages/react"
|
|
23
|
+
}
|
|
24
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { useMemo, useSyncExternalStore } from 'react';
|
|
2
|
+
import { observe, toTask } from '@atolljs/core';
|
|
3
|
+
import type { AsyncTask, ObservableValue, PathConnector, SharedMemory, SharedSpec, SpecPath, SliceOptions } from '@atolljs/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Subscribe to any sdk ObservableValue (task snapshot, field observable).
|
|
7
|
+
* SSR-safe: `getServerSnapshot` reuses `get`, which yields `undefined` for
|
|
8
|
+
* fields on unbound contracts.
|
|
9
|
+
*/
|
|
10
|
+
export function useObservable<T>(source: ObservableValue<T>): T {
|
|
11
|
+
return useSyncExternalStore(source.subscribe, source.get, source.get);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Bind one shared-memory field to React state. Returns `undefined` until the
|
|
16
|
+
* contract is bound and the field written; re-renders on every write.
|
|
17
|
+
*/
|
|
18
|
+
export function useSharedValue<S extends SharedSpec, K extends SpecPath<S>>(memory: SharedMemory<S>, key: K): (PathConnector<S, K> extends { read(): infer T } ? T : never) | undefined;
|
|
19
|
+
export function useSharedValue<S extends SharedSpec, K extends SpecPath<S>, Sel>(
|
|
20
|
+
memory: SharedMemory<S>,
|
|
21
|
+
key: K,
|
|
22
|
+
select: (value: PathConnector<S, K> extends { read(): infer T } ? T : never) => Sel,
|
|
23
|
+
options?: SliceOptions<Sel>
|
|
24
|
+
): Sel | undefined;
|
|
25
|
+
export function useSharedValue<S extends SharedSpec, K extends SpecPath<S>, Sel>(
|
|
26
|
+
memory: SharedMemory<S>,
|
|
27
|
+
key: K,
|
|
28
|
+
select?: (value: never) => Sel,
|
|
29
|
+
options?: SliceOptions<Sel>
|
|
30
|
+
) {
|
|
31
|
+
const source = useMemo(() => observe(memory, key, select as never, options as never), [memory, key]);
|
|
32
|
+
return useObservable(source);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Bind an AsyncTask — or a plain async function (e.g. a worker client's
|
|
37
|
+
* method), wrapped via toTask: its snapshot fields plus `run`/`runOnce`.
|
|
38
|
+
*/
|
|
39
|
+
export function useTask<R>(source: AsyncTask<void, R> | (() => Promise<R>)): {
|
|
40
|
+
data: R | null; pending: boolean; settled: boolean; elapsedMs: number | null; error: unknown;
|
|
41
|
+
run: AsyncTask<void, R>['run']; runOnce: AsyncTask<void, R>['runOnce'];
|
|
42
|
+
};
|
|
43
|
+
export function useTask<A, R>(source: AsyncTask<A, R> | ((input: A) => Promise<R>)): {
|
|
44
|
+
data: R | null; pending: boolean; settled: boolean; elapsedMs: number | null; error: unknown;
|
|
45
|
+
run: AsyncTask<A, R>['run']; runOnce: AsyncTask<A, R>['runOnce'];
|
|
46
|
+
};
|
|
47
|
+
export function useTask<A, R>(source: AsyncTask<A, R> | ((input: A) => Promise<R>)) {
|
|
48
|
+
const task = useMemo(() => toTask(source), [source]);
|
|
49
|
+
return { ...useObservable(task), run: task.run, runOnce: task.runOnce };
|
|
50
|
+
}
|