@assistant-ui/tap 0.5.14 → 0.6.1
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 -8
- package/dist/core/ResourceFiber.d.ts.map +1 -1
- package/dist/core/ResourceFiber.js +3 -2
- package/dist/core/ResourceFiber.js.map +1 -1
- package/dist/core/context.d.ts +13 -6
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/context.js +19 -6
- package/dist/core/context.js.map +1 -1
- package/dist/core/createResourceRoot.d.ts +2 -1
- package/dist/core/createResourceRoot.d.ts.map +1 -1
- package/dist/core/createResourceRoot.js +2 -2
- package/dist/core/createResourceRoot.js.map +1 -1
- package/dist/core/helpers/execution-context.d.ts +2 -1
- package/dist/core/helpers/execution-context.d.ts.map +1 -1
- package/dist/core/helpers/execution-context.js +4 -1
- package/dist/core/helpers/execution-context.js.map +1 -1
- package/dist/core/react-dispatcher.d.ts +12 -0
- package/dist/core/react-dispatcher.d.ts.map +1 -0
- package/dist/core/react-dispatcher.js +63 -0
- package/dist/core/react-dispatcher.js.map +1 -0
- package/dist/core/scheduler.js +1 -1
- package/dist/core/scheduler.js.map +1 -1
- package/dist/core/types.d.ts +3 -3
- package/dist/hooks/index.d.ts +13 -0
- package/dist/hooks/index.js +13 -0
- package/dist/hooks/use.d.ts +9 -0
- package/dist/hooks/use.d.ts.map +1 -0
- package/dist/hooks/use.js +14 -0
- package/dist/hooks/use.js.map +1 -0
- package/dist/hooks/useCallback.d.ts +5 -0
- package/dist/hooks/useCallback.d.ts.map +1 -0
- package/dist/hooks/useCallback.js +9 -0
- package/dist/hooks/useCallback.js.map +1 -0
- package/dist/hooks/useEffect.d.ts +10 -0
- package/dist/hooks/useEffect.d.ts.map +1 -0
- package/dist/hooks/{tap-effect.js → useEffect.js} +7 -7
- package/dist/hooks/useEffect.js.map +1 -0
- package/dist/hooks/{tap-effect-event.d.ts → useEffectEvent.d.ts} +5 -5
- package/dist/hooks/useEffectEvent.d.ts.map +1 -0
- package/dist/hooks/{tap-effect-event.js → useEffectEvent.js} +12 -12
- package/dist/hooks/useEffectEvent.js.map +1 -0
- package/dist/hooks/useMemo.d.ts +5 -0
- package/dist/hooks/useMemo.d.ts.map +1 -0
- package/dist/hooks/{tap-memo.js → useMemo.js} +6 -6
- package/dist/hooks/useMemo.js.map +1 -0
- package/dist/hooks/useMemoCache.d.ts +10 -0
- package/dist/hooks/useMemoCache.d.ts.map +1 -0
- package/dist/hooks/useMemoCache.js +21 -0
- package/dist/hooks/useMemoCache.js.map +1 -0
- package/dist/hooks/useReducer.d.ts +21 -0
- package/dist/hooks/useReducer.d.ts.map +1 -0
- package/dist/hooks/{tap-reducer.js → useReducer.js} +10 -10
- package/dist/hooks/useReducer.js.map +1 -0
- package/dist/hooks/useRef.d.ts +11 -0
- package/dist/hooks/useRef.d.ts.map +1 -0
- package/dist/hooks/useRef.js +10 -0
- package/dist/hooks/useRef.js.map +1 -0
- package/dist/{react/use-resource.d.ts → hooks/useResource.d.ts} +3 -2
- package/dist/hooks/useResource.d.ts.map +1 -0
- package/dist/hooks/{tap-resource.js → useResource.js} +12 -12
- package/dist/hooks/useResource.js.map +1 -0
- package/dist/hooks/useResourceRoot.d.ts +20 -0
- package/dist/hooks/useResourceRoot.d.ts.map +1 -0
- package/dist/{tapResourceRoot.js → hooks/useResourceRoot.js} +30 -26
- package/dist/hooks/useResourceRoot.js.map +1 -0
- package/dist/hooks/{tap-resources.d.ts → useResources.d.ts} +4 -4
- package/dist/hooks/useResources.d.ts.map +1 -0
- package/dist/hooks/{tap-resources.js → useResources.js} +28 -23
- package/dist/hooks/useResources.js.map +1 -0
- package/dist/hooks/useState.d.ts +9 -0
- package/dist/hooks/useState.d.ts.map +1 -0
- package/dist/hooks/useState.js +11 -0
- package/dist/hooks/useState.js.map +1 -0
- package/dist/hooks/utils/useCell.d.ts +10 -0
- package/dist/hooks/utils/useCell.d.ts.map +1 -0
- package/dist/hooks/utils/{tapHook.js → useCell.js} +4 -4
- package/dist/hooks/utils/{tapHook.js.map → useCell.js.map} +1 -1
- package/dist/index.d.ts +3 -13
- package/dist/index.js +3 -13
- package/dist/react/hooks.d.ts +25 -0
- package/dist/react/hooks.d.ts.map +1 -0
- package/dist/react/hooks.js +69 -0
- package/dist/react/hooks.js.map +1 -0
- package/dist/react-shim/index.d.ts +17 -0
- package/dist/react-shim/index.d.ts.map +1 -0
- package/dist/react-shim/index.js +28 -0
- package/dist/react-shim/index.js.map +1 -0
- package/package.json +13 -16
- package/react-shim/package.json +4 -0
- package/src/__tests__/basic/resourceHandle.test.ts +7 -3
- package/src/__tests__/basic/tapEffect.basic.test.ts +19 -19
- package/src/__tests__/basic/tapReducer.basic.test.ts +14 -14
- package/src/__tests__/basic/tapResources.basic.test.ts +19 -14
- package/src/__tests__/basic/tapState.basic.test.ts +20 -20
- package/src/__tests__/errors/errors.effect-errors.test.ts +21 -21
- package/src/__tests__/errors/errors.render-errors.test.ts +18 -18
- package/src/__tests__/lifecycle/lifecycle.dependencies.test.ts +25 -25
- package/src/__tests__/lifecycle/lifecycle.mount-unmount.test.ts +17 -18
- package/src/__tests__/react/concurrent-mode.test.tsx +7 -7
- package/src/__tests__/react/react-shim.test.tsx +65 -0
- package/src/__tests__/react/useResource.test.tsx +172 -0
- package/src/__tests__/react-dispatcher.test.ts +74 -0
- package/src/__tests__/rules/rules.hook-count.test.ts +30 -29
- package/src/__tests__/rules/rules.hook-order.test.ts +27 -27
- package/src/__tests__/strictmode/react-strictmode-behavior.test.tsx +1 -1
- package/src/__tests__/strictmode/strictmode.test.ts +42 -42
- package/src/__tests__/strictmode/tap-strictmode-rerender-sources.test.ts +55 -55
- package/src/__tests__/test-utils.ts +2 -2
- package/src/core/ResourceFiber.ts +4 -1
- package/src/core/context.ts +31 -9
- package/src/core/createResourceRoot.ts +4 -4
- package/src/core/helpers/execution-context.ts +4 -0
- package/src/core/react-dispatcher.ts +78 -0
- package/src/core/scheduler.ts +1 -1
- package/src/core/types.ts +3 -3
- package/src/hooks/index.ts +12 -0
- package/src/hooks/use.ts +13 -0
- package/src/hooks/useCallback.ts +9 -0
- package/src/hooks/{tap-effect.ts → useEffect.ts} +9 -9
- package/src/hooks/{tap-effect-event.ts → useEffectEvent.ts} +9 -9
- package/src/hooks/{tap-memo.ts → useMemo.ts} +3 -3
- package/src/hooks/useMemoCache.ts +25 -0
- package/src/hooks/{tap-reducer.ts → useReducer.ts} +23 -11
- package/src/hooks/useRef.ts +16 -0
- package/src/hooks/{tap-resource.ts → useResource.ts} +13 -12
- package/src/{tapResourceRoot.ts → hooks/useResourceRoot.ts} +26 -27
- package/src/hooks/{tap-resources.ts → useResources.ts} +21 -22
- package/src/hooks/useState.ts +29 -0
- package/src/hooks/utils/{tapHook.ts → useCell.ts} +1 -1
- package/src/index.ts +4 -24
- package/src/react/hooks.ts +112 -0
- package/src/react-shim/index.ts +75 -0
- package/dist/hooks/tap-callback.d.ts +0 -5
- package/dist/hooks/tap-callback.d.ts.map +0 -1
- package/dist/hooks/tap-callback.js +0 -9
- package/dist/hooks/tap-callback.js.map +0 -1
- package/dist/hooks/tap-const.d.ts +0 -5
- package/dist/hooks/tap-const.d.ts.map +0 -1
- package/dist/hooks/tap-const.js +0 -10
- package/dist/hooks/tap-const.js.map +0 -1
- package/dist/hooks/tap-effect-event.d.ts.map +0 -1
- package/dist/hooks/tap-effect-event.js.map +0 -1
- package/dist/hooks/tap-effect.d.ts +0 -10
- package/dist/hooks/tap-effect.d.ts.map +0 -1
- package/dist/hooks/tap-effect.js.map +0 -1
- package/dist/hooks/tap-memo.d.ts +0 -5
- package/dist/hooks/tap-memo.d.ts.map +0 -1
- package/dist/hooks/tap-memo.js.map +0 -1
- package/dist/hooks/tap-reducer.d.ts +0 -9
- package/dist/hooks/tap-reducer.d.ts.map +0 -1
- package/dist/hooks/tap-reducer.js.map +0 -1
- package/dist/hooks/tap-ref.d.ts +0 -11
- package/dist/hooks/tap-ref.d.ts.map +0 -1
- package/dist/hooks/tap-ref.js +0 -10
- package/dist/hooks/tap-ref.js.map +0 -1
- package/dist/hooks/tap-resource.d.ts +0 -8
- package/dist/hooks/tap-resource.d.ts.map +0 -1
- package/dist/hooks/tap-resource.js.map +0 -1
- package/dist/hooks/tap-resources.d.ts.map +0 -1
- package/dist/hooks/tap-resources.js.map +0 -1
- package/dist/hooks/tap-state.d.ts +0 -9
- package/dist/hooks/tap-state.d.ts.map +0 -1
- package/dist/hooks/tap-state.js +0 -11
- package/dist/hooks/tap-state.js.map +0 -1
- package/dist/hooks/utils/tapHook.d.ts +0 -10
- package/dist/hooks/utils/tapHook.d.ts.map +0 -1
- package/dist/react/index.d.ts +0 -2
- package/dist/react/index.js +0 -2
- package/dist/react/use-resource.d.ts.map +0 -1
- package/dist/react/use-resource.js +0 -46
- package/dist/react/use-resource.js.map +0 -1
- package/dist/tapResourceRoot.d.ts +0 -20
- package/dist/tapResourceRoot.d.ts.map +0 -1
- package/dist/tapResourceRoot.js.map +0 -1
- package/react/package.json +0 -5
- package/src/hooks/tap-callback.ts +0 -9
- package/src/hooks/tap-const.ts +0 -6
- package/src/hooks/tap-ref.ts +0 -16
- package/src/hooks/tap-state.ts +0 -29
- package/src/react/index.ts +0 -1
- package/src/react/use-resource.ts +0 -61
|
@@ -3,22 +3,21 @@ import {
|
|
|
3
3
|
createResourceFiber,
|
|
4
4
|
renderResourceFiber,
|
|
5
5
|
unmountResourceFiber,
|
|
6
|
-
} from "
|
|
7
|
-
import { UpdateScheduler } from "
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import { isDevelopment } from "./core/helpers/env";
|
|
6
|
+
} from "../core/ResourceFiber";
|
|
7
|
+
import { UpdateScheduler } from "../core/scheduler";
|
|
8
|
+
import { useMemo } from "./useMemo";
|
|
9
|
+
import { useEffect } from "./useEffect";
|
|
10
|
+
import { useEffectEvent } from "./useEffectEvent";
|
|
11
|
+
import { useRef } from "./useRef";
|
|
12
|
+
import type { RenderResult, ResourceElement } from "../core/types";
|
|
13
|
+
import { isDevelopment } from "../core/helpers/env";
|
|
15
14
|
import {
|
|
16
15
|
commitRoot,
|
|
17
16
|
createResourceFiberRoot,
|
|
18
17
|
setRootVersion,
|
|
19
|
-
} from "
|
|
18
|
+
} from "../core/helpers/root";
|
|
20
19
|
|
|
21
|
-
export namespace
|
|
20
|
+
export namespace useResourceRoot {
|
|
22
21
|
export type Unsubscribe = () => void;
|
|
23
22
|
|
|
24
23
|
export interface SubscribableResource<TState> {
|
|
@@ -34,18 +33,18 @@ export namespace tapResourceRoot {
|
|
|
34
33
|
}
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
//
|
|
36
|
+
// The root is never reset, because rollbacks are not supported in useResourceRoot.
|
|
38
37
|
|
|
39
|
-
export const
|
|
38
|
+
export const useResourceRoot = <TState>(
|
|
40
39
|
element: ResourceElement<TState>,
|
|
41
|
-
):
|
|
42
|
-
const scheduler =
|
|
40
|
+
): useResourceRoot.SubscribableResource<TState> => {
|
|
41
|
+
const scheduler = useMemo(
|
|
43
42
|
() => new UpdateScheduler(() => handleUpdate(null)),
|
|
44
43
|
[],
|
|
45
44
|
);
|
|
46
|
-
const queue =
|
|
45
|
+
const queue = useMemo(() => [] as (() => void)[], []);
|
|
47
46
|
|
|
48
|
-
const fiber =
|
|
47
|
+
const fiber = useMemo(() => {
|
|
49
48
|
void element.key;
|
|
50
49
|
|
|
51
50
|
return createResourceFiber(
|
|
@@ -56,16 +55,16 @@ export const tapResourceRoot = <TState>(
|
|
|
56
55
|
scheduler.markDirty();
|
|
57
56
|
}),
|
|
58
57
|
);
|
|
59
|
-
}, [element.type, element.key]);
|
|
58
|
+
}, [element.type, element.key, queue, scheduler]);
|
|
60
59
|
|
|
61
60
|
setRootVersion(fiber.root, fiber.root.committedVersion);
|
|
62
61
|
const render = renderResourceFiber(fiber, element.props);
|
|
63
62
|
|
|
64
|
-
const isMountedRef =
|
|
65
|
-
const committedPropsRef =
|
|
66
|
-
const valueRef =
|
|
67
|
-
const subscribers =
|
|
68
|
-
const handleUpdate =
|
|
63
|
+
const isMountedRef = useRef(false);
|
|
64
|
+
const committedPropsRef = useRef(element.props);
|
|
65
|
+
const valueRef = useRef<TState>(render.output);
|
|
66
|
+
const subscribers = useMemo(() => new Set<() => void>(), []);
|
|
67
|
+
const handleUpdate = useEffectEvent((render: RenderResult | null) => {
|
|
69
68
|
if (render === null) {
|
|
70
69
|
setRootVersion(fiber.root, 2);
|
|
71
70
|
setRootVersion(fiber.root, 1);
|
|
@@ -100,7 +99,7 @@ export const tapResourceRoot = <TState>(
|
|
|
100
99
|
subscribers.forEach((callback) => callback());
|
|
101
100
|
});
|
|
102
101
|
|
|
103
|
-
|
|
102
|
+
useEffect(() => {
|
|
104
103
|
isMountedRef.current = true;
|
|
105
104
|
return () => {
|
|
106
105
|
isMountedRef.current = false;
|
|
@@ -108,7 +107,7 @@ export const tapResourceRoot = <TState>(
|
|
|
108
107
|
};
|
|
109
108
|
}, [fiber]);
|
|
110
109
|
|
|
111
|
-
|
|
110
|
+
useEffect(() => {
|
|
112
111
|
committedPropsRef.current = render.props;
|
|
113
112
|
commitRoot(fiber.root);
|
|
114
113
|
commitResourceFiber(fiber, render);
|
|
@@ -118,7 +117,7 @@ export const tapResourceRoot = <TState>(
|
|
|
118
117
|
subscribers.forEach((callback) => callback());
|
|
119
118
|
});
|
|
120
119
|
|
|
121
|
-
return
|
|
120
|
+
return useMemo(
|
|
122
121
|
() => ({
|
|
123
122
|
getValue: () => valueRef.current,
|
|
124
123
|
subscribe: (listener: () => void) => {
|
|
@@ -126,6 +125,6 @@ export const tapResourceRoot = <TState>(
|
|
|
126
125
|
return () => subscribers.delete(listener);
|
|
127
126
|
},
|
|
128
127
|
}),
|
|
129
|
-
[],
|
|
128
|
+
[subscribers],
|
|
130
129
|
);
|
|
131
130
|
};
|
|
@@ -4,17 +4,16 @@ import type {
|
|
|
4
4
|
ResourceElement,
|
|
5
5
|
ResourceFiber,
|
|
6
6
|
} from "../core/types";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { useEffect } from "./useEffect";
|
|
8
|
+
import { useMemo } from "./useMemo";
|
|
9
|
+
import { useCallback } from "./useCallback";
|
|
10
10
|
import {
|
|
11
11
|
createResourceFiber,
|
|
12
12
|
unmountResourceFiber,
|
|
13
13
|
renderResourceFiber,
|
|
14
14
|
commitResourceFiber,
|
|
15
15
|
} from "../core/ResourceFiber";
|
|
16
|
-
import {
|
|
17
|
-
import { tapRef } from "./tap-ref";
|
|
16
|
+
import { useRef } from "./useRef";
|
|
18
17
|
import { getCurrentResourceFiber } from "../core/helpers/execution-context";
|
|
19
18
|
|
|
20
19
|
type FiberState = {
|
|
@@ -25,31 +24,31 @@ type FiberState = {
|
|
|
25
24
|
| "delete";
|
|
26
25
|
};
|
|
27
26
|
|
|
28
|
-
export function
|
|
27
|
+
export function useResources<E extends ResourceElement<any, any>>(
|
|
29
28
|
getElements: () => readonly E[],
|
|
30
29
|
getElementsDeps?: readonly unknown[],
|
|
31
30
|
): ExtractResourceReturnType<E>[] {
|
|
32
|
-
const versionRef =
|
|
31
|
+
const versionRef = useRef(0);
|
|
33
32
|
const version = versionRef.current;
|
|
34
33
|
|
|
35
|
-
const parentFiber =
|
|
36
|
-
const markDirty =
|
|
34
|
+
const parentFiber = useMemo(() => getCurrentResourceFiber(), []);
|
|
35
|
+
const markDirty = useMemo(
|
|
37
36
|
() => () => {
|
|
38
37
|
versionRef.current++;
|
|
39
38
|
parentFiber.markDirty?.();
|
|
40
39
|
},
|
|
41
|
-
[],
|
|
40
|
+
[parentFiber],
|
|
42
41
|
);
|
|
43
|
-
const fibers =
|
|
42
|
+
const fibers = useMemo(() => new Map<string | number, FiberState>(), []);
|
|
44
43
|
|
|
45
44
|
const getElementsMemo = getElementsDeps
|
|
46
|
-
? // oxlint-disable-next-line
|
|
47
|
-
|
|
45
|
+
? // oxlint-disable-next-line react/exhaustive-deps,react/rules-of-hooks -- deps forwarded by caller; getElementsDeps presence is fixed per call site
|
|
46
|
+
useCallback(getElements, getElementsDeps)
|
|
48
47
|
: getElements;
|
|
49
48
|
|
|
50
49
|
// Process each element
|
|
51
50
|
|
|
52
|
-
const res =
|
|
51
|
+
const res = useMemo(() => {
|
|
53
52
|
void version;
|
|
54
53
|
|
|
55
54
|
const elementsArray = getElementsMemo();
|
|
@@ -64,12 +63,12 @@ export function tapResources<E extends ResourceElement<any, any>>(
|
|
|
64
63
|
const elementKey = element.key;
|
|
65
64
|
if (elementKey === undefined) {
|
|
66
65
|
throw new Error(
|
|
67
|
-
`
|
|
66
|
+
`useResources did not provide a key for array at index ${i}`,
|
|
68
67
|
);
|
|
69
68
|
}
|
|
70
69
|
|
|
71
70
|
if (seenKeys.has(elementKey))
|
|
72
|
-
throw new Error(`Duplicate key ${elementKey} in
|
|
71
|
+
throw new Error(`Duplicate key ${elementKey} in useResources`);
|
|
73
72
|
seenKeys.add(elementKey);
|
|
74
73
|
|
|
75
74
|
let state = fibers.get(elementKey);
|
|
@@ -112,20 +111,20 @@ export function tapResources<E extends ResourceElement<any, any>>(
|
|
|
112
111
|
}
|
|
113
112
|
|
|
114
113
|
return results;
|
|
115
|
-
}, [getElementsMemo, version]);
|
|
114
|
+
}, [getElementsMemo, version, parentFiber, markDirty, fibers]);
|
|
116
115
|
|
|
117
116
|
// Cleanup on unmount
|
|
118
|
-
|
|
117
|
+
useEffect(() => {
|
|
119
118
|
return () => {
|
|
120
119
|
for (const key of fibers.keys()) {
|
|
121
120
|
const fiber = fibers.get(key)!.fiber;
|
|
122
121
|
unmountResourceFiber(fiber);
|
|
123
122
|
}
|
|
124
123
|
};
|
|
125
|
-
}, []);
|
|
124
|
+
}, [fibers]);
|
|
126
125
|
|
|
127
|
-
|
|
128
|
-
res; // as a performance optimization, we only run if the results have changed
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
void res; // as a performance optimization, we only run if the results have changed
|
|
129
128
|
|
|
130
129
|
for (const [key, state] of fibers.entries()) {
|
|
131
130
|
if (state.next === "delete") {
|
|
@@ -142,7 +141,7 @@ export function tapResources<E extends ResourceElement<any, any>>(
|
|
|
142
141
|
commitResourceFiber(state.fiber, state.next);
|
|
143
142
|
}
|
|
144
143
|
}
|
|
145
|
-
}, [res]);
|
|
144
|
+
}, [res, fibers]);
|
|
146
145
|
|
|
147
146
|
return res;
|
|
148
147
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useReducer } from "./useReducer";
|
|
2
|
+
|
|
3
|
+
export namespace useState {
|
|
4
|
+
export type StateUpdater<S> = S | ((prev: S) => S);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const stateReducer = <S>(
|
|
8
|
+
state: S | undefined,
|
|
9
|
+
action: useState.StateUpdater<S>,
|
|
10
|
+
): S =>
|
|
11
|
+
typeof action === "function"
|
|
12
|
+
? (action as (prev: S | undefined) => S)(state)
|
|
13
|
+
: action;
|
|
14
|
+
|
|
15
|
+
const stateInit = <S>(initial: S | (() => S)): S =>
|
|
16
|
+
typeof initial === "function" ? (initial as () => S)() : initial;
|
|
17
|
+
|
|
18
|
+
export function useState<S = undefined>(): [
|
|
19
|
+
S | undefined,
|
|
20
|
+
(updater: useState.StateUpdater<S>) => void,
|
|
21
|
+
];
|
|
22
|
+
export function useState<S>(
|
|
23
|
+
initial: S | (() => S),
|
|
24
|
+
): [S, (updater: useState.StateUpdater<S>) => void];
|
|
25
|
+
export function useState<S>(
|
|
26
|
+
initial?: S | (() => S),
|
|
27
|
+
): [S | undefined, (updater: useState.StateUpdater<S>) => void] {
|
|
28
|
+
return useReducer(stateReducer, initial, stateInit);
|
|
29
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getCurrentResourceFiber } from "../../core/helpers/execution-context";
|
|
2
2
|
import type { Cell } from "../../core/types";
|
|
3
3
|
|
|
4
|
-
export const
|
|
4
|
+
export const useCell = <T extends Cell["type"]>(
|
|
5
5
|
type: T,
|
|
6
6
|
init: () => Cell,
|
|
7
7
|
): Cell & { type: T } => {
|
package/src/index.ts
CHANGED
|
@@ -1,35 +1,15 @@
|
|
|
1
1
|
export { resource } from "./core/resource";
|
|
2
2
|
export { withKey } from "./core/withKey";
|
|
3
3
|
|
|
4
|
-
// primitive hooks
|
|
5
|
-
export { tapState } from "./hooks/tap-state";
|
|
6
|
-
export { tapReducer, tapReducerWithDerivedState } from "./hooks/tap-reducer";
|
|
7
|
-
export { tapEffect } from "./hooks/tap-effect";
|
|
8
|
-
|
|
9
|
-
// utility hooks
|
|
10
|
-
export { tapRef } from "./hooks/tap-ref";
|
|
11
|
-
export { tapConst } from "./hooks/tap-const";
|
|
12
|
-
export { tapMemo } from "./hooks/tap-memo";
|
|
13
|
-
export { tapCallback } from "./hooks/tap-callback";
|
|
14
|
-
export { tapEffectEvent } from "./hooks/tap-effect-event";
|
|
15
|
-
|
|
16
|
-
// resources
|
|
17
|
-
export { tapResource } from "./hooks/tap-resource";
|
|
18
|
-
export { tapResources } from "./hooks/tap-resources";
|
|
19
|
-
|
|
20
|
-
// subscribable
|
|
21
|
-
export { tapResourceRoot } from "./tapResourceRoot";
|
|
22
|
-
|
|
23
4
|
// imperative
|
|
24
5
|
export { createResourceRoot } from "./core/createResourceRoot";
|
|
25
6
|
export { flushResourcesSync } from "./core/scheduler";
|
|
26
7
|
|
|
27
8
|
// context
|
|
28
|
-
export {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
} from "./core/context";
|
|
9
|
+
export { createResourceContext, withContextProvider } from "./core/context";
|
|
10
|
+
|
|
11
|
+
// hooks
|
|
12
|
+
export { useResource, useResources, useResourceRoot } from "./react/hooks";
|
|
33
13
|
|
|
34
14
|
// types
|
|
35
15
|
export type {
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
2
|
+
import type { ResourceFiberRoot, Resource } from "../core/types";
|
|
3
|
+
import {
|
|
4
|
+
createResourceFiber,
|
|
5
|
+
unmountResourceFiber,
|
|
6
|
+
renderResourceFiber,
|
|
7
|
+
commitResourceFiber,
|
|
8
|
+
} from "../core/ResourceFiber";
|
|
9
|
+
import { isDevelopment } from "../core/helpers/env";
|
|
10
|
+
import {
|
|
11
|
+
commitRoot,
|
|
12
|
+
createResourceFiberRoot,
|
|
13
|
+
setRootVersion,
|
|
14
|
+
} from "../core/helpers/root";
|
|
15
|
+
import { peekResourceFiber } from "../core/helpers/execution-context";
|
|
16
|
+
import * as hooks from "../hooks";
|
|
17
|
+
import { resource } from "../core/resource";
|
|
18
|
+
|
|
19
|
+
const useDevStrictMode = () => {
|
|
20
|
+
if (!isDevelopment) return null;
|
|
21
|
+
|
|
22
|
+
// oxlint-disable-next-line react/rules-of-hooks -- isDevelopment is a build-time constant, so this branch is stable per build
|
|
23
|
+
const count = useRef(0);
|
|
24
|
+
const isFirstRender = count.current === 0;
|
|
25
|
+
// oxlint-disable-next-line react/rules-of-hooks -- isDevelopment is a build-time constant, so this branch is stable per build
|
|
26
|
+
useState(() => count.current++);
|
|
27
|
+
if (count.current !== 2) return null;
|
|
28
|
+
return isFirstRender ? ("child" as const) : ("root" as const);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const HostResource = resource(function HostResource<T>(callback: () => T) {
|
|
32
|
+
return callback();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Runs `callback` inside a resource render hosted by a React component, so the
|
|
36
|
+
// resource composition hooks (useResource/useResources/useResourceRoot) work from
|
|
37
|
+
// React. `callback` executes inside the resource fiber below, so it may only call
|
|
38
|
+
// resource hooks, not React's own hooks (which would have no fiber to attach to).
|
|
39
|
+
// This is the single React->resource bridge; the React branch of every public
|
|
40
|
+
// hook goes through it.
|
|
41
|
+
const useResourceHost = <T>(callback: () => T): T => {
|
|
42
|
+
const root = useMemo<ResourceFiberRoot>(() => {
|
|
43
|
+
return createResourceFiberRoot((cb) => dispatch(cb));
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
const [version, dispatch] = useReducer((v: number, cb: () => boolean) => {
|
|
47
|
+
setRootVersion(root, v);
|
|
48
|
+
return v + (cb() ? 1 : 0);
|
|
49
|
+
}, 0);
|
|
50
|
+
setRootVersion(root, version);
|
|
51
|
+
|
|
52
|
+
const devStrictMode = useDevStrictMode();
|
|
53
|
+
const fiber = useMemo(() => {
|
|
54
|
+
return createResourceFiber(
|
|
55
|
+
HostResource as unknown as Resource<T, () => T>,
|
|
56
|
+
root,
|
|
57
|
+
undefined,
|
|
58
|
+
devStrictMode,
|
|
59
|
+
);
|
|
60
|
+
}, [root, devStrictMode]);
|
|
61
|
+
|
|
62
|
+
const result = renderResourceFiber(fiber, callback);
|
|
63
|
+
useLayoutEffect(() => {
|
|
64
|
+
return () => unmountResourceFiber(fiber);
|
|
65
|
+
}, [fiber]);
|
|
66
|
+
useLayoutEffect(() => {
|
|
67
|
+
commitRoot(root);
|
|
68
|
+
commitResourceFiber(fiber, result);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return result.output;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Turns a resource hook into an isomorphic hook with the SAME type (overloads
|
|
75
|
+
// included): inside a resource render it calls the hook directly; inside a React
|
|
76
|
+
// component it hosts it via the `useResourceHost` bridge. peekResourceFiber() is
|
|
77
|
+
// stable per call site (a given call always renders in the same environment), so
|
|
78
|
+
// the branch order across renders is fixed even though rules-of-hooks can't prove
|
|
79
|
+
// it.
|
|
80
|
+
const makeHook = <F extends (...args: any[]) => any>(hook: F): F =>
|
|
81
|
+
((...args: any[]) => {
|
|
82
|
+
/* oxlint-disable react/rules-of-hooks */
|
|
83
|
+
if (peekResourceFiber()) return hook(...args);
|
|
84
|
+
return useResourceHost(() => hook(...args));
|
|
85
|
+
/* oxlint-enable react/rules-of-hooks */
|
|
86
|
+
}) as F;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Hosts a resource element. Inside a resource render it hosts the element as a
|
|
90
|
+
* child resource; inside a React component it hosts it via the React bridge.
|
|
91
|
+
* `propsDeps` is a resource-render optimization and is ignored on the React side.
|
|
92
|
+
*/
|
|
93
|
+
export const useResource: typeof hooks.useResource = makeHook(
|
|
94
|
+
hooks.useResource,
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Hosts a keyed list of resource elements. Inside a resource render it composes
|
|
99
|
+
* them directly; inside a React component it hosts them via the React bridge.
|
|
100
|
+
*/
|
|
101
|
+
export const useResources: typeof hooks.useResources = makeHook(
|
|
102
|
+
hooks.useResources,
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Hosts a resource element as a subscribable root. Inside a resource render it
|
|
107
|
+
* uses the root hook directly; inside a React component it hosts that root via
|
|
108
|
+
* the React bridge (host it in one place; observe it via getValue/subscribe).
|
|
109
|
+
*/
|
|
110
|
+
export const useResourceRoot: typeof hooks.useResourceRoot = makeHook(
|
|
111
|
+
hooks.useResourceRoot,
|
|
112
|
+
);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* oxlint-disable react/rules-of-hooks -- this module deliberately routes hook calls between tap and React at runtime */
|
|
2
|
+
/* oxlint-disable react/exhaustive-deps -- dependency arrays are forwarded verbatim from the caller */
|
|
3
|
+
// Runtime drop-in for "react": forward everything from react, then override the
|
|
4
|
+
// hooks that have a tap equivalent so they route to tap inside a resource render
|
|
5
|
+
// and to React otherwise. Alias `react` to this module (build `output.paths` /
|
|
6
|
+
// vitest resolver) in code that can run inside a tap resource.
|
|
7
|
+
//
|
|
8
|
+
// This subpath ships no type declarations: the build reverts the aliased
|
|
9
|
+
// specifier back to `"react"` in emitted `.d.ts`, so consumer types resolve to
|
|
10
|
+
// React's own. The source-level TS2498 from the `export *` below is suppressed.
|
|
11
|
+
import React from "react";
|
|
12
|
+
import { peekResourceFiber } from "../core/helpers/execution-context";
|
|
13
|
+
import * as hooks from "../hooks";
|
|
14
|
+
import { useResourceContext, isResourceContext } from "../core/context";
|
|
15
|
+
|
|
16
|
+
// @ts-expect-error -- @types/react uses `export =`; this is valid at runtime.
|
|
17
|
+
export * from "react";
|
|
18
|
+
export { default } from "react";
|
|
19
|
+
|
|
20
|
+
const inTap = () => peekResourceFiber() !== null;
|
|
21
|
+
const ReactRuntime = React as any;
|
|
22
|
+
|
|
23
|
+
// --- hooks with a tap equivalent: override the star-exported react hooks ---
|
|
24
|
+
|
|
25
|
+
export const useState = (initialState?: any) =>
|
|
26
|
+
inTap() ? hooks.useState(initialState) : ReactRuntime.useState(initialState);
|
|
27
|
+
|
|
28
|
+
export const useReducer = (reducer: any, initialArg: any, init?: any) =>
|
|
29
|
+
inTap()
|
|
30
|
+
? hooks.useReducer(reducer, initialArg, init)
|
|
31
|
+
: ReactRuntime.useReducer(reducer, initialArg, init);
|
|
32
|
+
|
|
33
|
+
export const useRef = (initialValue?: any) =>
|
|
34
|
+
inTap() ? hooks.useRef(initialValue) : ReactRuntime.useRef(initialValue);
|
|
35
|
+
|
|
36
|
+
export const useMemo = (factory: any, deps: any) =>
|
|
37
|
+
inTap() ? hooks.useMemo(factory, deps) : ReactRuntime.useMemo(factory, deps);
|
|
38
|
+
|
|
39
|
+
export const useCallback = (callback: any, deps: any) =>
|
|
40
|
+
inTap()
|
|
41
|
+
? hooks.useCallback(callback, deps)
|
|
42
|
+
: ReactRuntime.useCallback(callback, deps);
|
|
43
|
+
|
|
44
|
+
export const useEffect = (effect: any, deps?: any) =>
|
|
45
|
+
inTap()
|
|
46
|
+
? hooks.useEffect(effect, deps)
|
|
47
|
+
: ReactRuntime.useEffect(effect, deps);
|
|
48
|
+
|
|
49
|
+
// tap has a single effect primitive; layout effects collapse onto it
|
|
50
|
+
export const useLayoutEffect = (effect: any, deps?: any) =>
|
|
51
|
+
inTap()
|
|
52
|
+
? hooks.useEffect(effect, deps)
|
|
53
|
+
: ReactRuntime.useLayoutEffect(effect, deps);
|
|
54
|
+
|
|
55
|
+
// The non-tap fallback requires a React version that provides useEffectEvent.
|
|
56
|
+
export const useEffectEvent = (callback: any) =>
|
|
57
|
+
inTap()
|
|
58
|
+
? hooks.useEffectEvent(callback)
|
|
59
|
+
: ReactRuntime.useEffectEvent(callback);
|
|
60
|
+
|
|
61
|
+
// `use(usable)` reads tap resource context when handed a tap context (routed by
|
|
62
|
+
// its brand, not by ambient render state), and falls back to React's `use`
|
|
63
|
+
// (promises / React context) for everything else. The non-tap fallback requires
|
|
64
|
+
// React 19.
|
|
65
|
+
export const use = (usable: any) =>
|
|
66
|
+
isResourceContext(usable)
|
|
67
|
+
? useResourceContext(usable)
|
|
68
|
+
: ReactRuntime.use(usable);
|
|
69
|
+
|
|
70
|
+
// `useContext(context)` reads tap resource context when handed a tap context
|
|
71
|
+
// (routed by its brand), and falls back to React's `useContext` otherwise.
|
|
72
|
+
export const useContext = (context: any) =>
|
|
73
|
+
isResourceContext(context)
|
|
74
|
+
? useResourceContext(context)
|
|
75
|
+
: ReactRuntime.useContext(context);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-callback.d.ts","names":[],"sources":["../../src/hooks/tap-callback.ts"],"mappings":";cAEa,WAAA,iBAA6B,IAAA,iBACxC,EAAA,EAAI,CAAA,EACJ,IAAA,yBACC,CAGF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-callback.js","names":[],"sources":["../../src/hooks/tap-callback.ts"],"sourcesContent":["import { tapMemo } from \"./tap-memo\";\n\nexport const tapCallback = <T extends (...args: any[]) => any>(\n fn: T,\n deps: readonly unknown[],\n): T => {\n // oxlint-disable-next-line tap-hooks/exhaustive-deps -- user-provided dep array forwarded verbatim\n return tapMemo(() => fn, deps);\n};\n"],"mappings":";;AAEA,MAAa,eACX,IACA,SACM;CAEN,OAAO,cAAc,IAAI,IAAI;AAC/B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-const.d.ts","names":[],"sources":["../../src/hooks/tap-const.ts"],"mappings":";iBAEgB,QAAA,IAAY,QAAA,QAAgB,CAAA,EAAG,KAAA,qBAA0B,CAAC"}
|
package/dist/hooks/tap-const.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-const.js","names":[],"sources":["../../src/hooks/tap-const.ts"],"sourcesContent":["import { tapState } from \"./tap-state\";\n\nexport function tapConst<T>(getValue: () => T, _deps: readonly never[]): T {\n const [state] = tapState(getValue);\n return state;\n}\n"],"mappings":";;AAEA,SAAgB,SAAY,UAAmB,OAA4B;CACzE,MAAM,CAAC,SAAS,SAAS,QAAQ;CACjC,OAAO;AACT"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-effect-event.d.ts","names":[],"sources":["../../src/hooks/tap-effect-event.ts"],"mappings":";;AAqBA;;;;;;;;;;AAEI;;;;iBAFY,cAAA,eAA6B,IAAA,iBAC3C,QAAA,EAAU,CAAA,GACT,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-effect-event.js","names":[],"sources":["../../src/hooks/tap-effect-event.ts"],"sourcesContent":["import { tapRef } from \"./tap-ref\";\nimport { tapEffect } from \"./tap-effect\";\nimport { isDevelopment } from \"../core/helpers/env\";\nimport { tapCallback } from \"./tap-callback\";\nimport { getCurrentResourceFiber } from \"../core/helpers/execution-context\";\n\n/**\n * Creates a stable function reference that always calls the most recent version of the callback.\n * Similar to React's useEffectEvent hook.\n *\n * @param callback - The callback function to wrap\n * @returns A stable function reference that always calls the latest callback\n *\n * @example\n * ```typescript\n * const handleClick = tapEffectEvent((value: string) => {\n * console.log(value);\n * });\n * // handleClick reference is stable, but always calls the latest version\n * ```\n */\nexport function tapEffectEvent<T extends (...args: any[]) => any>(\n callback: T,\n): T {\n const callbackRef = tapRef(callback);\n\n // TODO this effect needs to run before all userland effects\n tapEffect(() => {\n callbackRef.current = callback;\n });\n\n const fiber = getCurrentResourceFiber();\n return tapCallback(\n ((...args: Parameters<T>) => {\n if (isDevelopment && fiber.renderContext)\n throw new Error(\"tapEffectEvent cannot be called during render\");\n return callbackRef.current(...args);\n }) as T,\n [fiber],\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,eACd,UACG;CACH,MAAM,cAAc,OAAO,QAAQ;CAGnC,gBAAgB;EACd,YAAY,UAAU;CACxB,CAAC;CAED,MAAM,QAAQ,wBAAwB;CACtC,OAAO,cACH,GAAG,SAAwB;EAC3B,IAAI,iBAAiB,MAAM,eACzB,MAAM,IAAI,MAAM,+CAA+C;EACjE,OAAO,YAAY,QAAQ,GAAG,IAAI;CACpC,IACA,CAAC,KAAK,CACR;AACF"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
//#region src/hooks/tap-effect.d.ts
|
|
2
|
-
declare namespace tapEffect {
|
|
3
|
-
type Destructor = () => void;
|
|
4
|
-
type EffectCallback = () => Destructor | undefined;
|
|
5
|
-
}
|
|
6
|
-
declare function tapEffect(effect: tapEffect.EffectCallback): void;
|
|
7
|
-
declare function tapEffect(effect: tapEffect.EffectCallback, deps: readonly unknown[]): void;
|
|
8
|
-
//#endregion
|
|
9
|
-
export { tapEffect };
|
|
10
|
-
//# sourceMappingURL=tap-effect.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-effect.d.ts","names":[],"sources":["../../src/hooks/tap-effect.ts"],"mappings":";kBAUiB,SAAA;EAAA,KACH,UAAA;EAAA,KACA,cAAA,SAAuB,UAAU;AAAA;AAAA,iBAG/B,SAAA,CAAU,MAAA,EAAQ,SAAA,CAAU,cAAc;AAAA,iBAC1C,SAAA,CACd,MAAA,EAAQ,SAAA,CAAU,cAAc,EAChC,IAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-effect.js","names":[],"sources":["../../src/hooks/tap-effect.ts"],"sourcesContent":["import type { Cell } from \"../core/types\";\nimport { depsShallowEqual } from \"./utils/depsShallowEqual\";\nimport { tapHook, registerRenderMountTask } from \"./utils/tapHook\";\n\nconst newEffect = (): Cell & { type: \"effect\" } => ({\n type: \"effect\",\n cleanup: undefined,\n deps: null, // null means the effect has never been run\n});\n\nexport namespace tapEffect {\n export type Destructor = () => void;\n export type EffectCallback = () => Destructor | undefined;\n}\n\nexport function tapEffect(effect: tapEffect.EffectCallback): void;\nexport function tapEffect(\n effect: tapEffect.EffectCallback,\n deps: readonly unknown[],\n): void;\nexport function tapEffect(\n effect: tapEffect.EffectCallback,\n deps?: readonly unknown[],\n): void {\n const cell = tapHook(\"effect\", newEffect);\n\n if (deps && cell.deps && depsShallowEqual(cell.deps, deps)) return;\n if (cell.deps !== null && !!deps !== !!cell.deps)\n throw new Error(\n \"tapEffect called with and without dependencies across re-renders\",\n );\n\n registerRenderMountTask(() => {\n const errors: unknown[] = [];\n\n try {\n cell.cleanup?.();\n } catch (error) {\n errors.push(error);\n } finally {\n cell.cleanup = undefined;\n }\n\n try {\n const cleanup = effect();\n\n if (cleanup !== undefined && typeof cleanup !== \"function\") {\n throw new Error(\n \"An effect function must either return a cleanup function or nothing. \" +\n `Received: ${typeof cleanup}`,\n );\n }\n\n cell.cleanup = cleanup;\n } catch (error) {\n errors.push(error);\n }\n\n cell.deps = deps;\n\n if (errors.length > 0) {\n if (errors.length === 1) {\n throw errors[0];\n } else {\n for (const error of errors) {\n console.error(error);\n }\n throw new AggregateError(errors, \"Errors during commit\");\n }\n }\n });\n}\n"],"mappings":";;;AAIA,MAAM,mBAA8C;CAClD,MAAM;CACN,SAAS,KAAA;CACT,MAAM;AACR;AAYA,SAAgB,UACd,QACA,MACM;CACN,MAAM,OAAO,QAAQ,UAAU,SAAS;CAExC,IAAI,QAAQ,KAAK,QAAQ,iBAAiB,KAAK,MAAM,IAAI,GAAG;CAC5D,IAAI,KAAK,SAAS,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,MAC1C,MAAM,IAAI,MACR,kEACF;CAEF,8BAA8B;EAC5B,MAAM,SAAoB,CAAC;EAE3B,IAAI;GACF,KAAK,UAAU;EACjB,SAAS,OAAO;GACd,OAAO,KAAK,KAAK;EACnB,UAAU;GACR,KAAK,UAAU,KAAA;EACjB;EAEA,IAAI;GACF,MAAM,UAAU,OAAO;GAEvB,IAAI,YAAY,KAAA,KAAa,OAAO,YAAY,YAC9C,MAAM,IAAI,MACR,kFACe,OAAO,SACxB;GAGF,KAAK,UAAU;EACjB,SAAS,OAAO;GACd,OAAO,KAAK,KAAK;EACnB;EAEA,KAAK,OAAO;EAEZ,IAAI,OAAO,SAAS,GAClB,IAAI,OAAO,WAAW,GACpB,MAAM,OAAO;OACR;GACL,KAAK,MAAM,SAAS,QAClB,QAAQ,MAAM,KAAK;GAErB,MAAM,IAAI,eAAe,QAAQ,sBAAsB;EACzD;CAEJ,CAAC;AACH"}
|
package/dist/hooks/tap-memo.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-memo.d.ts","names":[],"sources":["../../src/hooks/tap-memo.ts"],"mappings":";cAWa,OAAA,MAAc,EAAA,QAAU,CAAA,EAAG,IAAA,yBAA2B,CAkBlE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-memo.js","names":[],"sources":["../../src/hooks/tap-memo.ts"],"sourcesContent":["import { isDevelopment } from \"../core/helpers/env\";\nimport { getCurrentResourceFiber } from \"../core/helpers/execution-context\";\nimport { tapReducerWithDerivedState } from \"./tap-reducer\";\nimport { depsShallowEqual } from \"./utils/depsShallowEqual\";\n\nconst memoReducer = () => {\n throw new Error(\"Memo reducer should not be called\");\n};\n\ntype MemoState<T> = { value: T; deps: readonly unknown[] };\n\nexport const tapMemo = <T>(fn: () => T, deps: readonly unknown[]): T => {\n const fiber = getCurrentResourceFiber();\n const [state] = tapReducerWithDerivedState(\n memoReducer,\n (state: MemoState<T> | null): MemoState<T> => {\n if (state && depsShallowEqual(state.deps, deps)) return state;\n\n const value = fn();\n\n if (isDevelopment && fiber.devStrictMode) {\n void fn();\n }\n\n return { value, deps };\n },\n null,\n );\n return state.value;\n};\n"],"mappings":";;;;;AAKA,MAAM,oBAAoB;CACxB,MAAM,IAAI,MAAM,mCAAmC;AACrD;AAIA,MAAa,WAAc,IAAa,SAAgC;CACtE,MAAM,QAAQ,wBAAwB;CACtC,MAAM,CAAC,SAAS,2BACd,cACC,UAA6C;EAC5C,IAAI,SAAS,iBAAiB,MAAM,MAAM,IAAI,GAAG,OAAO;EAExD,MAAM,QAAQ,GAAG;EAEjB,IAAI,iBAAiB,MAAM,eACzB,GAAQ;EAGV,OAAO;GAAE;GAAO;EAAK;CACvB,GACA,IACF;CACA,OAAO,MAAM;AACf"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
//#region src/hooks/tap-reducer.d.ts
|
|
2
|
-
type Dispatch<A> = (action: A) => void;
|
|
3
|
-
declare function tapReducer<S, A>(reducer: (state: S, action: A) => S, initialState: S): [S, Dispatch<A>];
|
|
4
|
-
declare function tapReducer<S, A, I>(reducer: (state: S, action: A) => S, initialArg: I, init: (arg: I) => S): [S, Dispatch<A>];
|
|
5
|
-
declare function tapReducerWithDerivedState<S, A, R extends S>(reducer: (state: S, action: A) => S, getDerivedState: (state: S) => R, initialState: S): [R, Dispatch<A>];
|
|
6
|
-
declare function tapReducerWithDerivedState<S, A, I, R extends S>(reducer: (state: S, action: A) => S, getDerivedState: (state: S) => R, initialArg: I, init: (arg: I) => S): [R, Dispatch<A>];
|
|
7
|
-
//#endregion
|
|
8
|
-
export { tapReducer, tapReducerWithDerivedState };
|
|
9
|
-
//# sourceMappingURL=tap-reducer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-reducer.d.ts","names":[],"sources":["../../src/hooks/tap-reducer.ts"],"mappings":";KAMK,QAAA,OAAe,MAAA,EAAQ,CAAC;AAAA,iBAqGb,UAAA,OACd,OAAA,GAAU,KAAA,EAAO,CAAA,EAAG,MAAA,EAAQ,CAAA,KAAM,CAAA,EAClC,YAAA,EAAc,CAAA,IACZ,CAAA,EAAG,QAAA,CAAS,CAAA;AAAA,iBACA,UAAA,UACd,OAAA,GAAU,KAAA,EAAO,CAAA,EAAG,MAAA,EAAQ,CAAA,KAAM,CAAA,EAClC,UAAA,EAAY,CAAA,EACZ,IAAA,GAAO,GAAA,EAAK,CAAA,KAAM,CAAA,IAChB,CAAA,EAAG,QAAA,CAAS,CAAA;AAAA,iBAcA,0BAAA,iBAA2C,CAAA,EACzD,OAAA,GAAU,KAAA,EAAO,CAAA,EAAG,MAAA,EAAQ,CAAA,KAAM,CAAA,EAClC,eAAA,GAAkB,KAAA,EAAO,CAAA,KAAM,CAAA,EAC/B,YAAA,EAAc,CAAA,IACZ,CAAA,EAAG,QAAA,CAAS,CAAA;AAAA,iBACA,0BAAA,oBAA8C,CAAA,EAC5D,OAAA,GAAU,KAAA,EAAO,CAAA,EAAG,MAAA,EAAQ,CAAA,KAAM,CAAA,EAClC,eAAA,GAAkB,KAAA,EAAO,CAAA,KAAM,CAAA,EAC/B,UAAA,EAAY,CAAA,EACZ,IAAA,GAAO,GAAA,EAAK,CAAA,KAAM,CAAA,IAChB,CAAA,EAAG,QAAA,CAAS,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-reducer.js","names":[],"sources":["../../src/hooks/tap-reducer.ts"],"sourcesContent":["import { isDevelopment } from \"../core/helpers/env\";\nimport { getCurrentResourceFiber } from \"../core/helpers/execution-context\";\nimport type { ReducerQueueEntry, ResourceFiber } from \"../core/types\";\nimport { markCellDirty } from \"../core/helpers/root\";\nimport { tapHook } from \"./utils/tapHook\";\n\ntype Dispatch<A> = (action: A) => void;\n\nconst dispatchOnFiber = (\n fiber: ResourceFiber<any, any>,\n callback: () => (() => void) | null,\n): void => {\n if (fiber.renderContext) {\n throw new Error(\"Resource updated during render\");\n }\n if (fiber.isNeverMounted) {\n throw new Error(\"Resource updated before mount\");\n }\n\n fiber.root.dispatchUpdate(() => {\n const result = callback();\n if (result) {\n result();\n fiber.root.changelog.push(result);\n return true;\n }\n return false;\n });\n};\n\nfunction tapReducerImpl<S, A, I, R extends S>(\n reducer: (state: S, action: A) => S,\n getDerivedState: ((state: S) => R) | undefined,\n initialArg: S | I,\n initFn: ((arg: I) => S) | undefined,\n): [R, Dispatch<A>] {\n const cell = tapHook(\"reducer\", () => {\n const fiber = getCurrentResourceFiber();\n\n // First render: compute initial state\n const initialState = initFn ? initFn(initialArg as I) : initialArg;\n\n if (isDevelopment && fiber.devStrictMode && initFn) {\n void initFn(initialArg as I);\n }\n\n return {\n type: \"reducer\",\n queue: new Set(),\n dirty: false,\n workInProgress: initialState,\n current: initialState,\n reducer,\n dispatch: (action: A) => {\n const entry: ReducerQueueEntry = {\n action,\n hasEagerState: false,\n eagerState: undefined,\n };\n\n dispatchOnFiber(fiber, () => {\n if (fiber.root.dirtyCells.length === 0 && !entry.hasEagerState) {\n entry.eagerState = reducer(cell.workInProgress, action);\n entry.hasEagerState = true;\n\n if (Object.is(cell.current, entry.eagerState)) return null;\n }\n\n return () => {\n markCellDirty(fiber, cell);\n cell.queue.add(entry);\n };\n });\n },\n };\n });\n\n const fiber = getCurrentResourceFiber();\n const sameReducer = reducer === cell.reducer;\n cell.reducer = reducer;\n\n for (const item of cell.queue) {\n if (!item.hasEagerState || !sameReducer) {\n item.eagerState = reducer(cell.workInProgress, item.action);\n item.hasEagerState = true;\n }\n\n if (isDevelopment && fiber.devStrictMode) {\n void reducer(cell.workInProgress, item.action);\n }\n\n cell.workInProgress = item.eagerState;\n }\n cell.queue.clear();\n\n if (getDerivedState) {\n const derived = getDerivedState(cell.workInProgress);\n\n if (!Object.is(derived, cell.workInProgress)) {\n markCellDirty(fiber, cell);\n cell.workInProgress = derived;\n }\n }\n\n return [cell.workInProgress, cell.dispatch];\n}\n\nexport function tapReducer<S, A>(\n reducer: (state: S, action: A) => S,\n initialState: S,\n): [S, Dispatch<A>];\nexport function tapReducer<S, A, I>(\n reducer: (state: S, action: A) => S,\n initialArg: I,\n init: (arg: I) => S,\n): [S, Dispatch<A>];\nexport function tapReducer<S, A, I>(\n reducer: (state: S, action: A) => S,\n initialArg: S | I,\n init?: (arg: I) => S,\n): [S, Dispatch<A>] {\n return tapReducerImpl(\n reducer,\n undefined,\n initialArg as S,\n init as ((arg: S) => S) | undefined,\n );\n}\n\nexport function tapReducerWithDerivedState<S, A, R extends S>(\n reducer: (state: S, action: A) => S,\n getDerivedState: (state: S) => R,\n initialState: S,\n): [R, Dispatch<A>];\nexport function tapReducerWithDerivedState<S, A, I, R extends S>(\n reducer: (state: S, action: A) => S,\n getDerivedState: (state: S) => R,\n initialArg: I,\n init: (arg: I) => S,\n): [R, Dispatch<A>];\nexport function tapReducerWithDerivedState<S, A, I, R extends S>(\n reducer: (state: S, action: A) => S,\n getDerivedState: (state: S) => R,\n initialArg: I,\n init?: (arg: I) => S,\n): [R, Dispatch<A>] {\n return tapReducerImpl(reducer, getDerivedState, initialArg, init);\n}\n"],"mappings":";;;;;AAQA,MAAM,mBACJ,OACA,aACS;CACT,IAAI,MAAM,eACR,MAAM,IAAI,MAAM,gCAAgC;CAElD,IAAI,MAAM,gBACR,MAAM,IAAI,MAAM,+BAA+B;CAGjD,MAAM,KAAK,qBAAqB;EAC9B,MAAM,SAAS,SAAS;EACxB,IAAI,QAAQ;GACV,OAAO;GACP,MAAM,KAAK,UAAU,KAAK,MAAM;GAChC,OAAO;EACT;EACA,OAAO;CACT,CAAC;AACH;AAEA,SAAS,eACP,SACA,iBACA,YACA,QACkB;CAClB,MAAM,OAAO,QAAQ,iBAAiB;EACpC,MAAM,QAAQ,wBAAwB;EAGtC,MAAM,eAAe,SAAS,OAAO,UAAe,IAAI;EAExD,IAAI,iBAAiB,MAAM,iBAAiB,QAC1C,OAAY,UAAe;EAG7B,OAAO;GACL,MAAM;GACN,uBAAO,IAAI,IAAI;GACf,OAAO;GACP,gBAAgB;GAChB,SAAS;GACT;GACA,WAAW,WAAc;IACvB,MAAM,QAA2B;KAC/B;KACA,eAAe;KACf,YAAY,KAAA;IACd;IAEA,gBAAgB,aAAa;KAC3B,IAAI,MAAM,KAAK,WAAW,WAAW,KAAK,CAAC,MAAM,eAAe;MAC9D,MAAM,aAAa,QAAQ,KAAK,gBAAgB,MAAM;MACtD,MAAM,gBAAgB;MAEtB,IAAI,OAAO,GAAG,KAAK,SAAS,MAAM,UAAU,GAAG,OAAO;KACxD;KAEA,aAAa;MACX,cAAc,OAAO,IAAI;MACzB,KAAK,MAAM,IAAI,KAAK;KACtB;IACF,CAAC;GACH;EACF;CACF,CAAC;CAED,MAAM,QAAQ,wBAAwB;CACtC,MAAM,cAAc,YAAY,KAAK;CACrC,KAAK,UAAU;CAEf,KAAK,MAAM,QAAQ,KAAK,OAAO;EAC7B,IAAI,CAAC,KAAK,iBAAiB,CAAC,aAAa;GACvC,KAAK,aAAa,QAAQ,KAAK,gBAAgB,KAAK,MAAM;GAC1D,KAAK,gBAAgB;EACvB;EAEA,IAAI,iBAAiB,MAAM,eACzB,QAAa,KAAK,gBAAgB,KAAK,MAAM;EAG/C,KAAK,iBAAiB,KAAK;CAC7B;CACA,KAAK,MAAM,MAAM;CAEjB,IAAI,iBAAiB;EACnB,MAAM,UAAU,gBAAgB,KAAK,cAAc;EAEnD,IAAI,CAAC,OAAO,GAAG,SAAS,KAAK,cAAc,GAAG;GAC5C,cAAc,OAAO,IAAI;GACzB,KAAK,iBAAiB;EACxB;CACF;CAEA,OAAO,CAAC,KAAK,gBAAgB,KAAK,QAAQ;AAC5C;AAWA,SAAgB,WACd,SACA,YACA,MACkB;CAClB,OAAO,eACL,SACA,KAAA,GACA,YACA,IACF;AACF;AAaA,SAAgB,2BACd,SACA,iBACA,YACA,MACkB;CAClB,OAAO,eAAe,SAAS,iBAAiB,YAAY,IAAI;AAClE"}
|
package/dist/hooks/tap-ref.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
//#region src/hooks/tap-ref.d.ts
|
|
2
|
-
declare namespace tapRef {
|
|
3
|
-
interface RefObject<T> {
|
|
4
|
-
current: T;
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
declare function tapRef<T>(initialValue: T): tapRef.RefObject<T>;
|
|
8
|
-
declare function tapRef<T = undefined>(): tapRef.RefObject<T | undefined>;
|
|
9
|
-
//#endregion
|
|
10
|
-
export { tapRef };
|
|
11
|
-
//# sourceMappingURL=tap-ref.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap-ref.d.ts","names":[],"sources":["../../src/hooks/tap-ref.ts"],"mappings":";kBAEiB,MAAA;EAAA,UACE,SAAA;IACf,OAAA,EAAS,CAAC;EAAA;AAAA;AAAA,iBAIE,MAAA,IAAU,YAAA,EAAc,CAAA,GAAI,MAAA,CAAO,SAAA,CAAU,CAAA;AAAA,iBAC7C,MAAA,mBAAyB,MAAA,CAAO,SAAS,CAAC,CAAA"}
|