@assistant-ui/tap 0.3.6 → 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 +24 -23
- package/dist/core/ResourceFiber.d.ts +1 -1
- package/dist/core/ResourceFiber.d.ts.map +1 -1
- package/dist/core/ResourceFiber.js +15 -8
- package/dist/core/ResourceFiber.js.map +1 -1
- package/dist/core/commit.d.ts +1 -1
- package/dist/core/commit.d.ts.map +1 -1
- package/dist/core/commit.js +30 -48
- package/dist/core/commit.js.map +1 -1
- package/dist/core/context.d.ts +2 -2
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/context.js +2 -2
- package/dist/core/context.js.map +1 -1
- package/dist/core/createResource.d.ts +3 -2
- package/dist/core/createResource.d.ts.map +1 -1
- package/dist/core/createResource.js +33 -19
- package/dist/core/createResource.js.map +1 -1
- package/dist/core/env.d.ts +2 -0
- package/dist/core/env.d.ts.map +1 -0
- package/dist/core/env.js +3 -0
- package/dist/core/env.js.map +1 -0
- package/dist/core/execution-context.d.ts +1 -0
- package/dist/core/execution-context.d.ts.map +1 -1
- package/dist/core/execution-context.js +8 -0
- package/dist/core/execution-context.js.map +1 -1
- package/dist/core/resource.d.ts +3 -3
- package/dist/core/resource.d.ts.map +1 -1
- package/dist/core/resource.js.map +1 -1
- package/dist/core/scheduler.d.ts +1 -1
- package/dist/core/scheduler.d.ts.map +1 -1
- package/dist/core/scheduler.js +1 -1
- package/dist/core/scheduler.js.map +1 -1
- package/dist/core/types.d.ts +22 -21
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/withKey.d.ts +3 -0
- package/dist/core/withKey.d.ts.map +1 -0
- package/dist/core/withKey.js +4 -0
- package/dist/core/withKey.js.map +1 -0
- package/dist/hooks/tap-callback.d.ts.map +1 -1
- package/dist/hooks/tap-callback.js +1 -0
- package/dist/hooks/tap-callback.js.map +1 -1
- package/dist/hooks/tap-const.d.ts +2 -0
- package/dist/hooks/tap-const.d.ts.map +1 -0
- package/dist/hooks/tap-const.js +6 -0
- package/dist/hooks/tap-const.js.map +1 -0
- package/dist/hooks/tap-effect-event.d.ts.map +1 -1
- package/dist/hooks/tap-effect-event.js +11 -0
- package/dist/hooks/tap-effect-event.js.map +1 -1
- package/dist/hooks/tap-effect.d.ts.map +1 -1
- package/dist/hooks/tap-effect.js +43 -31
- package/dist/hooks/tap-effect.js.map +1 -1
- package/dist/hooks/tap-inline-resource.d.ts +2 -2
- package/dist/hooks/tap-inline-resource.d.ts.map +1 -1
- package/dist/hooks/tap-memo.js +1 -1
- package/dist/hooks/tap-memo.js.map +1 -1
- package/dist/hooks/tap-resource.d.ts +3 -3
- package/dist/hooks/tap-resource.d.ts.map +1 -1
- package/dist/hooks/tap-resource.js +17 -9
- package/dist/hooks/tap-resource.js.map +1 -1
- package/dist/hooks/tap-resources.d.ts +2 -10
- package/dist/hooks/tap-resources.d.ts.map +1 -1
- package/dist/hooks/tap-resources.js +74 -43
- package/dist/hooks/tap-resources.js.map +1 -1
- package/dist/hooks/tap-state.d.ts.map +1 -1
- package/dist/hooks/tap-state.js +37 -24
- package/dist/hooks/tap-state.js.map +1 -1
- package/dist/hooks/utils/depsShallowEqual.d.ts.map +1 -0
- package/dist/hooks/utils/depsShallowEqual.js.map +1 -0
- package/dist/hooks/utils/tapHook.d.ts +6 -0
- package/dist/hooks/utils/tapHook.d.ts.map +1 -0
- package/dist/hooks/utils/tapHook.js +24 -0
- package/dist/hooks/utils/tapHook.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/react/use-resource.d.ts +2 -2
- package/dist/react/use-resource.d.ts.map +1 -1
- package/dist/react/use-resource.js +24 -10
- package/dist/react/use-resource.js.map +1 -1
- package/package.json +8 -1
- package/src/__tests__/basic/resourceHandle.test.ts +4 -4
- package/src/__tests__/basic/tapEffect.basic.test.ts +3 -2
- package/src/__tests__/basic/tapResources.basic.test.ts +84 -64
- package/src/__tests__/basic/tapState.basic.test.ts +8 -8
- package/src/__tests__/errors/errors.effect-errors.test.ts +8 -3
- package/src/__tests__/lifecycle/lifecycle.dependencies.test.ts +3 -2
- package/src/__tests__/lifecycle/lifecycle.mount-unmount.test.ts +2 -2
- package/src/__tests__/react/concurrent-mode.test.tsx +243 -0
- package/src/__tests__/strictmode/react-strictmode-behavior.test.tsx +709 -0
- package/src/__tests__/strictmode/react-strictmode-rerender-sources.test.tsx +392 -0
- package/src/__tests__/strictmode/strictmode.test.ts +270 -0
- package/src/__tests__/strictmode/tap-strictmode-rerender-sources.test.ts +723 -0
- package/src/__tests__/test-utils.ts +8 -6
- package/src/core/ResourceFiber.ts +21 -11
- package/src/core/commit.ts +29 -58
- package/src/core/context.ts +2 -2
- package/src/core/createResource.ts +46 -22
- package/src/core/env.ts +3 -0
- package/src/core/execution-context.ts +9 -0
- package/src/core/resource.ts +6 -3
- package/src/core/scheduler.ts +1 -1
- package/src/core/types.ts +25 -26
- package/src/core/withKey.ts +8 -0
- package/src/hooks/tap-callback.ts +1 -0
- package/src/hooks/tap-const.ts +6 -0
- package/src/hooks/tap-effect-event.ts +15 -0
- package/src/hooks/tap-effect.ts +48 -38
- package/src/hooks/tap-inline-resource.ts +2 -2
- package/src/hooks/tap-memo.ts +1 -1
- package/src/hooks/tap-resource.ts +24 -20
- package/src/hooks/tap-resources.ts +86 -63
- package/src/hooks/tap-state.ts +49 -26
- package/src/hooks/utils/tapHook.ts +35 -0
- package/src/index.ts +8 -3
- package/src/react/use-resource.ts +27 -16
- package/dist/hooks/depsShallowEqual.d.ts.map +0 -1
- package/dist/hooks/depsShallowEqual.js.map +0 -1
- /package/dist/hooks/{depsShallowEqual.d.ts → utils/depsShallowEqual.d.ts} +0 -0
- /package/dist/hooks/{depsShallowEqual.js → utils/depsShallowEqual.js} +0 -0
- /package/src/hooks/{depsShallowEqual.ts → utils/depsShallowEqual.ts} +0 -0
package/dist/hooks/tap-state.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import { isDevelopment } from "../core/env.js";
|
|
1
2
|
import { getCurrentResourceFiber } from "../core/execution-context.js";
|
|
2
|
-
const
|
|
3
|
+
const dispatchOnFiber = (fiber, callback) => {
|
|
3
4
|
if (fiber.renderContext) {
|
|
4
5
|
throw new Error("Resource updated during render");
|
|
5
6
|
}
|
|
6
7
|
if (fiber.isMounted) {
|
|
7
8
|
// Only schedule rerender if currently mounted
|
|
8
|
-
fiber.
|
|
9
|
+
fiber.dispatchUpdate(callback);
|
|
9
10
|
}
|
|
10
11
|
else if (fiber.isNeverMounted) {
|
|
11
12
|
throw new Error("Resource updated before mount");
|
|
12
13
|
}
|
|
14
|
+
// TODO mark dirty
|
|
13
15
|
};
|
|
14
16
|
function getStateCell(initialValue) {
|
|
15
17
|
const fiber = getCurrentResourceFiber();
|
|
@@ -19,32 +21,43 @@ function getStateCell(initialValue) {
|
|
|
19
21
|
throw new Error("Rendered more hooks than during the previous render. " +
|
|
20
22
|
"Hooks must be called in the exact same order in every render.");
|
|
21
23
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
const cell = fiber.cells[index];
|
|
25
|
+
if (cell) {
|
|
26
|
+
if (cell.type !== "state")
|
|
27
|
+
throw new Error("Hook order changed between renders");
|
|
28
|
+
return cell;
|
|
29
|
+
}
|
|
30
|
+
const value = typeof initialValue === "function"
|
|
31
|
+
? initialValue()
|
|
32
|
+
: initialValue;
|
|
33
|
+
if (isDevelopment &&
|
|
34
|
+
fiber.devStrictMode &&
|
|
35
|
+
typeof initialValue === "function") {
|
|
36
|
+
void initialValue();
|
|
37
|
+
}
|
|
38
|
+
const newCell = {
|
|
39
|
+
type: "state",
|
|
40
|
+
value,
|
|
41
|
+
set: (updater) => {
|
|
42
|
+
dispatchOnFiber(fiber, () => {
|
|
43
|
+
const currentValue = newCell.value;
|
|
32
44
|
const nextValue = typeof updater === "function"
|
|
33
45
|
? updater(currentValue)
|
|
34
46
|
: updater;
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
if (isDevelopment &&
|
|
48
|
+
fiber.devStrictMode &&
|
|
49
|
+
typeof updater === "function") {
|
|
50
|
+
void updater(currentValue);
|
|
38
51
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return
|
|
52
|
+
if (Object.is(currentValue, nextValue))
|
|
53
|
+
return false;
|
|
54
|
+
newCell.value = nextValue;
|
|
55
|
+
return true;
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
fiber.cells[index] = newCell;
|
|
60
|
+
return newCell;
|
|
48
61
|
}
|
|
49
62
|
export function tapState(initial) {
|
|
50
63
|
const cell = getStateCell(initial);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tap-state.js","sourceRoot":"","sources":["../../src/hooks/tap-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,qCAAkC;AAOpE,MAAM,
|
|
1
|
+
{"version":3,"file":"tap-state.js","sourceRoot":"","sources":["../../src/hooks/tap-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,uBAAoB;AAC5C,OAAO,EAAE,uBAAuB,EAAE,qCAAkC;AAOpE,MAAM,eAAe,GAAG,CACtB,KAA8B,EAC9B,QAAuB,EACvB,EAAE;IACF,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACpB,8CAA8C;QAC9C,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;SAAM,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,kBAAkB;AACpB,CAAC,CAAC;AAEF,SAAS,YAAY,CACnB,YAA2B;IAE3B,MAAM,KAAK,GAAG,uBAAuB,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;IAEnC,mEAAmE;IACnE,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CACb,uDAAuD;YACrD,+DAA+D,CAClE,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;YACvB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAExD,OAAO,IAAgC,CAAC;IAC1C,CAAC;IAED,MAAM,KAAK,GACT,OAAO,YAAY,KAAK,UAAU;QAChC,CAAC,CAAE,YAAwB,EAAE;QAC7B,CAAC,CAAC,YAAY,CAAC;IAEnB,IACE,aAAa;QACb,KAAK,CAAC,aAAa;QACnB,OAAO,YAAY,KAAK,UAAU,EAClC,CAAC;QACD,KAAM,YAAwB,EAAE,CAAC;IACnC,CAAC;IAED,MAAM,OAAO,GAA6B;QACxC,IAAI,EAAE,OAAO;QACb,KAAK;QACL,GAAG,EAAE,CAAC,OAAiC,EAAE,EAAE;YACzC,eAAe,CAAC,KAAK,EAAE,GAAG,EAAE;gBAC1B,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC;gBACnC,MAAM,SAAS,GACb,OAAO,OAAO,KAAK,UAAU;oBAC3B,CAAC,CAAE,OAA0B,CAAC,YAAY,CAAC;oBAC3C,CAAC,CAAC,OAAO,CAAC;gBAEd,IACE,aAAa;oBACb,KAAK,CAAC,aAAa;oBACnB,OAAO,OAAO,KAAK,UAAU,EAC7B,CAAC;oBACD,KAAM,OAA0B,CAAC,YAAY,CAAC,CAAC;gBACjD,CAAC;gBAED,IAAI,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,SAAS,CAAC;oBAAE,OAAO,KAAK,CAAC;gBAErD,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC;gBAC1B,OAAO,IAAI,CAAC;YACd,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;IAEF,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;IAC7B,OAAO,OAAO,CAAC;AACjB,CAAC;AASD,MAAM,UAAU,QAAQ,CACtB,OAAuB;IAEvB,MAAM,IAAI,GAAG,YAAY,CAAC,OAAwB,CAAC,CAAC;IAEpD,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"depsShallowEqual.d.ts","sourceRoot":"","sources":["../../../src/hooks/utils/depsShallowEqual.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,GAC3B,GAAG,SAAS,OAAO,EAAE,EACrB,GAAG,SAAS,OAAO,EAAE,YAOtB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"depsShallowEqual.js","sourceRoot":"","sources":["../../../src/hooks/utils/depsShallowEqual.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,CAAqB,EACrB,CAAqB,EACrB,EAAE;IACF,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IAC3C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Cell } from "../../core/types.js";
|
|
2
|
+
export declare const tapHook: <T extends "effect" | "memo">(type: T, init: () => Cell) => Cell & {
|
|
3
|
+
type: T;
|
|
4
|
+
};
|
|
5
|
+
export declare const registerRenderMountTask: (task: () => void) => void;
|
|
6
|
+
//# sourceMappingURL=tapHook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tapHook.d.ts","sourceRoot":"","sources":["../../../src/hooks/utils/tapHook.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,4BAAyB;AAExC,eAAO,MAAM,OAAO,GAAI,CAAC,SAAS,QAAQ,GAAG,MAAM,EACjD,MAAM,CAAC,EACP,MAAM,MAAM,IAAI,KACf,IAAI,GAAG;IAAE,IAAI,EAAE,CAAC,CAAA;CAuBlB,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,IAAI,SAGvD,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getCurrentResourceFiber } from "../../core/execution-context.js";
|
|
2
|
+
export const tapHook = (type, init) => {
|
|
3
|
+
const fiber = getCurrentResourceFiber();
|
|
4
|
+
const index = fiber.currentIndex++;
|
|
5
|
+
if (!fiber.isFirstRender && index >= fiber.cells.length) {
|
|
6
|
+
// Check if we're trying to use more hooks than in previous renders
|
|
7
|
+
throw new Error("Rendered more hooks than during the previous render. " +
|
|
8
|
+
"Hooks must be called in the exact same order in every render.");
|
|
9
|
+
}
|
|
10
|
+
let cell = fiber.cells[index];
|
|
11
|
+
if (!cell) {
|
|
12
|
+
cell = init();
|
|
13
|
+
fiber.cells[index] = cell;
|
|
14
|
+
}
|
|
15
|
+
if (cell.type !== type) {
|
|
16
|
+
throw new Error("Hook order changed between renders");
|
|
17
|
+
}
|
|
18
|
+
return cell;
|
|
19
|
+
};
|
|
20
|
+
export const registerRenderMountTask = (task) => {
|
|
21
|
+
const fiber = getCurrentResourceFiber();
|
|
22
|
+
fiber.renderContext.commitTasks.push(task);
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=tapHook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tapHook.js","sourceRoot":"","sources":["../../../src/hooks/utils/tapHook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,wCAAqC;AAGvE,MAAM,CAAC,MAAM,OAAO,GAAG,CACrB,IAAO,EACP,IAAgB,EACI,EAAE;IACtB,MAAM,KAAK,GAAG,uBAAuB,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;IAEnC,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACxD,mEAAmE;QACnE,MAAM,IAAI,KAAK,CACb,uDAAuD;YACrD,+DAA+D,CAClE,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,GAAG,IAAI,EAAE,CAAC;QACd,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,IAA0B,CAAC;AACpC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,IAAgB,EAAE,EAAE;IAC1D,MAAM,KAAK,GAAG,uBAAuB,EAAE,CAAC;IACxC,KAAK,CAAC,aAAc,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9C,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { resource } from "./core/resource.js";
|
|
2
|
+
export { withKey } from "./core/withKey.js";
|
|
2
3
|
export { tapState } from "./hooks/tap-state.js";
|
|
3
4
|
export { tapEffect } from "./hooks/tap-effect.js";
|
|
4
5
|
export { tapRef } from "./hooks/tap-ref.js";
|
|
6
|
+
export { tapConst } from "./hooks/tap-const.js";
|
|
5
7
|
export { tapMemo } from "./hooks/tap-memo.js";
|
|
6
8
|
export { tapCallback } from "./hooks/tap-callback.js";
|
|
7
9
|
export { tapEffectEvent } from "./hooks/tap-effect-event.js";
|
|
@@ -9,7 +11,7 @@ export { tapResource } from "./hooks/tap-resource.js";
|
|
|
9
11
|
export { tapInlineResource } from "./hooks/tap-inline-resource.js";
|
|
10
12
|
export { tapResources } from "./hooks/tap-resources.js";
|
|
11
13
|
export { createResource } from "./core/createResource.js";
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
14
|
-
export type { Resource, ContravariantResource, ResourceElement,
|
|
14
|
+
export { flushResourcesSync } from "./core/scheduler.js";
|
|
15
|
+
export { createResourceContext, tap, withContextProvider, } from "./core/context.js";
|
|
16
|
+
export type { Resource, ContravariantResource, ResourceElement, } from "./core/types.js";
|
|
15
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,2BAAwB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,2BAAwB;AAC3C,OAAO,EAAE,OAAO,EAAE,0BAAuB;AAGzC,OAAO,EAAE,QAAQ,EAAE,6BAA0B;AAC7C,OAAO,EAAE,SAAS,EAAE,8BAA2B;AAG/C,OAAO,EAAE,MAAM,EAAE,2BAAwB;AACzC,OAAO,EAAE,QAAQ,EAAE,6BAA0B;AAC7C,OAAO,EAAE,OAAO,EAAE,4BAAyB;AAC3C,OAAO,EAAE,WAAW,EAAE,gCAA6B;AACnD,OAAO,EAAE,cAAc,EAAE,oCAAiC;AAG1D,OAAO,EAAE,WAAW,EAAE,gCAA6B;AACnD,OAAO,EAAE,iBAAiB,EAAE,uCAAoC;AAChE,OAAO,EAAE,YAAY,EAAE,iCAA8B;AAGrD,OAAO,EAAE,cAAc,EAAE,iCAA8B;AACvD,OAAO,EAAE,kBAAkB,EAAE,4BAAyB;AAGtD,OAAO,EACL,qBAAqB,EACrB,GAAG,EACH,mBAAmB,GACpB,0BAAuB;AAGxB,YAAY,EACV,QAAQ,EACR,qBAAqB,EACrB,eAAe,GAChB,wBAAqB"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export { resource } from "./core/resource.js";
|
|
2
|
+
export { withKey } from "./core/withKey.js";
|
|
2
3
|
// primitive hooks
|
|
3
4
|
export { tapState } from "./hooks/tap-state.js";
|
|
4
5
|
export { tapEffect } from "./hooks/tap-effect.js";
|
|
5
6
|
// utility hooks
|
|
6
7
|
export { tapRef } from "./hooks/tap-ref.js";
|
|
8
|
+
export { tapConst } from "./hooks/tap-const.js";
|
|
7
9
|
export { tapMemo } from "./hooks/tap-memo.js";
|
|
8
10
|
export { tapCallback } from "./hooks/tap-callback.js";
|
|
9
11
|
export { tapEffectEvent } from "./hooks/tap-effect-event.js";
|
|
@@ -13,7 +15,7 @@ export { tapInlineResource } from "./hooks/tap-inline-resource.js";
|
|
|
13
15
|
export { tapResources } from "./hooks/tap-resources.js";
|
|
14
16
|
// imperative
|
|
15
17
|
export { createResource } from "./core/createResource.js";
|
|
16
|
-
export {
|
|
18
|
+
export { flushResourcesSync } from "./core/scheduler.js";
|
|
17
19
|
// context
|
|
18
|
-
export {
|
|
20
|
+
export { createResourceContext, tap, withContextProvider, } from "./core/context.js";
|
|
19
21
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,2BAAwB;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,2BAAwB;AAC3C,OAAO,EAAE,OAAO,EAAE,0BAAuB;AAEzC,kBAAkB;AAClB,OAAO,EAAE,QAAQ,EAAE,6BAA0B;AAC7C,OAAO,EAAE,SAAS,EAAE,8BAA2B;AAE/C,gBAAgB;AAChB,OAAO,EAAE,MAAM,EAAE,2BAAwB;AACzC,OAAO,EAAE,QAAQ,EAAE,6BAA0B;AAC7C,OAAO,EAAE,OAAO,EAAE,4BAAyB;AAC3C,OAAO,EAAE,WAAW,EAAE,gCAA6B;AACnD,OAAO,EAAE,cAAc,EAAE,oCAAiC;AAE1D,YAAY;AACZ,OAAO,EAAE,WAAW,EAAE,gCAA6B;AACnD,OAAO,EAAE,iBAAiB,EAAE,uCAAoC;AAChE,OAAO,EAAE,YAAY,EAAE,iCAA8B;AAErD,aAAa;AACb,OAAO,EAAE,cAAc,EAAE,iCAA8B;AACvD,OAAO,EAAE,kBAAkB,EAAE,4BAAyB;AAEtD,UAAU;AACV,OAAO,EACL,qBAAqB,EACrB,GAAG,EACH,mBAAmB,GACpB,0BAAuB"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function useResource<E extends ResourceElement<any, any>>(element: E):
|
|
1
|
+
import type { ExtractResourceReturnType, ResourceElement } from "../core/types.js";
|
|
2
|
+
export declare function useResource<E extends ResourceElement<any, any>>(element: E): ExtractResourceReturnType<E>;
|
|
3
3
|
//# sourceMappingURL=use-resource.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-resource.d.ts","sourceRoot":"","sources":["../../src/react/use-resource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"use-resource.d.ts","sourceRoot":"","sources":["../../src/react/use-resource.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,eAAe,EAAE,yBAAsB;AAuBhF,wBAAgB,WAAW,CAAC,CAAC,SAAS,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,EAC7D,OAAO,EAAE,CAAC,GACT,yBAAyB,CAAC,CAAC,CAAC,CAmB9B"}
|
|
@@ -1,19 +1,33 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
2
2
|
import { createResourceFiber, unmountResourceFiber, renderResourceFiber, commitResourceFiber, } from "../core/ResourceFiber.js";
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import { isDevelopment } from "../core/env.js";
|
|
4
|
+
const useDevStrictMode = () => {
|
|
5
|
+
if (!isDevelopment)
|
|
6
|
+
return null;
|
|
7
|
+
const count = useRef(0);
|
|
8
|
+
const isFirstRender = count.current === 0;
|
|
9
|
+
useState(() => count.current++);
|
|
10
|
+
if (count.current !== 2)
|
|
11
|
+
return null;
|
|
12
|
+
return isFirstRender ? "child" : "root";
|
|
13
|
+
};
|
|
14
|
+
const resourceReducer = (version, callback) => {
|
|
15
|
+
return version + (callback() ? 1 : 0);
|
|
16
|
+
};
|
|
7
17
|
export function useResource(element) {
|
|
8
|
-
const [,
|
|
9
|
-
const
|
|
18
|
+
const [, dispatch] = useReducer(resourceReducer, 0);
|
|
19
|
+
const devStrictMode = useDevStrictMode();
|
|
20
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: user provided deps instead of prop identity
|
|
21
|
+
const fiber = useMemo(() => {
|
|
22
|
+
return createResourceFiber(element.type, dispatch, devStrictMode);
|
|
23
|
+
}, [element.type, element.key]);
|
|
10
24
|
const result = renderResourceFiber(fiber, element.props);
|
|
11
|
-
|
|
25
|
+
useLayoutEffect(() => {
|
|
12
26
|
return () => unmountResourceFiber(fiber);
|
|
13
27
|
}, [fiber]);
|
|
14
|
-
|
|
28
|
+
useLayoutEffect(() => {
|
|
15
29
|
commitResourceFiber(fiber, result);
|
|
16
30
|
});
|
|
17
|
-
return result.
|
|
31
|
+
return result.output;
|
|
18
32
|
}
|
|
19
33
|
//# sourceMappingURL=use-resource.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-resource.js","sourceRoot":"","sources":["../../src/react/use-resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"use-resource.js","sourceRoot":"","sources":["../../src/react/use-resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE/E,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,GACpB,iCAA8B;AAC/B,OAAO,EAAE,aAAa,EAAE,uBAAoB;AAE5C,MAAM,gBAAgB,GAAG,GAAG,EAAE;IAC5B,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAEhC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC;IAC1C,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,OAAO,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,aAAa,CAAC,CAAC,CAAE,OAAiB,CAAC,CAAC,CAAE,MAAgB,CAAC;AAChE,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,OAAe,EAAE,QAAuB,EAAE,EAAE;IACnE,OAAO,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF,MAAM,UAAU,WAAW,CACzB,OAAU;IAEV,MAAM,CAAC,EAAE,QAAQ,CAAC,GAAG,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAEpD,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IAEzC,uGAAuG;IACvG,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE;QACzB,OAAO,mBAAmB,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IACpE,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACzD,eAAe,CAAC,GAAG,EAAE;QACnB,OAAO,GAAG,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACZ,eAAe,CAAC,GAAG,EAAE;QACnB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/tap",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Zero-dependency reactive state management inspired by React hooks",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"state-management",
|
|
@@ -46,8 +46,15 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
+
"@testing-library/dom": "^10.4.1",
|
|
50
|
+
"@testing-library/react": "^16.3.1",
|
|
49
51
|
"@types/react": "^19.2.9",
|
|
52
|
+
"@types/node": "^25.0.3",
|
|
53
|
+
"@types/react-dom": "^19.2.3",
|
|
50
54
|
"@vitest/ui": "^4.0.17",
|
|
55
|
+
"react": "19.2.3",
|
|
56
|
+
"react-dom": "19.2.3",
|
|
57
|
+
"jsdom": "^27.3.0",
|
|
51
58
|
"vitest": "^4.0.17",
|
|
52
59
|
"@assistant-ui/x-buildutils": "0.0.1"
|
|
53
60
|
},
|
|
@@ -13,13 +13,13 @@ describe("ResourceHandle - Basic Usage", () => {
|
|
|
13
13
|
const handle = createResource(TestResource(5));
|
|
14
14
|
|
|
15
15
|
// The handle provides a const API
|
|
16
|
-
expect(typeof handle.
|
|
16
|
+
expect(typeof handle.getValue).toBe("function");
|
|
17
17
|
expect(typeof handle.subscribe).toBe("function");
|
|
18
18
|
expect(typeof handle.render).toBe("function");
|
|
19
19
|
|
|
20
20
|
// Initial state
|
|
21
|
-
expect(handle.
|
|
22
|
-
expect(handle.
|
|
21
|
+
expect(handle.getValue().value).toBe(10);
|
|
22
|
+
expect(handle.getValue().propsUsed).toBe(5);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
it("should allow updating props", () => {
|
|
@@ -29,7 +29,7 @@ describe("ResourceHandle - Basic Usage", () => {
|
|
|
29
29
|
const handle = createResource(TestResource({ multiplier: 2 }));
|
|
30
30
|
|
|
31
31
|
// Initial state
|
|
32
|
-
expect(handle.
|
|
32
|
+
expect(handle.getValue().result).toBe(20);
|
|
33
33
|
|
|
34
34
|
// Can call render to update props
|
|
35
35
|
expect(() => handle.render(TestResource({ multiplier: 3 }))).not.toThrow();
|
|
@@ -60,7 +60,7 @@ describe("tapEffect - Basic Functionality", () => {
|
|
|
60
60
|
expect(cleanup).toHaveBeenCalledTimes(1);
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
-
it("should cleanup effects in
|
|
63
|
+
it("should cleanup effects in same order", () => {
|
|
64
64
|
const cleanupOrder: string[] = [];
|
|
65
65
|
|
|
66
66
|
const testFiber = createTestResource(() => {
|
|
@@ -84,7 +84,7 @@ describe("tapEffect - Basic Functionality", () => {
|
|
|
84
84
|
manager.cleanup();
|
|
85
85
|
|
|
86
86
|
// Cleanup should run in reverse order (LIFO)
|
|
87
|
-
expect(cleanupOrder).toEqual(["
|
|
87
|
+
expect(cleanupOrder).toEqual(["first", "second", "third"]);
|
|
88
88
|
});
|
|
89
89
|
});
|
|
90
90
|
|
|
@@ -131,6 +131,7 @@ describe("tapEffect - Basic Functionality", () => {
|
|
|
131
131
|
}, []);
|
|
132
132
|
|
|
133
133
|
// Effect with deps - runs when deps change
|
|
134
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: test
|
|
134
135
|
tapEffect(() => {
|
|
135
136
|
effectCalls.conditional++;
|
|
136
137
|
}, [props.value]);
|
|
@@ -2,6 +2,7 @@ import { describe, it, expect, afterEach } from "vitest";
|
|
|
2
2
|
import { tapResources } from "../../hooks/tap-resources";
|
|
3
3
|
import { tapState } from "../../hooks/tap-state";
|
|
4
4
|
import { resource } from "../../core/resource";
|
|
5
|
+
import { withKey } from "../../core/withKey";
|
|
5
6
|
import {
|
|
6
7
|
createTestResource,
|
|
7
8
|
renderTest,
|
|
@@ -59,8 +60,11 @@ describe("tapResources - Basic Functionality", () => {
|
|
|
59
60
|
it("should render multiple resources with keys", () => {
|
|
60
61
|
const testFiber = createTestResource(() => {
|
|
61
62
|
const results = tapResources(
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
() => [
|
|
64
|
+
withKey("a", SimpleCounter({ value: 10 })),
|
|
65
|
+
withKey("b", SimpleCounter({ value: 20 })),
|
|
66
|
+
withKey("c", SimpleCounter({ value: 30 })),
|
|
67
|
+
],
|
|
64
68
|
[],
|
|
65
69
|
);
|
|
66
70
|
|
|
@@ -68,11 +72,7 @@ describe("tapResources - Basic Functionality", () => {
|
|
|
68
72
|
});
|
|
69
73
|
|
|
70
74
|
const result = renderTest(testFiber, undefined);
|
|
71
|
-
expect(result).toEqual({
|
|
72
|
-
a: { count: 10 },
|
|
73
|
-
b: { count: 20 },
|
|
74
|
-
c: { count: 30 },
|
|
75
|
-
});
|
|
75
|
+
expect(result).toEqual([{ count: 10 }, { count: 20 }, { count: 30 }]);
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
it("should work with resource constructor syntax", () => {
|
|
@@ -82,15 +82,17 @@ describe("tapResources - Basic Functionality", () => {
|
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
const testFiber = createTestResource(() => {
|
|
85
|
-
const items =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
const items = [
|
|
86
|
+
{ key: "first", value: 5 },
|
|
87
|
+
{ key: "second", value: 10 },
|
|
88
|
+
{ key: "third", value: 15 },
|
|
89
|
+
];
|
|
90
90
|
|
|
91
91
|
const results = tapResources(
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
() =>
|
|
93
|
+
items.map((item) =>
|
|
94
|
+
withKey(item.key, Counter({ value: item.value })),
|
|
95
|
+
),
|
|
94
96
|
[],
|
|
95
97
|
);
|
|
96
98
|
|
|
@@ -98,56 +100,66 @@ describe("tapResources - Basic Functionality", () => {
|
|
|
98
100
|
});
|
|
99
101
|
|
|
100
102
|
const result = renderTest(testFiber, undefined);
|
|
101
|
-
expect(result).toEqual(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
expect(result).toEqual([
|
|
104
|
+
{ count: 5, double: 10 },
|
|
105
|
+
{ count: 10, double: 20 },
|
|
106
|
+
{ count: 15, double: 30 },
|
|
107
|
+
]);
|
|
106
108
|
});
|
|
107
109
|
});
|
|
108
110
|
|
|
109
111
|
describe("Instance Preservation", () => {
|
|
110
112
|
it("should maintain resource instances when keys remain the same", () => {
|
|
111
113
|
const testFiber = createTestResource(
|
|
112
|
-
(props: {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
114
|
+
(props: {
|
|
115
|
+
items: Array<{ key: string; value: number; id: string }>;
|
|
116
|
+
}) => {
|
|
117
|
+
return tapResources(() => {
|
|
118
|
+
return props.items.map((item) =>
|
|
119
|
+
withKey(
|
|
120
|
+
item.key,
|
|
121
|
+
TrackingCounter({ value: item.value, id: item.id }),
|
|
122
|
+
),
|
|
123
|
+
);
|
|
124
|
+
}, [props.items]);
|
|
119
125
|
},
|
|
120
126
|
);
|
|
121
127
|
|
|
122
128
|
// Initial render
|
|
123
129
|
const result1 = renderTest(testFiber, {
|
|
124
|
-
items:
|
|
130
|
+
items: [
|
|
131
|
+
{ key: "a", value: 1, id: "a" },
|
|
132
|
+
{ key: "b", value: 2, id: "b" },
|
|
133
|
+
],
|
|
125
134
|
});
|
|
126
135
|
|
|
127
136
|
// Verify initial state
|
|
128
|
-
expect(result1
|
|
137
|
+
expect(result1[0]).toMatchObject({
|
|
129
138
|
id: "a",
|
|
130
139
|
value: 1,
|
|
131
140
|
renderCount: 1,
|
|
132
141
|
});
|
|
133
|
-
expect(result1
|
|
142
|
+
expect(result1[1]).toMatchObject({
|
|
134
143
|
id: "b",
|
|
135
144
|
value: 2,
|
|
136
145
|
renderCount: 1,
|
|
137
146
|
});
|
|
138
147
|
|
|
139
|
-
// Re-render with same keys but different values
|
|
148
|
+
// Re-render with same keys but different order and values
|
|
140
149
|
const result2 = renderTest(testFiber, {
|
|
141
|
-
items:
|
|
150
|
+
items: [
|
|
151
|
+
{ key: "b", value: 20, id: "b" },
|
|
152
|
+
{ key: "a", value: 10, id: "a" },
|
|
153
|
+
],
|
|
142
154
|
});
|
|
143
155
|
|
|
144
|
-
// Verify instances are preserved
|
|
145
|
-
expect(result2
|
|
156
|
+
// Verify instances are preserved (renderCount should be 2)
|
|
157
|
+
expect(result2[0]).toMatchObject({
|
|
146
158
|
id: "b",
|
|
147
159
|
value: 20,
|
|
148
160
|
renderCount: 2,
|
|
149
161
|
});
|
|
150
|
-
expect(result2
|
|
162
|
+
expect(result2[1]).toMatchObject({
|
|
151
163
|
id: "a",
|
|
152
164
|
value: 10,
|
|
153
165
|
renderCount: 2,
|
|
@@ -158,65 +170,73 @@ describe("tapResources - Basic Functionality", () => {
|
|
|
158
170
|
describe("Dynamic List Management", () => {
|
|
159
171
|
it("should handle adding and removing resources", () => {
|
|
160
172
|
const testFiber = createTestResource(
|
|
161
|
-
(props: { items:
|
|
162
|
-
const results = tapResources(
|
|
163
|
-
props.items
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
);
|
|
173
|
+
(props: { items: Array<{ key: string; value: number }> }) => {
|
|
174
|
+
const results = tapResources(() => {
|
|
175
|
+
return props.items.map((item) =>
|
|
176
|
+
withKey(item.key, SimpleCounter({ value: item.value })),
|
|
177
|
+
);
|
|
178
|
+
}, [props.items]);
|
|
168
179
|
return results;
|
|
169
180
|
},
|
|
170
181
|
);
|
|
171
182
|
|
|
172
183
|
// Initial render with 3 items
|
|
173
|
-
const result1 = renderTest(testFiber, {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
184
|
+
const result1 = renderTest(testFiber, {
|
|
185
|
+
items: [
|
|
186
|
+
{ key: "a", value: 0 },
|
|
187
|
+
{ key: "b", value: 10 },
|
|
188
|
+
{ key: "c", value: 20 },
|
|
189
|
+
],
|
|
178
190
|
});
|
|
191
|
+
expect(result1).toEqual([{ count: 0 }, { count: 10 }, { count: 20 }]);
|
|
179
192
|
|
|
180
193
|
// Remove middle item
|
|
181
|
-
const result2 = renderTest(testFiber, {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
194
|
+
const result2 = renderTest(testFiber, {
|
|
195
|
+
items: [
|
|
196
|
+
{ key: "a", value: 0 },
|
|
197
|
+
{ key: "c", value: 10 },
|
|
198
|
+
],
|
|
185
199
|
});
|
|
200
|
+
expect(result2).toEqual([{ count: 0 }, { count: 10 }]);
|
|
186
201
|
|
|
187
202
|
// Add new item
|
|
188
|
-
const result3 = renderTest(testFiber, {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
203
|
+
const result3 = renderTest(testFiber, {
|
|
204
|
+
items: [
|
|
205
|
+
{ key: "a", value: 0 },
|
|
206
|
+
{ key: "c", value: 10 },
|
|
207
|
+
{ key: "d", value: 20 },
|
|
208
|
+
],
|
|
193
209
|
});
|
|
210
|
+
expect(result3).toEqual([{ count: 0 }, { count: 10 }, { count: 20 }]);
|
|
194
211
|
});
|
|
195
212
|
|
|
196
213
|
it("should handle changing resource types for the same key", () => {
|
|
197
214
|
const testFiber = createTestResource((props: { useCounter: boolean }) => {
|
|
198
215
|
const results = tapResources(
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
216
|
+
() => [
|
|
217
|
+
withKey(
|
|
218
|
+
"item",
|
|
219
|
+
props.useCounter
|
|
220
|
+
? StatefulCounter({ initial: 42 })
|
|
221
|
+
: Display({ text: "Hello" }),
|
|
222
|
+
),
|
|
223
|
+
],
|
|
224
|
+
[props.useCounter],
|
|
205
225
|
);
|
|
206
226
|
return results;
|
|
207
227
|
});
|
|
208
228
|
|
|
209
229
|
// Start with Counter
|
|
210
230
|
const result1 = renderTest(testFiber, { useCounter: true });
|
|
211
|
-
expect(result1).toEqual({
|
|
231
|
+
expect(result1).toEqual([{ count: 42 }]);
|
|
212
232
|
|
|
213
233
|
// Switch to Display
|
|
214
234
|
const result2 = renderTest(testFiber, { useCounter: false });
|
|
215
|
-
expect(result2).toEqual({
|
|
235
|
+
expect(result2).toEqual([{ type: "display", text: "Hello" }]);
|
|
216
236
|
|
|
217
237
|
// Switch back to Counter (new instance)
|
|
218
238
|
const result3 = renderTest(testFiber, { useCounter: true });
|
|
219
|
-
expect(result3).toEqual({
|
|
239
|
+
expect(result3).toEqual([{ count: 42 }]);
|
|
220
240
|
});
|
|
221
241
|
});
|
|
222
242
|
});
|