signalium 1.2.2 → 2.0.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/CHANGELOG.md +28 -0
- package/{build/transform.js → config.js} +1 -5
- package/{build/react.js → debug.js} +1 -5
- package/dist/cjs/config.d.ts +1 -21
- package/dist/cjs/config.d.ts.map +1 -1
- package/dist/cjs/config.js +3 -36
- package/dist/cjs/config.js.map +1 -1
- package/dist/cjs/debug.d.ts +1 -1
- package/dist/cjs/debug.d.ts.map +1 -1
- package/dist/cjs/debug.js +1 -1
- package/dist/cjs/debug.js.map +1 -1
- package/dist/cjs/index.d.ts +5 -6
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +17 -23
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/internals/async.d.ts +24 -19
- package/dist/cjs/internals/async.d.ts.map +1 -1
- package/dist/cjs/internals/async.js +264 -137
- package/dist/cjs/internals/async.js.map +1 -1
- package/dist/cjs/internals/callback.d.ts +13 -0
- package/dist/cjs/internals/callback.d.ts.map +1 -0
- package/dist/cjs/internals/callback.js +73 -0
- package/dist/cjs/internals/callback.js.map +1 -0
- package/dist/cjs/internals/config.d.ts +7 -0
- package/dist/cjs/internals/config.d.ts.map +1 -0
- package/dist/cjs/internals/config.js +17 -0
- package/dist/cjs/internals/config.js.map +1 -0
- package/dist/cjs/internals/consumer.d.ts +3 -3
- package/dist/cjs/internals/consumer.d.ts.map +1 -1
- package/dist/cjs/internals/consumer.js.map +1 -1
- package/dist/cjs/internals/contexts.d.ts +15 -14
- package/dist/cjs/internals/contexts.d.ts.map +1 -1
- package/dist/cjs/internals/contexts.js +52 -52
- package/dist/cjs/internals/contexts.js.map +1 -1
- package/dist/cjs/internals/core-api.d.ts +15 -0
- package/dist/cjs/internals/core-api.d.ts.map +1 -0
- package/dist/cjs/internals/core-api.js +83 -0
- package/dist/cjs/internals/core-api.js.map +1 -0
- package/dist/cjs/internals/dirty.d.ts +3 -3
- package/dist/cjs/internals/dirty.d.ts.map +1 -1
- package/dist/cjs/internals/dirty.js +13 -13
- package/dist/cjs/internals/dirty.js.map +1 -1
- package/dist/cjs/internals/edge.d.ts +5 -5
- package/dist/cjs/internals/edge.d.ts.map +1 -1
- package/dist/cjs/internals/edge.js.map +1 -1
- package/dist/cjs/internals/generators.d.ts +5 -0
- package/dist/cjs/internals/generators.d.ts.map +1 -0
- package/dist/cjs/internals/generators.js +83 -0
- package/dist/cjs/internals/generators.js.map +1 -0
- package/dist/cjs/internals/get.d.ts +5 -8
- package/dist/cjs/internals/get.d.ts.map +1 -1
- package/dist/cjs/internals/get.js +48 -107
- package/dist/cjs/internals/get.js.map +1 -1
- package/dist/cjs/internals/reactive.d.ts +77 -0
- package/dist/cjs/internals/reactive.d.ts.map +1 -0
- package/dist/cjs/internals/{derived.js → reactive.js} +45 -33
- package/dist/cjs/internals/reactive.js.map +1 -0
- package/dist/cjs/internals/scheduling.d.ts +7 -7
- package/dist/cjs/internals/scheduling.d.ts.map +1 -1
- package/dist/cjs/internals/scheduling.js +9 -9
- package/dist/cjs/internals/scheduling.js.map +1 -1
- package/dist/cjs/internals/signal.d.ts +20 -0
- package/dist/cjs/internals/signal.d.ts.map +1 -0
- package/dist/cjs/internals/{state.js → signal.js} +31 -27
- package/dist/cjs/internals/signal.js.map +1 -0
- package/dist/{esm → cjs/internals}/trace.d.ts +1 -1
- package/dist/cjs/internals/trace.d.ts.map +1 -0
- package/dist/cjs/{trace.js → internals/trace.js} +1 -1
- package/dist/cjs/internals/trace.js.map +1 -0
- package/dist/cjs/internals/utils/equals.d.ts +4 -4
- package/dist/cjs/internals/utils/equals.d.ts.map +1 -1
- package/dist/cjs/internals/utils/equals.js.map +1 -1
- package/dist/cjs/internals/utils/type-utils.d.ts +0 -2
- package/dist/cjs/internals/utils/type-utils.d.ts.map +1 -1
- package/dist/cjs/internals/utils/type-utils.js +0 -5
- package/dist/cjs/internals/utils/type-utils.js.map +1 -1
- package/dist/cjs/internals/watch.d.ts +4 -0
- package/dist/cjs/internals/watch.d.ts.map +1 -0
- package/dist/cjs/internals/{connect.js → watch.js} +7 -7
- package/dist/cjs/internals/watch.js.map +1 -0
- package/dist/cjs/internals/weakref.d.ts.map +1 -0
- package/dist/cjs/internals/weakref.js.map +1 -0
- package/dist/cjs/react/component.d.ts +2 -0
- package/dist/cjs/react/component.d.ts.map +1 -0
- package/dist/cjs/react/component.js +40 -0
- package/dist/cjs/react/component.js.map +1 -0
- package/dist/cjs/react/context.d.ts +2 -1
- package/dist/cjs/react/context.d.ts.map +1 -1
- package/dist/cjs/react/context.js +10 -5
- package/dist/cjs/react/context.js.map +1 -1
- package/dist/cjs/react/index.d.ts +4 -4
- package/dist/cjs/react/index.d.ts.map +1 -1
- package/dist/cjs/react/index.js +11 -8
- package/dist/cjs/react/index.js.map +1 -1
- package/dist/cjs/react/provider.d.ts.map +1 -1
- package/dist/cjs/react/provider.js +1 -1
- package/dist/cjs/react/provider.js.map +1 -1
- package/dist/cjs/react/rendering.d.ts +0 -6
- package/dist/cjs/react/rendering.d.ts.map +1 -1
- package/dist/cjs/react/rendering.js +1 -19
- package/dist/cjs/react/rendering.js.map +1 -1
- package/dist/cjs/react/use-reactive.d.ts +7 -0
- package/dist/cjs/react/use-reactive.d.ts.map +1 -0
- package/dist/cjs/react/use-reactive.js +67 -0
- package/dist/cjs/react/use-reactive.js.map +1 -0
- package/dist/cjs/react/use-signal.d.ts +3 -0
- package/dist/cjs/react/use-signal.d.ts.map +1 -0
- package/dist/cjs/react/{state.js → use-signal.js} +5 -5
- package/dist/cjs/react/use-signal.js.map +1 -0
- package/dist/cjs/{transform.d.ts → transform/async.d.ts} +1 -1
- package/dist/cjs/transform/async.d.ts.map +1 -0
- package/dist/cjs/{transform.js → transform/async.js} +22 -9
- package/dist/cjs/transform/async.js.map +1 -0
- package/dist/cjs/transform/callback.d.ts +6 -0
- package/dist/cjs/transform/callback.d.ts.map +1 -0
- package/dist/cjs/transform/callback.js +259 -0
- package/dist/cjs/transform/callback.js.map +1 -0
- package/dist/cjs/transform/index.d.ts +5 -0
- package/dist/cjs/transform/index.d.ts.map +1 -0
- package/dist/cjs/transform/index.js +12 -0
- package/dist/cjs/transform/index.js.map +1 -0
- package/dist/cjs/transform/preset.d.ts +7 -0
- package/dist/cjs/transform/preset.d.ts.map +1 -0
- package/dist/cjs/transform/preset.js +20 -0
- package/dist/cjs/transform/preset.js.map +1 -0
- package/dist/cjs/transform/promise.d.ts +6 -0
- package/dist/cjs/transform/promise.d.ts.map +1 -0
- package/dist/cjs/transform/promise.js +129 -0
- package/dist/cjs/transform/promise.js.map +1 -0
- package/dist/cjs/types.d.ts +44 -63
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/utils.d.ts +2 -0
- package/dist/cjs/utils.d.ts.map +1 -0
- package/dist/cjs/utils.js +7 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/esm/config.d.ts +1 -21
- package/dist/esm/config.d.ts.map +1 -1
- package/dist/esm/config.js +1 -29
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/debug.d.ts +1 -1
- package/dist/esm/debug.d.ts.map +1 -1
- package/dist/esm/debug.js +1 -1
- package/dist/esm/debug.js.map +1 -1
- package/dist/esm/index.d.ts +5 -6
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +5 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internals/async.d.ts +24 -19
- package/dist/esm/internals/async.d.ts.map +1 -1
- package/dist/esm/internals/async.js +253 -128
- package/dist/esm/internals/async.js.map +1 -1
- package/dist/esm/internals/callback.d.ts +13 -0
- package/dist/esm/internals/callback.d.ts.map +1 -0
- package/dist/esm/internals/callback.js +67 -0
- package/dist/esm/internals/callback.js.map +1 -0
- package/dist/esm/internals/config.d.ts +7 -0
- package/dist/esm/internals/config.d.ts.map +1 -0
- package/dist/esm/internals/config.js +11 -0
- package/dist/esm/internals/config.js.map +1 -0
- package/dist/esm/internals/consumer.d.ts +3 -3
- package/dist/esm/internals/consumer.d.ts.map +1 -1
- package/dist/esm/internals/consumer.js.map +1 -1
- package/dist/esm/internals/contexts.d.ts +15 -14
- package/dist/esm/internals/contexts.d.ts.map +1 -1
- package/dist/esm/internals/contexts.js +46 -46
- package/dist/esm/internals/contexts.js.map +1 -1
- package/dist/esm/internals/core-api.d.ts +15 -0
- package/dist/esm/internals/core-api.d.ts.map +1 -0
- package/dist/esm/internals/core-api.js +74 -0
- package/dist/esm/internals/core-api.js.map +1 -0
- package/dist/esm/internals/dirty.d.ts +3 -3
- package/dist/esm/internals/dirty.d.ts.map +1 -1
- package/dist/esm/internals/dirty.js +12 -12
- package/dist/esm/internals/dirty.js.map +1 -1
- package/dist/esm/internals/edge.d.ts +5 -5
- package/dist/esm/internals/edge.d.ts.map +1 -1
- package/dist/esm/internals/edge.js.map +1 -1
- package/dist/esm/internals/generators.d.ts +5 -0
- package/dist/esm/internals/generators.d.ts.map +1 -0
- package/dist/esm/internals/generators.js +79 -0
- package/dist/esm/internals/generators.js.map +1 -0
- package/dist/esm/internals/get.d.ts +5 -8
- package/dist/esm/internals/get.d.ts.map +1 -1
- package/dist/esm/internals/get.js +43 -100
- package/dist/esm/internals/get.js.map +1 -1
- package/dist/esm/internals/reactive.d.ts +77 -0
- package/dist/esm/internals/reactive.d.ts.map +1 -0
- package/dist/esm/internals/{derived.js → reactive.js} +41 -29
- package/dist/esm/internals/reactive.js.map +1 -0
- package/dist/esm/internals/scheduling.d.ts +7 -7
- package/dist/esm/internals/scheduling.d.ts.map +1 -1
- package/dist/esm/internals/scheduling.js +6 -6
- package/dist/esm/internals/scheduling.js.map +1 -1
- package/dist/esm/internals/signal.d.ts +20 -0
- package/dist/esm/internals/signal.d.ts.map +1 -0
- package/dist/esm/internals/{state.js → signal.js} +25 -22
- package/dist/esm/internals/signal.js.map +1 -0
- package/dist/{cjs → esm/internals}/trace.d.ts +1 -1
- package/dist/esm/internals/trace.d.ts.map +1 -0
- package/dist/esm/{trace.js → internals/trace.js} +1 -1
- package/dist/esm/internals/trace.js.map +1 -0
- package/dist/esm/internals/utils/equals.d.ts +4 -4
- package/dist/esm/internals/utils/equals.d.ts.map +1 -1
- package/dist/esm/internals/utils/equals.js.map +1 -1
- package/dist/esm/internals/utils/type-utils.d.ts +0 -2
- package/dist/esm/internals/utils/type-utils.d.ts.map +1 -1
- package/dist/esm/internals/utils/type-utils.js +0 -4
- package/dist/esm/internals/utils/type-utils.js.map +1 -1
- package/dist/esm/internals/watch.d.ts +4 -0
- package/dist/esm/internals/watch.d.ts.map +1 -0
- package/dist/esm/internals/{connect.js → watch.js} +7 -7
- package/dist/esm/internals/watch.js.map +1 -0
- package/dist/esm/internals/weakref.d.ts.map +1 -0
- package/dist/esm/internals/weakref.js.map +1 -0
- package/dist/esm/react/component.d.ts +2 -0
- package/dist/esm/react/component.d.ts.map +1 -0
- package/dist/esm/react/component.js +37 -0
- package/dist/esm/react/component.js.map +1 -0
- package/dist/esm/react/context.d.ts +2 -1
- package/dist/esm/react/context.d.ts.map +1 -1
- package/dist/esm/react/context.js +10 -6
- package/dist/esm/react/context.js.map +1 -1
- package/dist/esm/react/index.d.ts +4 -4
- package/dist/esm/react/index.d.ts.map +1 -1
- package/dist/esm/react/index.js +4 -4
- package/dist/esm/react/index.js.map +1 -1
- package/dist/esm/react/provider.d.ts.map +1 -1
- package/dist/esm/react/provider.js +2 -2
- package/dist/esm/react/provider.js.map +1 -1
- package/dist/esm/react/rendering.d.ts +0 -6
- package/dist/esm/react/rendering.d.ts.map +1 -1
- package/dist/esm/react/rendering.js +1 -17
- package/dist/esm/react/rendering.js.map +1 -1
- package/dist/esm/react/use-reactive.d.ts +7 -0
- package/dist/esm/react/use-reactive.d.ts.map +1 -0
- package/dist/esm/react/use-reactive.js +64 -0
- package/dist/esm/react/use-reactive.js.map +1 -0
- package/dist/esm/react/use-signal.d.ts +3 -0
- package/dist/esm/react/use-signal.d.ts.map +1 -0
- package/dist/esm/react/use-signal.js +10 -0
- package/dist/esm/react/use-signal.js.map +1 -0
- package/dist/esm/{transform.d.ts → transform/async.d.ts} +1 -1
- package/dist/esm/transform/async.d.ts.map +1 -0
- package/dist/esm/{transform.js → transform/async.js} +22 -9
- package/dist/esm/transform/async.js.map +1 -0
- package/dist/esm/transform/callback.d.ts +6 -0
- package/dist/esm/transform/callback.d.ts.map +1 -0
- package/dist/esm/transform/callback.js +256 -0
- package/dist/esm/transform/callback.js.map +1 -0
- package/dist/esm/transform/index.d.ts +5 -0
- package/dist/esm/transform/index.d.ts.map +1 -0
- package/dist/esm/transform/index.js +5 -0
- package/dist/esm/transform/index.js.map +1 -0
- package/dist/esm/transform/preset.d.ts +7 -0
- package/dist/esm/transform/preset.d.ts.map +1 -0
- package/dist/esm/transform/preset.js +17 -0
- package/dist/esm/transform/preset.js.map +1 -0
- package/dist/esm/transform/promise.d.ts +6 -0
- package/dist/esm/transform/promise.d.ts.map +1 -0
- package/dist/esm/transform/promise.js +126 -0
- package/dist/esm/transform/promise.js.map +1 -0
- package/dist/esm/types.d.ts +44 -63
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/utils.d.ts +2 -0
- package/dist/esm/utils.d.ts.map +1 -0
- package/dist/esm/utils.js +2 -0
- package/dist/esm/utils.js.map +1 -0
- package/package.json +56 -58
- package/react.js +0 -4
- package/transform.js +1 -5
- package/utils.js +15 -0
- package/.turbo/turbo-build.log +0 -12
- package/dist/cjs/hooks.d.ts +0 -16
- package/dist/cjs/hooks.d.ts.map +0 -1
- package/dist/cjs/hooks.js +0 -44
- package/dist/cjs/hooks.js.map +0 -1
- package/dist/cjs/internals/connect.d.ts +0 -4
- package/dist/cjs/internals/connect.d.ts.map +0 -1
- package/dist/cjs/internals/connect.js.map +0 -1
- package/dist/cjs/internals/derived.d.ts +0 -76
- package/dist/cjs/internals/derived.d.ts.map +0 -1
- package/dist/cjs/internals/derived.js.map +0 -1
- package/dist/cjs/internals/state.d.ts +0 -18
- package/dist/cjs/internals/state.d.ts.map +0 -1
- package/dist/cjs/internals/state.js.map +0 -1
- package/dist/cjs/react/setup.d.ts +0 -2
- package/dist/cjs/react/setup.d.ts.map +0 -1
- package/dist/cjs/react/setup.js +0 -14
- package/dist/cjs/react/setup.js.map +0 -1
- package/dist/cjs/react/signal-value.d.ts +0 -6
- package/dist/cjs/react/signal-value.d.ts.map +0 -1
- package/dist/cjs/react/signal-value.js +0 -37
- package/dist/cjs/react/signal-value.js.map +0 -1
- package/dist/cjs/react/state.d.ts +0 -3
- package/dist/cjs/react/state.d.ts.map +0 -1
- package/dist/cjs/react/state.js.map +0 -1
- package/dist/cjs/trace.d.ts.map +0 -1
- package/dist/cjs/trace.js.map +0 -1
- package/dist/cjs/transform.d.ts.map +0 -1
- package/dist/cjs/transform.js.map +0 -1
- package/dist/cjs/weakref.d.ts.map +0 -1
- package/dist/cjs/weakref.js.map +0 -1
- package/dist/esm/hooks.d.ts +0 -16
- package/dist/esm/hooks.d.ts.map +0 -1
- package/dist/esm/hooks.js +0 -37
- package/dist/esm/hooks.js.map +0 -1
- package/dist/esm/internals/connect.d.ts +0 -4
- package/dist/esm/internals/connect.d.ts.map +0 -1
- package/dist/esm/internals/connect.js.map +0 -1
- package/dist/esm/internals/derived.d.ts +0 -76
- package/dist/esm/internals/derived.d.ts.map +0 -1
- package/dist/esm/internals/derived.js.map +0 -1
- package/dist/esm/internals/state.d.ts +0 -18
- package/dist/esm/internals/state.d.ts.map +0 -1
- package/dist/esm/internals/state.js.map +0 -1
- package/dist/esm/react/setup.d.ts +0 -2
- package/dist/esm/react/setup.d.ts.map +0 -1
- package/dist/esm/react/setup.js +0 -11
- package/dist/esm/react/setup.js.map +0 -1
- package/dist/esm/react/signal-value.d.ts +0 -6
- package/dist/esm/react/signal-value.d.ts.map +0 -1
- package/dist/esm/react/signal-value.js +0 -33
- package/dist/esm/react/signal-value.js.map +0 -1
- package/dist/esm/react/state.d.ts +0 -3
- package/dist/esm/react/state.d.ts.map +0 -1
- package/dist/esm/react/state.js +0 -10
- package/dist/esm/react/state.js.map +0 -1
- package/dist/esm/trace.d.ts.map +0 -1
- package/dist/esm/trace.js.map +0 -1
- package/dist/esm/transform.d.ts.map +0 -1
- package/dist/esm/transform.js.map +0 -1
- package/dist/esm/weakref.d.ts.map +0 -1
- package/dist/esm/weakref.js.map +0 -1
- package/src/__tests__/__snapshots__/context.test.ts.snap +0 -2101
- package/src/__tests__/__snapshots__/nesting.test.ts.snap +0 -16201
- package/src/__tests__/__snapshots__/params-and-state.test.ts.snap +0 -1879
- package/src/__tests__/async-task.test.ts +0 -327
- package/src/__tests__/context.test.ts +0 -619
- package/src/__tests__/gc.test.ts +0 -256
- package/src/__tests__/nesting.test.ts +0 -298
- package/src/__tests__/params-and-state.test.ts +0 -230
- package/src/__tests__/reactive-async.test.ts +0 -548
- package/src/__tests__/reactive-sync.test.ts +0 -130
- package/src/__tests__/subscription.test.ts +0 -510
- package/src/__tests__/utils/async.ts +0 -6
- package/src/__tests__/utils/instrumented-hooks.ts +0 -410
- package/src/__tests__/utils/permute.ts +0 -85
- package/src/config.ts +0 -54
- package/src/debug.ts +0 -14
- package/src/hooks.ts +0 -82
- package/src/index.ts +0 -21
- package/src/internals/async.ts +0 -563
- package/src/internals/connect.ts +0 -49
- package/src/internals/consumer.ts +0 -13
- package/src/internals/contexts.ts +0 -177
- package/src/internals/derived.ts +0 -217
- package/src/internals/dirty.ts +0 -91
- package/src/internals/edge.ts +0 -109
- package/src/internals/get.ts +0 -298
- package/src/internals/scheduling.ts +0 -160
- package/src/internals/state.ts +0 -111
- package/src/internals/utils/debug-name.ts +0 -14
- package/src/internals/utils/equals.ts +0 -12
- package/src/internals/utils/hash.ts +0 -221
- package/src/internals/utils/stringify.ts +0 -57
- package/src/internals/utils/type-utils.ts +0 -19
- package/src/react/__tests__/async.test.tsx +0 -704
- package/src/react/__tests__/basic.test.tsx +0 -95
- package/src/react/__tests__/contexts.test.tsx +0 -181
- package/src/react/__tests__/subscriptions.test.tsx +0 -49
- package/src/react/__tests__/utils.tsx +0 -40
- package/src/react/context.ts +0 -14
- package/src/react/index.ts +0 -6
- package/src/react/provider.tsx +0 -18
- package/src/react/rendering.ts +0 -43
- package/src/react/setup.ts +0 -11
- package/src/react/signal-value.ts +0 -50
- package/src/react/state.ts +0 -13
- package/src/trace.ts +0 -454
- package/src/transform.ts +0 -113
- package/src/types.ts +0 -115
- package/src/weakref.ts +0 -9
- package/tsconfig.json +0 -13
- package/vitest.workspace.ts +0 -61
- /package/dist/cjs/{weakref.d.ts → internals/weakref.d.ts} +0 -0
- /package/dist/cjs/{weakref.js → internals/weakref.js} +0 -0
- /package/dist/esm/{weakref.d.ts → internals/weakref.d.ts} +0 -0
- /package/dist/esm/{weakref.js → internals/weakref.js} +0 -0
@@ -1,95 +0,0 @@
|
|
1
|
-
import { beforeEach, describe, expect, test } from 'vitest';
|
2
|
-
import { render } from 'vitest-browser-react';
|
3
|
-
import { state, reactive, createContext, useContext } from 'signalium';
|
4
|
-
import { ContextProvider, setupReact, useStateSignal } from '../index.js';
|
5
|
-
import React, { useState } from 'react';
|
6
|
-
import { userEvent } from '@vitest/browser/context';
|
7
|
-
import { sleep } from '../../__tests__/utils/async.js';
|
8
|
-
|
9
|
-
setupReact();
|
10
|
-
|
11
|
-
describe('React > basic', () => {
|
12
|
-
test('basic state usage works', async () => {
|
13
|
-
const value = state('Hello');
|
14
|
-
|
15
|
-
function Component(): React.ReactNode {
|
16
|
-
return <div>{value.get()}</div>;
|
17
|
-
}
|
18
|
-
|
19
|
-
const { getByText } = render(<Component />);
|
20
|
-
|
21
|
-
await expect.element(getByText('Hello')).toBeInTheDocument();
|
22
|
-
|
23
|
-
value.set('World');
|
24
|
-
|
25
|
-
await expect.element(getByText('World')).toBeInTheDocument();
|
26
|
-
});
|
27
|
-
|
28
|
-
test('useStateSignal works', async () => {
|
29
|
-
function Component(): React.ReactNode {
|
30
|
-
const value = useStateSignal('Hello');
|
31
|
-
|
32
|
-
return (
|
33
|
-
<div>
|
34
|
-
{value.get()}
|
35
|
-
<button onClick={() => value.set('World')}>Toggle</button>
|
36
|
-
</div>
|
37
|
-
);
|
38
|
-
}
|
39
|
-
|
40
|
-
const { getByText } = render(<Component />);
|
41
|
-
|
42
|
-
await expect.element(getByText('Hello')).toBeInTheDocument();
|
43
|
-
|
44
|
-
await userEvent.click(getByText('Toggle'));
|
45
|
-
|
46
|
-
await expect.element(getByText('World')).toBeInTheDocument();
|
47
|
-
});
|
48
|
-
|
49
|
-
test('basic computed usage works', async () => {
|
50
|
-
const value = state('Hello');
|
51
|
-
|
52
|
-
const derived = reactive(() => `${value.get()}, World`);
|
53
|
-
|
54
|
-
function Component(): React.ReactNode {
|
55
|
-
return <div>{derived()}</div>;
|
56
|
-
}
|
57
|
-
|
58
|
-
const { getByText } = render(<Component />);
|
59
|
-
|
60
|
-
await expect.element(getByText('Hello, World')).toBeInTheDocument();
|
61
|
-
|
62
|
-
value.set('Hey');
|
63
|
-
|
64
|
-
await expect.element(getByText('Hey, World')).toBeInTheDocument();
|
65
|
-
});
|
66
|
-
|
67
|
-
test('computed updates when params change', async () => {
|
68
|
-
const value = state('Hello');
|
69
|
-
|
70
|
-
const derived = reactive((universe: boolean) => `${value.get()}, ${universe ? 'Universe' : 'World'}`);
|
71
|
-
|
72
|
-
function Component(): React.ReactNode {
|
73
|
-
const [universe, setUniverse] = useState(true);
|
74
|
-
|
75
|
-
return (
|
76
|
-
<div>
|
77
|
-
{derived(universe)}
|
78
|
-
<button onClick={() => setUniverse(!universe)}>Toggle Universe</button>
|
79
|
-
</div>
|
80
|
-
);
|
81
|
-
}
|
82
|
-
|
83
|
-
const { getByText } = render(<Component />);
|
84
|
-
|
85
|
-
await expect.element(getByText('Hello, Universe')).toBeInTheDocument();
|
86
|
-
|
87
|
-
value.set('Hey');
|
88
|
-
|
89
|
-
await expect.element(getByText('Hey, Universe')).toBeInTheDocument();
|
90
|
-
|
91
|
-
await userEvent.click(getByText('Toggle Universe'));
|
92
|
-
|
93
|
-
await expect.element(getByText('Hey, World')).toBeInTheDocument();
|
94
|
-
});
|
95
|
-
});
|
@@ -1,181 +0,0 @@
|
|
1
|
-
import { describe, expect, test } from 'vitest';
|
2
|
-
import { render } from 'vitest-browser-react';
|
3
|
-
import { state, reactive, createContext, useContext, setRootContexts } from '../../index.js';
|
4
|
-
import { ContextProvider, setupReact, useScope } from '../index.js';
|
5
|
-
import React, { useState } from 'react';
|
6
|
-
|
7
|
-
setupReact();
|
8
|
-
|
9
|
-
describe('React > contexts', () => {
|
10
|
-
test('useContext works inside computed with default value', async () => {
|
11
|
-
const value = state('Hello');
|
12
|
-
const context = createContext(value);
|
13
|
-
|
14
|
-
const derived = reactive(() => `${useContext(context).get()}, World`);
|
15
|
-
|
16
|
-
function Component(): React.ReactNode {
|
17
|
-
return <div>{derived()}</div>;
|
18
|
-
}
|
19
|
-
|
20
|
-
const { getByText } = render(<Component />);
|
21
|
-
|
22
|
-
await expect.element(getByText('Hello, World')).toBeInTheDocument();
|
23
|
-
|
24
|
-
value.set('Hey');
|
25
|
-
|
26
|
-
await expect.element(getByText('Hey, World')).toBeInTheDocument();
|
27
|
-
});
|
28
|
-
|
29
|
-
test('useContext works at root level with default value', async () => {
|
30
|
-
const value = state('Hello');
|
31
|
-
const context = createContext(value);
|
32
|
-
|
33
|
-
function Component(): React.ReactNode {
|
34
|
-
const v = useContext(context);
|
35
|
-
|
36
|
-
return <div>{v.get()}, World</div>;
|
37
|
-
}
|
38
|
-
|
39
|
-
const { getByText } = render(
|
40
|
-
<ContextProvider contexts={[]}>
|
41
|
-
<Component />
|
42
|
-
</ContextProvider>,
|
43
|
-
);
|
44
|
-
|
45
|
-
await expect.element(getByText('Hello, World')).toBeInTheDocument();
|
46
|
-
|
47
|
-
value.set('Hey');
|
48
|
-
|
49
|
-
await expect.element(getByText('Hey, World')).toBeInTheDocument();
|
50
|
-
});
|
51
|
-
|
52
|
-
test('provider inherits from root scope', async () => {
|
53
|
-
const defaultValue1 = state('default1');
|
54
|
-
const defaultValue2 = state('default2');
|
55
|
-
const ctx1 = createContext(defaultValue1);
|
56
|
-
const ctx2 = createContext(defaultValue2);
|
57
|
-
const rootOverride1 = state('root1');
|
58
|
-
const rootOverride2 = state('root2');
|
59
|
-
|
60
|
-
// Set root contexts
|
61
|
-
setRootContexts([
|
62
|
-
[ctx1, rootOverride1],
|
63
|
-
[ctx2, rootOverride2],
|
64
|
-
]);
|
65
|
-
|
66
|
-
// Component that uses both contexts
|
67
|
-
function Component({ testId }: { testId: string }): React.ReactNode {
|
68
|
-
const value1 = useContext(ctx1);
|
69
|
-
const value2 = useContext(ctx2);
|
70
|
-
const derived = reactive(() => `${value1.get()}-${value2.get()}`);
|
71
|
-
return <div data-testid={testId}>{derived()}</div>;
|
72
|
-
}
|
73
|
-
const localOverride1 = state('local1');
|
74
|
-
const localOverride2 = state('local2');
|
75
|
-
|
76
|
-
// Should inherit from root scope when no local overrides
|
77
|
-
const { getByTestId } = render(
|
78
|
-
<>
|
79
|
-
<ContextProvider contexts={[]}>
|
80
|
-
<Component testId="result" />
|
81
|
-
</ContextProvider>
|
82
|
-
<ContextProvider contexts={[[ctx1, localOverride1]]}>
|
83
|
-
<Component testId="result2" />
|
84
|
-
</ContextProvider>
|
85
|
-
<ContextProvider
|
86
|
-
contexts={[
|
87
|
-
[ctx1, localOverride1],
|
88
|
-
[ctx2, localOverride2],
|
89
|
-
]}
|
90
|
-
>
|
91
|
-
<Component testId="result3" />
|
92
|
-
</ContextProvider>
|
93
|
-
</>,
|
94
|
-
);
|
95
|
-
|
96
|
-
await expect.element(getByTestId('result')).toHaveTextContent('root1-root2');
|
97
|
-
|
98
|
-
// Should inherit from root scope for unoverridden contexts
|
99
|
-
await expect.element(getByTestId('result2')).toHaveTextContent('local1-root2');
|
100
|
-
|
101
|
-
// Should use local overrides when provided
|
102
|
-
await expect.element(getByTestId('result3')).toHaveTextContent('local1-local2');
|
103
|
-
|
104
|
-
// Changes to root contexts should be reflected in inherited contexts
|
105
|
-
rootOverride1.set('updated-root1');
|
106
|
-
rootOverride2.set('updated-root2');
|
107
|
-
|
108
|
-
await expect.element(getByTestId('result')).toHaveTextContent('updated-root1-updated-root2');
|
109
|
-
|
110
|
-
// Local overrides should remain unaffected by root context changes
|
111
|
-
await expect.element(getByTestId('result2')).toHaveTextContent('local1-updated-root2');
|
112
|
-
await expect.element(getByTestId('result3')).toHaveTextContent('local1-local2');
|
113
|
-
});
|
114
|
-
|
115
|
-
test('useContext works inside computed value passed via context provider', async () => {
|
116
|
-
const value = state('Hello');
|
117
|
-
const override = state('Hey');
|
118
|
-
const context = createContext(value);
|
119
|
-
|
120
|
-
const derived = reactive(() => `${useContext(context).get()}, World`);
|
121
|
-
|
122
|
-
function Component(): React.ReactNode {
|
123
|
-
return <div>{derived()}</div>;
|
124
|
-
}
|
125
|
-
|
126
|
-
const { getByText } = render(
|
127
|
-
<ContextProvider contexts={[[context, override]]}>
|
128
|
-
<Component />
|
129
|
-
</ContextProvider>,
|
130
|
-
);
|
131
|
-
|
132
|
-
await expect.element(getByText('Hey, World')).toBeInTheDocument();
|
133
|
-
|
134
|
-
override.set('Hi');
|
135
|
-
|
136
|
-
await expect.element(getByText('Hi, World')).toBeInTheDocument();
|
137
|
-
});
|
138
|
-
|
139
|
-
test('useContext works at root level with default value', async () => {
|
140
|
-
const value = state('Hello');
|
141
|
-
const override = state('Hey');
|
142
|
-
const context = createContext(value);
|
143
|
-
|
144
|
-
function Component(): React.ReactNode {
|
145
|
-
const v = useContext(context);
|
146
|
-
|
147
|
-
return <div>{v.get()}, World</div>;
|
148
|
-
}
|
149
|
-
|
150
|
-
const { getByText } = render(
|
151
|
-
<ContextProvider contexts={[[context, override]]}>
|
152
|
-
<Component />
|
153
|
-
</ContextProvider>,
|
154
|
-
);
|
155
|
-
|
156
|
-
await expect.element(getByText('Hey, World')).toBeInTheDocument();
|
157
|
-
|
158
|
-
override.set('Hi');
|
159
|
-
|
160
|
-
await expect.element(getByText('Hi, World')).toBeInTheDocument();
|
161
|
-
});
|
162
|
-
|
163
|
-
test('useScope returns undefined outside of rendering context', async () => {
|
164
|
-
// Direct call outside of rendering should return undefined
|
165
|
-
expect(useScope()).toBeUndefined();
|
166
|
-
|
167
|
-
// Inside a component during rendering, it should return the scope
|
168
|
-
function TestComponent() {
|
169
|
-
const scope = useScope();
|
170
|
-
return <div data-testid="scope">{scope ? 'has-scope' : 'no-scope'}</div>;
|
171
|
-
}
|
172
|
-
|
173
|
-
const { getByTestId } = render(
|
174
|
-
<ContextProvider contexts={[]}>
|
175
|
-
<TestComponent />
|
176
|
-
</ContextProvider>,
|
177
|
-
);
|
178
|
-
|
179
|
-
await expect.element(getByTestId('scope')).toHaveTextContent('has-scope');
|
180
|
-
});
|
181
|
-
});
|
@@ -1,49 +0,0 @@
|
|
1
|
-
import { describe, expect, test } from 'vitest';
|
2
|
-
import { render } from 'vitest-browser-react';
|
3
|
-
import { state, reactive, subscription } from 'signalium';
|
4
|
-
import { setupReact } from '../index.js';
|
5
|
-
import React from 'react';
|
6
|
-
import { sleep } from '../../__tests__/utils/async.js';
|
7
|
-
|
8
|
-
setupReact();
|
9
|
-
|
10
|
-
describe('React > subscriptions', () => {
|
11
|
-
test('subscriptions can be set by values accessed outside of normal run loop ', async () => {
|
12
|
-
const value = state('Hello');
|
13
|
-
|
14
|
-
const derived = reactive(() => {
|
15
|
-
return subscription<string>(({ set }) => {
|
16
|
-
const run = async () => {
|
17
|
-
await sleep(100);
|
18
|
-
|
19
|
-
try {
|
20
|
-
return `${value.get()}, World`;
|
21
|
-
} catch (e) {
|
22
|
-
console.error(e);
|
23
|
-
return 'Error';
|
24
|
-
}
|
25
|
-
};
|
26
|
-
|
27
|
-
set(run());
|
28
|
-
});
|
29
|
-
});
|
30
|
-
|
31
|
-
function GrandChild({ text }: { text: string }): React.ReactNode {
|
32
|
-
return <span>{text}</span>;
|
33
|
-
}
|
34
|
-
|
35
|
-
function Child({ asyncValue }: { asyncValue: { isPending: boolean; value: string | undefined } }): React.ReactNode {
|
36
|
-
return <div>{asyncValue.isPending ? 'Loading...' : <GrandChild text={asyncValue.value!} />}</div>;
|
37
|
-
}
|
38
|
-
|
39
|
-
function Parent(): React.ReactNode {
|
40
|
-
const d = derived();
|
41
|
-
return <Child asyncValue={d} />;
|
42
|
-
}
|
43
|
-
|
44
|
-
const { getByText } = render(<Parent />);
|
45
|
-
|
46
|
-
await expect.element(getByText('Loading...')).toBeInTheDocument();
|
47
|
-
await expect.element(getByText('Hello, World')).toBeInTheDocument();
|
48
|
-
});
|
49
|
-
});
|
@@ -1,40 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
|
3
|
-
export interface RenderCounter<Props extends Record<string, unknown>> {
|
4
|
-
(props: Props): React.ReactNode;
|
5
|
-
testId: number;
|
6
|
-
renderCount: number;
|
7
|
-
}
|
8
|
-
|
9
|
-
let CURRENT_ID = 0;
|
10
|
-
|
11
|
-
export type ComponentType<P = any> = (props: P) => React.ReactNode;
|
12
|
-
export type HOC<InProps = any, OutProps = InProps> = (Component: ComponentType<InProps>) => ComponentType<OutProps>;
|
13
|
-
|
14
|
-
/**
|
15
|
-
* The wrapper passed to createRenderCounter is a HOC that will wrap the component
|
16
|
-
* with additional functionality. The reason we don't pass a component directly is
|
17
|
-
* because introducing additional components would mess with the real render counts.
|
18
|
-
*/
|
19
|
-
const EmptyWrapper: HOC = Component => props => Component(props);
|
20
|
-
|
21
|
-
export function createRenderCounter<Props extends Record<string, unknown>>(
|
22
|
-
Component: (props: Props) => React.ReactNode,
|
23
|
-
wrapper: HOC<Props> = EmptyWrapper,
|
24
|
-
): RenderCounter<Props> {
|
25
|
-
const id = CURRENT_ID++;
|
26
|
-
|
27
|
-
const RenderCounterComponent = wrapper((props: Props) => {
|
28
|
-
RenderCounterComponent.renderCount++;
|
29
|
-
|
30
|
-
// Call the component manually so it's not a separate React component
|
31
|
-
const children = Component(props);
|
32
|
-
|
33
|
-
return <div data-testid={id}>{children}</div>;
|
34
|
-
}) as RenderCounter<Props>;
|
35
|
-
|
36
|
-
RenderCounterComponent.testId = id;
|
37
|
-
RenderCounterComponent.renderCount = 0;
|
38
|
-
|
39
|
-
return RenderCounterComponent;
|
40
|
-
}
|
package/src/react/context.ts
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
import { createContext, useContext } from 'react';
|
2
|
-
import { SignalScope } from '../internals/contexts.js';
|
3
|
-
import { isRendering } from './rendering.js';
|
4
|
-
|
5
|
-
export const ScopeContext = createContext<SignalScope | undefined>(undefined);
|
6
|
-
|
7
|
-
export function useScope() {
|
8
|
-
if (!isRendering()) {
|
9
|
-
return undefined;
|
10
|
-
}
|
11
|
-
|
12
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
13
|
-
return useContext(ScopeContext);
|
14
|
-
}
|
package/src/react/index.ts
DELETED
package/src/react/provider.tsx
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
import { useContext } from 'react';
|
2
|
-
import { ScopeContext } from './context.js';
|
3
|
-
import { ContextImpl, ContextPair, ROOT_SCOPE, SignalScope } from '../internals/contexts.js';
|
4
|
-
|
5
|
-
export function ContextProvider<C extends unknown[]>({
|
6
|
-
children,
|
7
|
-
contexts = [],
|
8
|
-
inherit = true,
|
9
|
-
}: {
|
10
|
-
children: React.ReactNode;
|
11
|
-
contexts?: [...ContextPair<C>] | [];
|
12
|
-
inherit?: boolean;
|
13
|
-
}) {
|
14
|
-
const parentScope = useContext(ScopeContext) ?? ROOT_SCOPE;
|
15
|
-
const scope = new SignalScope(contexts as [ContextImpl<unknown>, unknown][], inherit ? parentScope : undefined);
|
16
|
-
|
17
|
-
return <ScopeContext.Provider value={scope}>{children}</ScopeContext.Provider>;
|
18
|
-
}
|
package/src/react/rendering.ts
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
|
3
|
-
// This is a private React internal that we need to access to check if we are rendering.
|
4
|
-
// There is no other consistent way to check if we are rendering in both development
|
5
|
-
// and production, and it doesn't appear that the React team wants to add one. This
|
6
|
-
// should be checked on every major React version upgrade.
|
7
|
-
const REACT_INTERNALS =
|
8
|
-
(React as any).__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ||
|
9
|
-
(React as any).__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE ||
|
10
|
-
(React as any).__SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
|
11
|
-
|
12
|
-
const IS_REACT_18 = !!REACT_INTERNALS.ReactCurrentDispatcher;
|
13
|
-
const ReactCurrentDispatcher = REACT_INTERNALS.ReactCurrentDispatcher || REACT_INTERNALS;
|
14
|
-
|
15
|
-
let RENDERING_SAFE_MODE_COUNT = 0;
|
16
|
-
|
17
|
-
/**
|
18
|
-
* Reactive functions can be called anywhere, but React Hooks cannot. When calling reactive functions
|
19
|
-
* in code that _may or may not_ be used while rendering, we need to use this function to wrap the
|
20
|
-
* call. This will ensure that we will not be in a rendering context when the reactive function is called.
|
21
|
-
*/
|
22
|
-
export const runReactiveSafe = <T>(fn: () => T): T => {
|
23
|
-
RENDERING_SAFE_MODE_COUNT++;
|
24
|
-
|
25
|
-
try {
|
26
|
-
return fn();
|
27
|
-
} finally {
|
28
|
-
RENDERING_SAFE_MODE_COUNT--;
|
29
|
-
}
|
30
|
-
};
|
31
|
-
|
32
|
-
export function isRendering() {
|
33
|
-
const dispatcher = IS_REACT_18 ? ReactCurrentDispatcher.current : ReactCurrentDispatcher.H;
|
34
|
-
|
35
|
-
return (
|
36
|
-
RENDERING_SAFE_MODE_COUNT === 0 &&
|
37
|
-
!!dispatcher &&
|
38
|
-
// dispatcher can be in a state where it's defined, but all hooks are invalid to call.
|
39
|
-
// Only way we can tell is that if they are invalid, they will all be equal to each other
|
40
|
-
// (e.g. because it's the function that throws an error)
|
41
|
-
dispatcher.useState !== dispatcher.useEffect
|
42
|
-
);
|
43
|
-
}
|
package/src/react/setup.ts
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
import { setConfig } from '../config.js';
|
2
|
-
import { useScope } from './context.js';
|
3
|
-
import { useDerivedSignal, useStateSignal } from './signal-value.js';
|
4
|
-
|
5
|
-
export function setupReact() {
|
6
|
-
setConfig({
|
7
|
-
useDerivedSignal,
|
8
|
-
useStateSignal,
|
9
|
-
getFrameworkScope: useScope,
|
10
|
-
});
|
11
|
-
}
|
@@ -1,50 +0,0 @@
|
|
1
|
-
/* eslint-disable react-hooks/rules-of-hooks */
|
2
|
-
import { useCallback, useSyncExternalStore } from 'react';
|
3
|
-
import type { DerivedSignal } from '../internals/derived.js';
|
4
|
-
import type { StateSignal } from '../internals/state.js';
|
5
|
-
import type { ReactiveValue } from '../types.js';
|
6
|
-
import { isReactivePromise } from '../internals/utils/type-utils.js';
|
7
|
-
import { isReactiveSubscription } from '../internals/async.js';
|
8
|
-
import { isRendering } from './rendering.js';
|
9
|
-
|
10
|
-
export function useStateSignal<T>(signal: StateSignal<T>): T {
|
11
|
-
if (!isRendering()) {
|
12
|
-
return signal.peek();
|
13
|
-
}
|
14
|
-
|
15
|
-
return useSyncExternalStore(
|
16
|
-
useCallback(onStoreChange => signal.addListener(onStoreChange), [signal]),
|
17
|
-
() => signal.peek(),
|
18
|
-
() => signal.peek(),
|
19
|
-
);
|
20
|
-
}
|
21
|
-
|
22
|
-
export function useDerivedSignal<T, Args extends unknown[]>(signal: DerivedSignal<T, Args>): ReactiveValue<T> {
|
23
|
-
if (!isRendering()) {
|
24
|
-
return signal.get();
|
25
|
-
}
|
26
|
-
|
27
|
-
const value = useSyncExternalStore(
|
28
|
-
signal.addListenerLazy(),
|
29
|
-
() => signal.get(),
|
30
|
-
() => signal.get(),
|
31
|
-
);
|
32
|
-
|
33
|
-
// Reactive promises can update their value independently of the signal, since
|
34
|
-
// we reuse the same promise object for each result. We need to entangle the
|
35
|
-
// version of the promise here so that we can trigger a re-render when the
|
36
|
-
// promise value updates.
|
37
|
-
//
|
38
|
-
// If hooks could be called in dynamic order this would not be necessary, we
|
39
|
-
// could entangle the promise when it is used. But, because that is not the
|
40
|
-
// case, we need to eagerly entangle.
|
41
|
-
if (typeof value === 'object' && value !== null && isReactivePromise(value)) {
|
42
|
-
if (isReactiveSubscription(value)) {
|
43
|
-
useDerivedSignal(value['_signal'] as DerivedSignal<any, unknown[]>);
|
44
|
-
}
|
45
|
-
|
46
|
-
useStateSignal(value['_version']);
|
47
|
-
}
|
48
|
-
|
49
|
-
return value as ReactiveValue<T>;
|
50
|
-
}
|
package/src/react/state.ts
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
import { useRef } from 'react';
|
2
|
-
import { state } from '../hooks.js';
|
3
|
-
import { SignalOptions, StateSignal } from '../types.js';
|
4
|
-
|
5
|
-
export function useStateSignal<T>(value: T, opts?: SignalOptions<T, unknown[]>): StateSignal<T> {
|
6
|
-
const ref = useRef<StateSignal<T> | undefined>(undefined);
|
7
|
-
|
8
|
-
if (!ref.current) {
|
9
|
-
ref.current = state(value, opts);
|
10
|
-
}
|
11
|
-
|
12
|
-
return ref.current;
|
13
|
-
}
|