@preact/signals-react 3.1.1 → 3.2.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/CHANGELOG.md +20 -0
- package/README.md +25 -20
- package/package.json +2 -2
- package/runtime/dist/index.d.ts +3 -3
- package/runtime/dist/runtime.js +1 -1
- package/runtime/dist/runtime.js.map +1 -1
- package/runtime/dist/runtime.min.js +1 -1
- package/runtime/dist/runtime.min.js.map +1 -1
- package/runtime/dist/runtime.mjs +1 -1
- package/runtime/dist/runtime.mjs.map +1 -1
- package/runtime/dist/runtime.module.js +1 -1
- package/runtime/dist/runtime.module.js.map +1 -1
- package/runtime/src/index.ts +12 -5
- package/utils/dist/index.d.ts +1 -1
- package/utils/dist/utils.js.map +1 -1
- package/utils/dist/utils.min.js.map +1 -1
- package/utils/dist/utils.mjs.map +1 -1
- package/utils/dist/utils.module.js.map +1 -1
- package/utils/src/index.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @preact/signals-react
|
|
2
2
|
|
|
3
|
+
## 3.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#711](https://github.com/preactjs/signals/pull/711) [`4b96199`](https://github.com/preactjs/signals/commit/4b9619999f9133398a2bd25ae7dd5300d71ad2ac) Thanks [@calebeby](https://github.com/calebeby)! - Narrow types for Show utility, the callback is truthy by design
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`4045d2d`](https://github.com/preactjs/signals/commit/4045d2d86b720546848d5163d5b683792c0a5af3)]:
|
|
10
|
+
- @preact/signals-core@1.11.0
|
|
11
|
+
|
|
12
|
+
## 3.2.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- [#634](https://github.com/preactjs/signals/pull/634) [`62bed44`](https://github.com/preactjs/signals/commit/62bed44b0f298ac0097060289bfecd73f030b146) Thanks [@JoviDeCroock](https://github.com/JoviDeCroock)! - Add an option to specify a watched/unwatched callback to a signal
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies [[`587e702`](https://github.com/preactjs/signals/commit/587e702f8db9a8e67fe2cdf8dda0a4bffe5fc195), [`62bed44`](https://github.com/preactjs/signals/commit/62bed44b0f298ac0097060289bfecd73f030b146)]:
|
|
21
|
+
- @preact/signals-core@1.9.0
|
|
22
|
+
|
|
3
23
|
## 3.1.1
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -7,21 +7,26 @@ Signals is a performant state management library with two primary goals:
|
|
|
7
7
|
|
|
8
8
|
Read the [announcement post](https://preactjs.com/blog/introducing-signals/) to learn more about which problems signals solves and how it came to be.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- [
|
|
17
|
-
- [`signal(initialValue)`](../../README.md#signalinitialvalue)
|
|
18
|
-
- [`signal.peek()`](../../README.md#signalpeek)
|
|
19
|
-
- [`computed(fn)`](../../README.md#computedfn)
|
|
20
|
-
- [`effect(fn)`](../../README.md#effectfn)
|
|
21
|
-
- [`batch(fn)`](../../README.md#batchfn)
|
|
22
|
-
- [`untracked(fn)`](../../README.md#untrackedfn)
|
|
10
|
+
- [Core API](../core/README.md#guide--api)
|
|
11
|
+
- [`signal(initialValue)`](../core/README.md#signalinitialvalue)
|
|
12
|
+
- [`signal.peek()`](../core/README.md#signalpeek)
|
|
13
|
+
- [`computed(fn)`](../core/README.md#computedfn)
|
|
14
|
+
- [`effect(fn)`](../core/README.md#effectfn)
|
|
15
|
+
- [`batch(fn)`](../core/README.md#batchfn)
|
|
16
|
+
- [`untracked(fn)`](../core/README.md#untrackedfn)
|
|
23
17
|
- [React Integration](#react-integration)
|
|
18
|
+
- [Babel Transform](#babel-transform)
|
|
19
|
+
- [`useSignals` hook](#usesignals-hook)
|
|
24
20
|
- [Hooks](#hooks)
|
|
21
|
+
- [Using signals with React's SSR APIs](#using-signals-with-reacts-ssr-apis)
|
|
22
|
+
- [Rendering optimizations](#rendering-optimizations)
|
|
23
|
+
- [Utility Components and Hooks](#utility-components-and-hooks)
|
|
24
|
+
- [Show Component](#show-component)
|
|
25
|
+
- [For Component](#for-component)
|
|
26
|
+
- [Additional Hooks](#additional-hooks)
|
|
27
|
+
- [`useLiveSignal`](#uselivesignal)
|
|
28
|
+
- [`useSignalRef`](#usesignalref)
|
|
29
|
+
- [Limitations](#limitations)
|
|
25
30
|
- [License](#license)
|
|
26
31
|
|
|
27
32
|
## React Integration
|
|
@@ -132,11 +137,11 @@ To opt into this optimization, simply pass the signal directly instead of access
|
|
|
132
137
|
> **Note**
|
|
133
138
|
> The content is wrapped in a React Fragment due to React 18's newer, more strict children types.
|
|
134
139
|
|
|
135
|
-
|
|
140
|
+
### Utility Components and Hooks
|
|
136
141
|
|
|
137
142
|
The `@preact/signals-react/utils` package provides additional utility components and hooks to make working with signals even easier.
|
|
138
143
|
|
|
139
|
-
|
|
144
|
+
#### Show Component
|
|
140
145
|
|
|
141
146
|
The `Show` component provides a declarative way to conditionally render content based on a signal's value.
|
|
142
147
|
|
|
@@ -160,7 +165,7 @@ function App() {
|
|
|
160
165
|
}
|
|
161
166
|
```
|
|
162
167
|
|
|
163
|
-
|
|
168
|
+
#### For Component
|
|
164
169
|
|
|
165
170
|
The `For` component helps you render lists from signal arrays with automatic caching of rendered items.
|
|
166
171
|
|
|
@@ -179,9 +184,9 @@ function App() {
|
|
|
179
184
|
}
|
|
180
185
|
```
|
|
181
186
|
|
|
182
|
-
|
|
187
|
+
#### Additional Hooks
|
|
183
188
|
|
|
184
|
-
|
|
189
|
+
##### useLiveSignal
|
|
185
190
|
|
|
186
191
|
The `useLiveSignal` hook allows you to create a local signal that stays synchronized with an external signal.
|
|
187
192
|
|
|
@@ -197,7 +202,7 @@ function Component() {
|
|
|
197
202
|
}
|
|
198
203
|
```
|
|
199
204
|
|
|
200
|
-
|
|
205
|
+
##### useSignalRef
|
|
201
206
|
|
|
202
207
|
The `useSignalRef` hook creates a signal that behaves like a React ref with a `.current` property.
|
|
203
208
|
|
|
@@ -210,7 +215,7 @@ function Component() {
|
|
|
210
215
|
}
|
|
211
216
|
```
|
|
212
217
|
|
|
213
|
-
|
|
218
|
+
### Limitations
|
|
214
219
|
|
|
215
220
|
This version of React integration does not support passing signals as DOM attributes. Support for this may be added at a later date.
|
|
216
221
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@preact/signals-react",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Manage state with style in React",
|
|
6
6
|
"keywords": [],
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"README.md"
|
|
62
62
|
],
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@preact/signals-core": "^1.
|
|
64
|
+
"@preact/signals-core": "^1.11.0",
|
|
65
65
|
"use-sync-external-store": "^1.2.0"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
package/runtime/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Signal, ReadonlySignal } from "@preact/signals-core";
|
|
1
|
+
import { Signal, ReadonlySignal, SignalOptions } from "@preact/signals-core";
|
|
2
2
|
export declare function wrapJsx<T>(jsx: T): T;
|
|
3
3
|
declare const symDispose: unique symbol;
|
|
4
4
|
interface Effect {
|
|
@@ -56,8 +56,8 @@ export declare function ensureFinalCleanup(): void;
|
|
|
56
56
|
*/
|
|
57
57
|
export declare function _useSignalsImplementation(_usage?: EffectStoreUsage): EffectStore;
|
|
58
58
|
export declare function useSignals(usage?: EffectStoreUsage): EffectStore;
|
|
59
|
-
export declare function useSignal<T>(value: T): Signal<T>;
|
|
59
|
+
export declare function useSignal<T>(value: T, options?: SignalOptions<T>): Signal<T>;
|
|
60
60
|
export declare function useSignal<T = undefined>(): Signal<T | undefined>;
|
|
61
|
-
export declare function useComputed<T>(compute: () => T): ReadonlySignal<T>;
|
|
61
|
+
export declare function useComputed<T>(compute: () => T, options?: SignalOptions<T>): ReadonlySignal<T>;
|
|
62
62
|
export declare function useSignalEffect(cb: () => void | (() => void)): void;
|
|
63
63
|
export {};
|
package/runtime/dist/runtime.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var n,t=require("@preact/signals-core"),e=require("react"),r=require("use-sync-external-store/shim/index.js"),i=e.version.split(".").map(Number)[0],u=[],o=Symbol.for(i>=19?"react.transitional.element":"react.element"),f=Symbol.dispose||Symbol.for("Symbol.dispose");function c(t,e){var r=e.effect.S();n=e;return s.bind(e,t,r)}function s(t,e){e();n=t}var a,l,v=function(){},p=((a={u:0,effect:{s:void 0,c:function(){},S:function(){return v},d:function(){}},subscribe:function(){return v},getSnapshot:function(){return 0},S:function(){},f:function(){}})[f]=function(){},a),d=Promise.prototype.then.bind(Promise.resolve());function b(){if(!l)l=d(y)}function y(){var t;l=void 0;null==(t=n)||t.f()}var g="undefined"!=typeof window?e.useLayoutEffect:e.useEffect;function h(i){if(void 0===i)i=0;b();var u=e.useRef();if(null==u.current)if("undefined"==typeof window)u.current=p;else u.current=function(e){var r,i,u,o,s=0,a=t.effect(function(){i=this});i.c=function(){s=s+1|0;if(o)o()};return(r={u:e,effect:i,subscribe:function(n){o=n;return function(){s=s+1|0;o=void 0;a()}},getSnapshot:function(){return s},S:function(){if(null!=n){var t=n.u,e=this.u;if(0==t&&0==e||0==t&&1==e){n.f();u=c(void 0,this)}else if(1==t&&0==e||2==t&&0==e);else u=c(n,this)}else u=c(void 0,this)},f:function(){var n=u;u=void 0;null==n||n()}})[f]=function(){this.f()},r}(i);var o=u.current;r.useSyncExternalStore(o.subscribe,o.getSnapshot,o.getSnapshot);o.S();if(0===i)g(y);return o}Object.defineProperties(t.Signal.prototype,{$$typeof:{configurable:!0,value:o},type:{configurable:!0,value:function(n){var t=n.data,e=h(1);try{return t.value}finally{e.f()}}},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});exports._useSignalsImplementation=h;exports.ensureFinalCleanup=b;exports.useComputed=function(n){var
|
|
1
|
+
var n,t=require("@preact/signals-core"),e=require("react"),r=require("use-sync-external-store/shim/index.js"),i=e.version.split(".").map(Number)[0],u=[],o=Symbol.for(i>=19?"react.transitional.element":"react.element"),f=Symbol.dispose||Symbol.for("Symbol.dispose");function c(t,e){var r=e.effect.S();n=e;return s.bind(e,t,r)}function s(t,e){e();n=t}var a,l,v=function(){},p=((a={u:0,effect:{s:void 0,c:function(){},S:function(){return v},d:function(){}},subscribe:function(){return v},getSnapshot:function(){return 0},S:function(){},f:function(){}})[f]=function(){},a),d=Promise.prototype.then.bind(Promise.resolve());function b(){if(!l)l=d(y)}function y(){var t;l=void 0;null==(t=n)||t.f()}var g="undefined"!=typeof window?e.useLayoutEffect:e.useEffect;function h(i){if(void 0===i)i=0;b();var u=e.useRef();if(null==u.current)if("undefined"==typeof window)u.current=p;else u.current=function(e){var r,i,u,o,s=0,a=t.effect(function(){i=this});i.c=function(){s=s+1|0;if(o)o()};return(r={u:e,effect:i,subscribe:function(n){o=n;return function(){s=s+1|0;o=void 0;a()}},getSnapshot:function(){return s},S:function(){if(null!=n){var t=n.u,e=this.u;if(0==t&&0==e||0==t&&1==e){n.f();u=c(void 0,this)}else if(1==t&&0==e||2==t&&0==e);else u=c(n,this)}else u=c(void 0,this)},f:function(){var n=u;u=void 0;null==n||n()}})[f]=function(){this.f()},r}(i);var o=u.current;r.useSyncExternalStore(o.subscribe,o.getSnapshot,o.getSnapshot);o.S();if(0===i)g(y);return o}Object.defineProperties(t.Signal.prototype,{$$typeof:{configurable:!0,value:o},type:{configurable:!0,value:function(n){var t=n.data,e=h(1);try{return t.value}finally{e.f()}}},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});exports._useSignalsImplementation=h;exports.ensureFinalCleanup=b;exports.useComputed=function(n,r){var i=e.useRef(n);i.current=n;return e.useMemo(function(){return t.computed(function(){return i.current()},r)},u)};exports.useSignal=function(n,r){return e.useMemo(function(){return t.signal(n,r)},u)};exports.useSignalEffect=function(n){var r=e.useRef(n);r.current=n;e.useEffect(function(){return t.effect(function(){return r.current()})},u)};exports.useSignals=function(n){return h(n)};exports.wrapJsx=function(n){if("function"!=typeof n)return n;else return function(e,r){if("string"==typeof e&&r)for(var i in r){var u=r[i];if("children"!==i&&u instanceof t.Signal)r[i]=u.value}return n.call.apply(n,[n,e,r].concat([].slice.call(arguments,2)))}};//# sourceMappingURL=runtime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tsignal,\n\tcomputed,\n\teffect,\n\tSignal,\n\tReadonlySignal,\n} from \"@preact/signals-core\";\nimport {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tuseLayoutEffect,\n\tversion as reactVersion,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nconst [major] = reactVersion.split(\".\").map(Number);\nconst Empty = [] as const;\n// V19 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\n// V18 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactElemType = Symbol.for(\n\tmajor >= 19 ? \"react.transitional.element\" : \"react.element\"\n);\n\nexport function wrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst symDispose: unique symbol =\n\t(Symbol as any).dispose || Symbol.for(\"Symbol.dispose\");\n\ninterface Effect {\n\t_sources: object | undefined;\n\t_start(): () => void;\n\t_callback(): void;\n\t_dispose(): void;\n}\n\n/**\n * Use this flag to represent a bare `useSignals` call that doesn't manually\n * close its effect store and relies on auto-closing when the next useSignals is\n * called or after a microtask\n */\nconst UNMANAGED = 0;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a component's render method. This is the default usage\n * that the react-transform plugin uses.\n */\nconst MANAGED_COMPONENT = 1;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a hook body. This is the default usage that the\n * react-transform plugin uses.\n */\nconst MANAGED_HOOK = 2;\n\n/**\n * An enum defining how this store is used. See the documentation for each enum\n * member for more details.\n * @see {@link UNMANAGED}\n * @see {@link MANAGED_COMPONENT}\n * @see {@link MANAGED_HOOK}\n */\ntype EffectStoreUsage =\n\t| typeof UNMANAGED\n\t| typeof MANAGED_COMPONENT\n\t| typeof MANAGED_HOOK;\n\nexport interface EffectStore {\n\t/**\n\t * An enum defining how this hook is used and whether it is invoked in a\n\t * component's body or hook body. See the comment on `EffectStoreUsage` for\n\t * more details.\n\t */\n\treadonly _usage: EffectStoreUsage;\n\treadonly effect: Effect;\n\tsubscribe(onStoreChange: () => void): () => void;\n\tgetSnapshot(): number;\n\t/** startEffect - begin tracking signals used in this component */\n\t_start(): void;\n\t/** finishEffect - stop tracking the signals used in this component */\n\tf(): void;\n\t[symDispose](): void;\n}\n\nlet currentStore: EffectStore | undefined;\n\nfunction startComponentEffect(\n\tprevStore: EffectStore | undefined,\n\tnextStore: EffectStore\n) {\n\tconst endEffect = nextStore.effect._start();\n\tcurrentStore = nextStore;\n\n\treturn finishComponentEffect.bind(nextStore, prevStore, endEffect);\n}\n\nfunction finishComponentEffect(\n\tthis: EffectStore,\n\tprevStore: EffectStore | undefined,\n\tendEffect: () => void\n) {\n\tendEffect();\n\tcurrentStore = prevStore;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a\n * 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the\n * component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the\n * `effect._callback' is called, we update our store version and tell React to\n * re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://react.dev/reference/react/useSyncExternalStore\n * @see\n * https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n *\n * @param _usage An enum defining how this hook is used and whether it is\n * invoked in a component's body or hook body. See the comment on\n * `EffectStoreUsage` for more details.\n */\nfunction createEffectStore(_usage: EffectStoreUsage): EffectStore {\n\tlet effectInstance!: Effect;\n\tlet endEffect: (() => void) | undefined;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\teffectInstance = this;\n\t});\n\teffectInstance._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\t_usage,\n\t\teffect: effectInstance,\n\t\tsubscribe(onStoreChange) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t\t_start() {\n\t\t\t// In general, we want to support two kinds of usages of useSignals:\n\t\t\t//\n\t\t\t// A) Managed: calling useSignals in a component or hook body wrapped in a\n\t\t\t// try/finally (like what the react-transform plugin does)\n\t\t\t//\n\t\t\t// B) Unmanaged: Calling useSignals directly without wrapping in a\n\t\t\t// try/finally\n\t\t\t//\n\t\t\t// For managed, we finish the effect in the finally block of the component\n\t\t\t// or hook body. For unmanaged, we finish the effect in the next\n\t\t\t// useSignals call or after a microtask.\n\t\t\t//\n\t\t\t// There are different tradeoffs which each approach. With managed, using\n\t\t\t// a try/finally ensures that only signals used in the component or hook\n\t\t\t// body are tracked. However, signals accessed in render props are missed\n\t\t\t// because the render prop is invoked in another component that may or may\n\t\t\t// not realize it is rendering signals accessed in the render prop it is\n\t\t\t// given.\n\t\t\t//\n\t\t\t// The other approach is \"unmanaged\": to call useSignals directly without\n\t\t\t// wrapping in a try/finally. This approach is easier to manually write in\n\t\t\t// situations where a build step isn't available but does open up the\n\t\t\t// possibility of catching signals accessed in other code before the\n\t\t\t// effect is closed (e.g. in a layout effect). Most situations where this\n\t\t\t// could happen are generally consider bad patterns or bugs. For example,\n\t\t\t// using a signal in a component and not having a call to `useSignals`\n\t\t\t// would be an bug. Or using a signal in `useLayoutEffect` is generally\n\t\t\t// not recommended since that layout effect won't update when the signals'\n\t\t\t// value change.\n\t\t\t//\n\t\t\t// To support both approaches, we need to track how each invocation of\n\t\t\t// useSignals is used, so we can properly transition between different\n\t\t\t// kinds of usages.\n\t\t\t//\n\t\t\t// The following table shows the different scenarios and how we should\n\t\t\t// handle them.\n\t\t\t//\n\t\t\t// Key:\n\t\t\t// 0 = UNMANAGED\n\t\t\t// 1 = MANAGED_COMPONENT\n\t\t\t// 2 = MANAGED_HOOK\n\t\t\t//\n\t\t\t// Pattern:\n\t\t\t// prev store usage -> this store usage: action to take\n\t\t\t//\n\t\t\t// - 0 -> 0: finish previous effect (unknown to unknown)\n\t\t\t//\n\t\t\t// We don't know how the previous effect was used, so we need to finish\n\t\t\t// it before starting the next effect.\n\t\t\t//\n\t\t\t// - 0 -> 1: finish previous effect\n\t\t\t//\n\t\t\t// Assume previous invocation was another component or hook from another\n\t\t\t// component. Nested component renders (renderToStaticMarkup within a\n\t\t\t// component's render) won't be supported with bare useSignals calls.\n\t\t\t//\n\t\t\t// - 0 -> 2: capture & restore\n\t\t\t//\n\t\t\t// Previous invocation could be a component or a hook. Either way,\n\t\t\t// restore it after our invocation so that it can continue to capture\n\t\t\t// any signals after we exit.\n\t\t\t//\n\t\t\t// - 1 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 1 -> 1: capture & restore (e.g. component calls renderToStaticMarkup)\n\t\t\t// - 1 -> 2: capture & restore (e.g. hook)\n\t\t\t//\n\t\t\t// - 2 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 2 -> 1: capture & restore (e.g. hook calls renderToStaticMarkup)\n\t\t\t// - 2 -> 2: capture & restore (e.g. nested hook calls)\n\n\t\t\tif (currentStore == undefined) {\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst prevUsage = currentStore._usage;\n\t\t\tconst thisUsage = this._usage;\n\n\t\t\tif (\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == UNMANAGED) || // 0 -> 0\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == MANAGED_COMPONENT) // 0 -> 1\n\t\t\t) {\n\t\t\t\t// finish previous effect\n\t\t\t\tcurrentStore.f();\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t} else if (\n\t\t\t\t(prevUsage == MANAGED_COMPONENT && thisUsage == UNMANAGED) || // 1 -> 0\n\t\t\t\t(prevUsage == MANAGED_HOOK && thisUsage == UNMANAGED) // 2 -> 0\n\t\t\t) {\n\t\t\t\t// Do nothing since it'll be captured by current effect store\n\t\t\t} else {\n\t\t\t\t// nested scenarios, so capture and restore the previous effect store\n\t\t\t\tendEffect = startComponentEffect(currentStore, this);\n\t\t\t}\n\t\t},\n\t\tf() {\n\t\t\tconst end = endEffect;\n\t\t\tendEffect = undefined;\n\t\t\tend?.();\n\t\t},\n\t\t[symDispose]() {\n\t\t\tthis.f();\n\t\t},\n\t};\n}\n\nconst noop = () => {};\n\nfunction createEmptyEffectStore(): EffectStore {\n\treturn {\n\t\t_usage: UNMANAGED,\n\t\teffect: {\n\t\t\t_sources: undefined,\n\t\t\t_callback() {},\n\t\t\t_start() {\n\t\t\t\treturn /* endEffect */ noop;\n\t\t\t},\n\t\t\t_dispose() {},\n\t\t},\n\t\tsubscribe() {\n\t\t\treturn /* unsubscribe */ noop;\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn 0;\n\t\t},\n\t\t_start() {},\n\t\tf() {},\n\t\t[symDispose]() {},\n\t};\n}\n\nconst emptyEffectStore = createEmptyEffectStore();\n\nconst _queueMicroTask = Promise.prototype.then.bind(Promise.resolve());\n\nlet finalCleanup: Promise<void> | undefined;\nexport function ensureFinalCleanup() {\n\tif (!finalCleanup) {\n\t\tfinalCleanup = _queueMicroTask(cleanupTrailingStore);\n\t}\n}\nfunction cleanupTrailingStore() {\n\tfinalCleanup = undefined;\n\tcurrentStore?.f();\n}\n\nconst useIsomorphicLayoutEffect =\n\ttypeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\n/**\n * Custom hook to create the effect to track signals used during render and\n * subscribe to changes to rerender the component when the signals change.\n */\nexport function _useSignalsImplementation(\n\t_usage: EffectStoreUsage = UNMANAGED\n): EffectStore {\n\tensureFinalCleanup();\n\n\tconst storeRef = useRef<EffectStore>();\n\tif (storeRef.current == null) {\n\t\tif (typeof window === \"undefined\") {\n\t\t\tstoreRef.current = emptyEffectStore;\n\t\t} else {\n\t\t\tstoreRef.current = createEffectStore(_usage);\n\t\t}\n\t}\n\n\tconst store = storeRef.current;\n\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\tstore._start();\n\t// note: _usage is a constant here, so conditional is okay\n\tif (_usage === UNMANAGED) useIsomorphicLayoutEffect(cleanupTrailingStore);\n\n\treturn store;\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node or JSX.\n */\nfunction SignalValue({ data }: { data: Signal }) {\n\tconst store = _useSignalsImplementation(1);\n\ttry {\n\t\treturn data.value;\n\t} finally {\n\t\tstore.f();\n\t}\n}\n\n// Decorate Signals so React renders them as <SignalValue> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: SignalValue },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignals(usage?: EffectStoreUsage): EffectStore {\n\treturn _useSignalsImplementation(usage);\n}\n\nexport function useSignal<T>(value: T): Signal<T>;\nexport function useSignal<T = undefined>(): Signal<T | undefined>;\nexport function useSignal<T>(value?: T) {\n\treturn useMemo(() => signal<T | undefined>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => T): ReadonlySignal<T> {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(function (this: Effect) {\n\t\t\treturn callback.current();\n\t\t});\n\t}, Empty);\n}\n"],"names":["currentStore","major","reactVersion","split","map","Number","Empty","ReactElemType","Symbol","symDispose","dispose","startComponentEffect","prevStore","nextStore","endEffect","effect","_start","finishComponentEffect","bind","_ref2","finalCleanup","noop","emptyEffectStore","_usage","_sources","undefined","_callback","_dispose","subscribe","getSnapshot","f","_queueMicroTask","Promise","prototype","then","resolve","ensureFinalCleanup","cleanupTrailingStore","_currentStore","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","_useSignalsImplementation","storeRef","useRef","current","_ref","effectInstance","onChangeNotifyReact","version","unsubscribe","this","onStoreChange","prevUsage","thisUsage","end","createEffectStore","store","useSyncExternalStore","Object","defineProperties","Signal","$$typeof","configurable","value","type","_ref3","data","props","get","ref","exports","useComputed","compute","$compute","useMemo","computed","useSignal","signal","useSignalEffect","cb","callback","useSignals","usage","wrapJsx","jsx","i","v","call","apply","concat","slice","arguments"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tsignal,\n\tcomputed,\n\teffect,\n\tSignal,\n\tReadonlySignal,\n\tSignalOptions,\n} from \"@preact/signals-core\";\nimport {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tuseLayoutEffect,\n\tversion as reactVersion,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nconst [major] = reactVersion.split(\".\").map(Number);\nconst Empty = [] as const;\n// V19 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\n// V18 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactElemType = Symbol.for(\n\tmajor >= 19 ? \"react.transitional.element\" : \"react.element\"\n);\n\nexport function wrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst symDispose: unique symbol =\n\t(Symbol as any).dispose || Symbol.for(\"Symbol.dispose\");\n\ninterface Effect {\n\t_sources: object | undefined;\n\t_start(): () => void;\n\t_callback(): void;\n\t_dispose(): void;\n}\n\n/**\n * Use this flag to represent a bare `useSignals` call that doesn't manually\n * close its effect store and relies on auto-closing when the next useSignals is\n * called or after a microtask\n */\nconst UNMANAGED = 0;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a component's render method. This is the default usage\n * that the react-transform plugin uses.\n */\nconst MANAGED_COMPONENT = 1;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a hook body. This is the default usage that the\n * react-transform plugin uses.\n */\nconst MANAGED_HOOK = 2;\n\n/**\n * An enum defining how this store is used. See the documentation for each enum\n * member for more details.\n * @see {@link UNMANAGED}\n * @see {@link MANAGED_COMPONENT}\n * @see {@link MANAGED_HOOK}\n */\ntype EffectStoreUsage =\n\t| typeof UNMANAGED\n\t| typeof MANAGED_COMPONENT\n\t| typeof MANAGED_HOOK;\n\nexport interface EffectStore {\n\t/**\n\t * An enum defining how this hook is used and whether it is invoked in a\n\t * component's body or hook body. See the comment on `EffectStoreUsage` for\n\t * more details.\n\t */\n\treadonly _usage: EffectStoreUsage;\n\treadonly effect: Effect;\n\tsubscribe(onStoreChange: () => void): () => void;\n\tgetSnapshot(): number;\n\t/** startEffect - begin tracking signals used in this component */\n\t_start(): void;\n\t/** finishEffect - stop tracking the signals used in this component */\n\tf(): void;\n\t[symDispose](): void;\n}\n\nlet currentStore: EffectStore | undefined;\n\nfunction startComponentEffect(\n\tprevStore: EffectStore | undefined,\n\tnextStore: EffectStore\n) {\n\tconst endEffect = nextStore.effect._start();\n\tcurrentStore = nextStore;\n\n\treturn finishComponentEffect.bind(nextStore, prevStore, endEffect);\n}\n\nfunction finishComponentEffect(\n\tthis: EffectStore,\n\tprevStore: EffectStore | undefined,\n\tendEffect: () => void\n) {\n\tendEffect();\n\tcurrentStore = prevStore;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a\n * 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the\n * component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the\n * `effect._callback' is called, we update our store version and tell React to\n * re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://react.dev/reference/react/useSyncExternalStore\n * @see\n * https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n *\n * @param _usage An enum defining how this hook is used and whether it is\n * invoked in a component's body or hook body. See the comment on\n * `EffectStoreUsage` for more details.\n */\nfunction createEffectStore(_usage: EffectStoreUsage): EffectStore {\n\tlet effectInstance!: Effect;\n\tlet endEffect: (() => void) | undefined;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\teffectInstance = this;\n\t});\n\teffectInstance._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\t_usage,\n\t\teffect: effectInstance,\n\t\tsubscribe(onStoreChange) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t\t_start() {\n\t\t\t// In general, we want to support two kinds of usages of useSignals:\n\t\t\t//\n\t\t\t// A) Managed: calling useSignals in a component or hook body wrapped in a\n\t\t\t// try/finally (like what the react-transform plugin does)\n\t\t\t//\n\t\t\t// B) Unmanaged: Calling useSignals directly without wrapping in a\n\t\t\t// try/finally\n\t\t\t//\n\t\t\t// For managed, we finish the effect in the finally block of the component\n\t\t\t// or hook body. For unmanaged, we finish the effect in the next\n\t\t\t// useSignals call or after a microtask.\n\t\t\t//\n\t\t\t// There are different tradeoffs which each approach. With managed, using\n\t\t\t// a try/finally ensures that only signals used in the component or hook\n\t\t\t// body are tracked. However, signals accessed in render props are missed\n\t\t\t// because the render prop is invoked in another component that may or may\n\t\t\t// not realize it is rendering signals accessed in the render prop it is\n\t\t\t// given.\n\t\t\t//\n\t\t\t// The other approach is \"unmanaged\": to call useSignals directly without\n\t\t\t// wrapping in a try/finally. This approach is easier to manually write in\n\t\t\t// situations where a build step isn't available but does open up the\n\t\t\t// possibility of catching signals accessed in other code before the\n\t\t\t// effect is closed (e.g. in a layout effect). Most situations where this\n\t\t\t// could happen are generally consider bad patterns or bugs. For example,\n\t\t\t// using a signal in a component and not having a call to `useSignals`\n\t\t\t// would be an bug. Or using a signal in `useLayoutEffect` is generally\n\t\t\t// not recommended since that layout effect won't update when the signals'\n\t\t\t// value change.\n\t\t\t//\n\t\t\t// To support both approaches, we need to track how each invocation of\n\t\t\t// useSignals is used, so we can properly transition between different\n\t\t\t// kinds of usages.\n\t\t\t//\n\t\t\t// The following table shows the different scenarios and how we should\n\t\t\t// handle them.\n\t\t\t//\n\t\t\t// Key:\n\t\t\t// 0 = UNMANAGED\n\t\t\t// 1 = MANAGED_COMPONENT\n\t\t\t// 2 = MANAGED_HOOK\n\t\t\t//\n\t\t\t// Pattern:\n\t\t\t// prev store usage -> this store usage: action to take\n\t\t\t//\n\t\t\t// - 0 -> 0: finish previous effect (unknown to unknown)\n\t\t\t//\n\t\t\t// We don't know how the previous effect was used, so we need to finish\n\t\t\t// it before starting the next effect.\n\t\t\t//\n\t\t\t// - 0 -> 1: finish previous effect\n\t\t\t//\n\t\t\t// Assume previous invocation was another component or hook from another\n\t\t\t// component. Nested component renders (renderToStaticMarkup within a\n\t\t\t// component's render) won't be supported with bare useSignals calls.\n\t\t\t//\n\t\t\t// - 0 -> 2: capture & restore\n\t\t\t//\n\t\t\t// Previous invocation could be a component or a hook. Either way,\n\t\t\t// restore it after our invocation so that it can continue to capture\n\t\t\t// any signals after we exit.\n\t\t\t//\n\t\t\t// - 1 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 1 -> 1: capture & restore (e.g. component calls renderToStaticMarkup)\n\t\t\t// - 1 -> 2: capture & restore (e.g. hook)\n\t\t\t//\n\t\t\t// - 2 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 2 -> 1: capture & restore (e.g. hook calls renderToStaticMarkup)\n\t\t\t// - 2 -> 2: capture & restore (e.g. nested hook calls)\n\n\t\t\tif (currentStore == undefined) {\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst prevUsage = currentStore._usage;\n\t\t\tconst thisUsage = this._usage;\n\n\t\t\tif (\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == UNMANAGED) || // 0 -> 0\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == MANAGED_COMPONENT) // 0 -> 1\n\t\t\t) {\n\t\t\t\t// finish previous effect\n\t\t\t\tcurrentStore.f();\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t} else if (\n\t\t\t\t(prevUsage == MANAGED_COMPONENT && thisUsage == UNMANAGED) || // 1 -> 0\n\t\t\t\t(prevUsage == MANAGED_HOOK && thisUsage == UNMANAGED) // 2 -> 0\n\t\t\t) {\n\t\t\t\t// Do nothing since it'll be captured by current effect store\n\t\t\t} else {\n\t\t\t\t// nested scenarios, so capture and restore the previous effect store\n\t\t\t\tendEffect = startComponentEffect(currentStore, this);\n\t\t\t}\n\t\t},\n\t\tf() {\n\t\t\tconst end = endEffect;\n\t\t\tendEffect = undefined;\n\t\t\tend?.();\n\t\t},\n\t\t[symDispose]() {\n\t\t\tthis.f();\n\t\t},\n\t};\n}\n\nconst noop = () => {};\n\nfunction createEmptyEffectStore(): EffectStore {\n\treturn {\n\t\t_usage: UNMANAGED,\n\t\teffect: {\n\t\t\t_sources: undefined,\n\t\t\t_callback() {},\n\t\t\t_start() {\n\t\t\t\treturn /* endEffect */ noop;\n\t\t\t},\n\t\t\t_dispose() {},\n\t\t},\n\t\tsubscribe() {\n\t\t\treturn /* unsubscribe */ noop;\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn 0;\n\t\t},\n\t\t_start() {},\n\t\tf() {},\n\t\t[symDispose]() {},\n\t};\n}\n\nconst emptyEffectStore = createEmptyEffectStore();\n\nconst _queueMicroTask = Promise.prototype.then.bind(Promise.resolve());\n\nlet finalCleanup: Promise<void> | undefined;\nexport function ensureFinalCleanup() {\n\tif (!finalCleanup) {\n\t\tfinalCleanup = _queueMicroTask(cleanupTrailingStore);\n\t}\n}\nfunction cleanupTrailingStore() {\n\tfinalCleanup = undefined;\n\tcurrentStore?.f();\n}\n\nconst useIsomorphicLayoutEffect =\n\ttypeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\n/**\n * Custom hook to create the effect to track signals used during render and\n * subscribe to changes to rerender the component when the signals change.\n */\nexport function _useSignalsImplementation(\n\t_usage: EffectStoreUsage = UNMANAGED\n): EffectStore {\n\tensureFinalCleanup();\n\n\tconst storeRef = useRef<EffectStore>();\n\tif (storeRef.current == null) {\n\t\tif (typeof window === \"undefined\") {\n\t\t\tstoreRef.current = emptyEffectStore;\n\t\t} else {\n\t\t\tstoreRef.current = createEffectStore(_usage);\n\t\t}\n\t}\n\n\tconst store = storeRef.current;\n\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\tstore._start();\n\t// note: _usage is a constant here, so conditional is okay\n\tif (_usage === UNMANAGED) useIsomorphicLayoutEffect(cleanupTrailingStore);\n\n\treturn store;\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node or JSX.\n */\nfunction SignalValue({ data }: { data: Signal }) {\n\tconst store = _useSignalsImplementation(1);\n\ttry {\n\t\treturn data.value;\n\t} finally {\n\t\tstore.f();\n\t}\n}\n\n// Decorate Signals so React renders them as <SignalValue> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: SignalValue },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignals(usage?: EffectStoreUsage): EffectStore {\n\treturn _useSignalsImplementation(usage);\n}\n\nexport function useSignal<T>(value: T, options?: SignalOptions<T>): Signal<T>;\nexport function useSignal<T = undefined>(): Signal<T | undefined>;\nexport function useSignal<T>(value?: T, options?: SignalOptions<T>) {\n\treturn useMemo(\n\t\t() => signal<T | undefined>(value, options as SignalOptions),\n\t\tEmpty\n\t);\n}\n\nexport function useComputed<T>(\n\tcompute: () => T,\n\toptions?: SignalOptions<T>\n): ReadonlySignal<T> {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current(), options), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(function (this: Effect) {\n\t\t\treturn callback.current();\n\t\t});\n\t}, Empty);\n}\n"],"names":["currentStore","major","reactVersion","split","map","Number","Empty","ReactElemType","Symbol","symDispose","dispose","startComponentEffect","prevStore","nextStore","endEffect","effect","_start","finishComponentEffect","bind","_ref2","finalCleanup","noop","emptyEffectStore","_usage","_sources","undefined","_callback","_dispose","subscribe","getSnapshot","f","_queueMicroTask","Promise","prototype","then","resolve","ensureFinalCleanup","cleanupTrailingStore","_currentStore","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","_useSignalsImplementation","storeRef","useRef","current","_ref","effectInstance","onChangeNotifyReact","version","unsubscribe","this","onStoreChange","prevUsage","thisUsage","end","createEffectStore","store","useSyncExternalStore","Object","defineProperties","Signal","$$typeof","configurable","value","type","_ref3","data","props","get","ref","exports","useComputed","compute","options","$compute","useMemo","computed","useSignal","signal","useSignalEffect","cb","callback","useSignals","usage","wrapJsx","jsx","i","v","call","apply","concat","slice","arguments"],"mappings":"IAoGIA,0GAnFGC,EAASC,EAAAA,QAAaC,MAAM,KAAKC,IAAIC,QAAhC,GACNC,EAAQ,GAGRC,EAAgBC,OAAM,IAC3BP,GAAS,GAAK,6BAA+B,iBAoBxCQ,EACJD,OAAeE,SAAWF,OAAM,IAAK,kBA2DvC,SAASG,EACRC,EACAC,GAEA,IAAMC,EAAYD,EAAUE,OAAOC,IACnChB,EAAea,EAEf,OAAOI,EAAsBC,KAAKL,EAAWD,EAAWE,EACzD,CAEA,SAASG,EAERL,EACAE,GAEAA,IACAd,EAAeY,CAChB,CAyKA,IAE+BO,EA2B3BC,EA7BEC,EAAO,WAAQ,EAyBfC,IAtBLH,EACCI,CAAAA,EA3OgB,EA4OhBR,OAAQ,CACPS,OAAUC,EACVC,EAAS,aACTV,EAAM,WACL,OAAuBK,CACxB,EACAM,EAAQ,cAETC,UAAA,WACC,OAAyBP,CAC1B,EACAQ,YAAW,WACV,OACD,CAAA,EACAb,EAAA,WAAW,EACXc,EAAA,eACCrB,GAAW,WAAK,EAAAU,GAMbY,EAAkBC,QAAQC,UAAUC,KAAKhB,KAAKc,QAAQG,WAG5C,SAAAC,IACf,IAAKhB,EACJA,EAAeW,EAAgBM,EAEjC,CACA,SAASA,IAAoBC,IAAAA,EAC5BlB,OAAeK,EACfa,OAAAA,EAAAtC,IAAAsC,EAAcR,GACf,CAEA,IAAMS,EACa,oBAAXC,OAAyBC,EAAeA,gBAAGC,EAASA,UAM5C,SAAAC,EACfpB,GAAAA,QAAAA,IAAAA,EAAAA,EAvRiB,EAyRjBa,IAEA,IAAMQ,EAAWC,EAAMA,SACvB,GAAwB,MAApBD,EAASE,QACZ,GAAsB,oBAAXN,OACVI,EAASE,QAAUxB,OAEnBsB,EAASE,QA3MZ,SAA2BvB,GAAwBwB,IAAAA,EAC9CC,EACAlC,EAEAmC,EADAC,EAAU,EAGVC,EAAcpC,EAAMA,OAAC,WACxBiC,EAAiBI,IAClB,GACAJ,EAAetB,EAAY,WAC1BwB,EAAWA,EAAU,EAAK,EAC1B,GAAID,EAAqBA,GAC1B,EAEA,OAAAF,EAAA,CACCxB,EAAAA,EACAR,OAAQiC,EACRpB,UAAA,SAAUyB,GACTJ,EAAsBI,EAEtB,OAAO,WAWNH,EAAWA,EAAU,EAAK,EAC1BD,OAAsBxB,EACtB0B,GACD,CACD,EACAtB,YAAW,WACV,OAAOqB,CACR,EACAlC,EAAA,WAuEC,GAAoBS,MAAhBzB,EAAJ,CAKA,IAAMsD,EAAYtD,EAAauB,EACzBgC,EAAYH,KAAK7B,EAEvB,GA3Me,GA4Mb+B,GA5Ma,GA4MaC,GA5Mb,GA6MbD,GAvMqB,GAuMKC,EAC1B,CAEDvD,EAAa8B,IACbhB,EAAYH,OAAqBc,EAAW2B,KAC7C,MAAO,GA5MgB,GA6MrBE,GAnNa,GAmNqBC,GAvMlB,GAwMhBD,GApNa,GAoNgBC,QAK9BzC,EAAYH,EAAqBX,EAAcoD,KAnBhD,MAFCtC,EAAYH,OAAqBc,EAAW2B,KAuB9C,EACAtB,EAAA,WACC,IAAM0B,EAAM1C,EACZA,OAAYW,EACZ+B,MAAAA,GAAAA,GACD,IACC/C,GAAU,WACV2C,KAAKtB,GACN,EAACiB,CAEH,CA2DsBU,CAAkBlC,GAIvC,IAAMmC,EAAQd,EAASE,QACvBa,EAAoBA,qBAACD,EAAM9B,UAAW8B,EAAM7B,YAAa6B,EAAM7B,aAC/D6B,EAAM1C,IAEN,GAxSiB,IAwSbO,EAAsBgB,EAA0BF,GAEpD,OAAOqB,CACR,CAeAE,OAAOC,iBAAiBC,EAAMA,OAAC7B,UAAW,CACzC8B,SAAU,CAAEC,cAAc,EAAMC,MAAO1D,GACvC2D,KAAM,CAAEF,cAAc,EAAMC,MAZ7B,SAAoBE,GAA2B,IAAxBC,EAAID,EAAJC,KAChBV,EAAQf,EAA0B,GACxC,IACC,OAAOyB,EAAKH,KAGb,CAFC,QACAP,EAAM5B,GACP,CACD,GAMCuC,MAAO,CACNL,cAAc,EACdM,IAAA,WACC,MAAO,CAAEF,KAAMhB,KAChB,GAEDmB,IAAK,CAAEP,cAAc,EAAMC,MAAO,QAkCnCO,QAAA7B,0BAAAA,EAAA6B,QAAApC,mBAAAA,EAAAoC,QAAAC,YAlBgB,SACfC,EACAC,GAEA,IAAMC,EAAW/B,EAAMA,OAAC6B,GACxBE,EAAS9B,QAAU4B,EACnB,OAAOG,EAAOA,QAAC,WAAA,OAAMC,EAAQA,SAAI,WAAA,OAAMF,EAAS9B,SAAS,EAAE6B,EAAQ,EAAErE,EACtE,EAWAkE,QAAAO,UAzBgB,SAAad,EAAWU,GACvC,OAAOE,EAAOA,QACb,WAAA,OAAMG,EAAAA,OAAsBf,EAAOU,EAAyB,EAC5DrE,EAEF,EAoBAkE,QAAAS,gBATM,SAA0BC,GAC/B,IAAMC,EAAWtC,EAAAA,OAAOqC,GACxBC,EAASrC,QAAUoC,EAEnBxC,EAAAA,UAAU,WACT,OAAO3B,EAAMA,OAAC,WACb,OAAOoE,EAASrC,SACjB,EACD,EAAGxC,EACJ,EAAAkE,QAAAY,WA/BgB,SAAWC,GAC1B,OAAO1C,EAA0B0C,EAClC,EA6BAb,QAAAc,QArYgB,SAAWC,GAC1B,GAAmB,mBAARA,EAAoB,OAAOA,OAEtC,OAAiBrB,SAAAA,EAAWG,GAC3B,GAAoB,iBAATH,GAAqBG,EAC/B,IAAK,IAAImB,KAAKnB,EAAO,CACpB,IAAIoB,EAAIpB,EAAMmB,GACd,GAAU,aAANA,GAAoBC,aAAa3B,EAAAA,OACpCO,EAAMmB,GAAKC,EAAExB,KAEf,CAGD,OAAOsB,EAAIG,KAAIC,MAARJ,EAASA,CAAAA,EAAKrB,EAAMG,GAAKuB,OAAA,GAAAC,MAAAH,KAAAI,UAAA,IACjC,CACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("@preact/signals-core"),require("react"),require("use-sync-external-store/shim/index.js")):"function"==typeof define&&define.amd?define(["exports","@preact/signals-core","react","use-sync-external-store/shim/index.js"],e):e((n||self).reactSignalsRuntime={},n.preactSignalsCore,n.react,n.index_js)}(this,function(n,e,t,i){var r,u=t.version.split(".").map(Number)[0],o=[],f=Symbol.for(u>=19?"react.transitional.element":"react.element"),c=Symbol.dispose||Symbol.for("Symbol.dispose");function s(n,e){var t=e.effect.S();r=e;return a.bind(e,n,t)}function a(n,e){e();r=n}var l,d,v=function(){},p=((l={u:0,effect:{s:void 0,c:function(){},S:function(){return v},d:function(){}},subscribe:function(){return v},getSnapshot:function(){return 0},S:function(){},f:function(){}})[c]=function(){},l),b=Promise.prototype.then.bind(Promise.resolve());function y(){if(!d)d=b(h)}function h(){var n;d=void 0;null==(n=r)||n.f()}var g="undefined"!=typeof window?t.useLayoutEffect:t.useEffect;function m(n){if(void 0===n)n=0;y();var u=t.useRef();if(null==u.current)if("undefined"==typeof window)u.current=p;else u.current=function(n){var t,i,u,o,f=0,a=e.effect(function(){i=this});i.c=function(){f=f+1|0;if(o)o()};return(t={u:n,effect:i,subscribe:function(n){o=n;return function(){f=f+1|0;o=void 0;a()}},getSnapshot:function(){return f},S:function(){if(null!=r){var n=r.u,e=this.u;if(0==n&&0==e||0==n&&1==e){r.f();u=s(void 0,this)}else if(1==n&&0==e||2==n&&0==e);else u=s(r,this)}else u=s(void 0,this)},f:function(){var n=u;u=void 0;null==n||n()}})[c]=function(){this.f()},t}(n);var o=u.current;i.useSyncExternalStore(o.subscribe,o.getSnapshot,o.getSnapshot);o.S();if(0===n)g(h);return o}Object.defineProperties(e.Signal.prototype,{$$typeof:{configurable:!0,value:f},type:{configurable:!0,value:function(n){var e=n.data,t=m(1);try{return e.value}finally{t.f()}}},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});n.o=m;n.ensureFinalCleanup=y;n.useComputed=function(n){var
|
|
1
|
+
!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("@preact/signals-core"),require("react"),require("use-sync-external-store/shim/index.js")):"function"==typeof define&&define.amd?define(["exports","@preact/signals-core","react","use-sync-external-store/shim/index.js"],e):e((n||self).reactSignalsRuntime={},n.preactSignalsCore,n.react,n.index_js)}(this,function(n,e,t,i){var r,u=t.version.split(".").map(Number)[0],o=[],f=Symbol.for(u>=19?"react.transitional.element":"react.element"),c=Symbol.dispose||Symbol.for("Symbol.dispose");function s(n,e){var t=e.effect.S();r=e;return a.bind(e,n,t)}function a(n,e){e();r=n}var l,d,v=function(){},p=((l={u:0,effect:{s:void 0,c:function(){},S:function(){return v},d:function(){}},subscribe:function(){return v},getSnapshot:function(){return 0},S:function(){},f:function(){}})[c]=function(){},l),b=Promise.prototype.then.bind(Promise.resolve());function y(){if(!d)d=b(h)}function h(){var n;d=void 0;null==(n=r)||n.f()}var g="undefined"!=typeof window?t.useLayoutEffect:t.useEffect;function m(n){if(void 0===n)n=0;y();var u=t.useRef();if(null==u.current)if("undefined"==typeof window)u.current=p;else u.current=function(n){var t,i,u,o,f=0,a=e.effect(function(){i=this});i.c=function(){f=f+1|0;if(o)o()};return(t={u:n,effect:i,subscribe:function(n){o=n;return function(){f=f+1|0;o=void 0;a()}},getSnapshot:function(){return f},S:function(){if(null!=r){var n=r.u,e=this.u;if(0==n&&0==e||0==n&&1==e){r.f();u=s(void 0,this)}else if(1==n&&0==e||2==n&&0==e);else u=s(r,this)}else u=s(void 0,this)},f:function(){var n=u;u=void 0;null==n||n()}})[c]=function(){this.f()},t}(n);var o=u.current;i.useSyncExternalStore(o.subscribe,o.getSnapshot,o.getSnapshot);o.S();if(0===n)g(h);return o}Object.defineProperties(e.Signal.prototype,{$$typeof:{configurable:!0,value:f},type:{configurable:!0,value:function(n){var e=n.data,t=m(1);try{return e.value}finally{t.f()}}},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});n.o=m;n.ensureFinalCleanup=y;n.useComputed=function(n,i){var r=t.useRef(n);r.current=n;return t.useMemo(function(){return e.computed(function(){return r.current()},i)},o)};n.useSignal=function(n,i){return t.useMemo(function(){return e.signal(n,i)},o)};n.useSignalEffect=function(n){var i=t.useRef(n);i.current=n;t.useEffect(function(){return e.effect(function(){return i.current()})},o)};n.useSignals=function(n){return m(n)};n.wrapJsx=function(n){if("function"!=typeof n)return n;else return function(t,i){if("string"==typeof t&&i)for(var r in i){var u=i[r];if("children"!==r&&u instanceof e.Signal)i[r]=u.value}return n.call.apply(n,[n,t,i].concat([].slice.call(arguments,2)))}}});//# sourceMappingURL=runtime.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.min.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tsignal,\n\tcomputed,\n\teffect,\n\tSignal,\n\tReadonlySignal,\n} from \"@preact/signals-core\";\nimport {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tuseLayoutEffect,\n\tversion as reactVersion,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nconst [major] = reactVersion.split(\".\").map(Number);\nconst Empty = [] as const;\n// V19 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\n// V18 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactElemType = Symbol.for(\n\tmajor >= 19 ? \"react.transitional.element\" : \"react.element\"\n);\n\nexport function wrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst symDispose: unique symbol =\n\t(Symbol as any).dispose || Symbol.for(\"Symbol.dispose\");\n\ninterface Effect {\n\t_sources: object | undefined;\n\t_start(): () => void;\n\t_callback(): void;\n\t_dispose(): void;\n}\n\n/**\n * Use this flag to represent a bare `useSignals` call that doesn't manually\n * close its effect store and relies on auto-closing when the next useSignals is\n * called or after a microtask\n */\nconst UNMANAGED = 0;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a component's render method. This is the default usage\n * that the react-transform plugin uses.\n */\nconst MANAGED_COMPONENT = 1;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a hook body. This is the default usage that the\n * react-transform plugin uses.\n */\nconst MANAGED_HOOK = 2;\n\n/**\n * An enum defining how this store is used. See the documentation for each enum\n * member for more details.\n * @see {@link UNMANAGED}\n * @see {@link MANAGED_COMPONENT}\n * @see {@link MANAGED_HOOK}\n */\ntype EffectStoreUsage =\n\t| typeof UNMANAGED\n\t| typeof MANAGED_COMPONENT\n\t| typeof MANAGED_HOOK;\n\nexport interface EffectStore {\n\t/**\n\t * An enum defining how this hook is used and whether it is invoked in a\n\t * component's body or hook body. See the comment on `EffectStoreUsage` for\n\t * more details.\n\t */\n\treadonly _usage: EffectStoreUsage;\n\treadonly effect: Effect;\n\tsubscribe(onStoreChange: () => void): () => void;\n\tgetSnapshot(): number;\n\t/** startEffect - begin tracking signals used in this component */\n\t_start(): void;\n\t/** finishEffect - stop tracking the signals used in this component */\n\tf(): void;\n\t[symDispose](): void;\n}\n\nlet currentStore: EffectStore | undefined;\n\nfunction startComponentEffect(\n\tprevStore: EffectStore | undefined,\n\tnextStore: EffectStore\n) {\n\tconst endEffect = nextStore.effect._start();\n\tcurrentStore = nextStore;\n\n\treturn finishComponentEffect.bind(nextStore, prevStore, endEffect);\n}\n\nfunction finishComponentEffect(\n\tthis: EffectStore,\n\tprevStore: EffectStore | undefined,\n\tendEffect: () => void\n) {\n\tendEffect();\n\tcurrentStore = prevStore;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a\n * 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the\n * component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the\n * `effect._callback' is called, we update our store version and tell React to\n * re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://react.dev/reference/react/useSyncExternalStore\n * @see\n * https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n *\n * @param _usage An enum defining how this hook is used and whether it is\n * invoked in a component's body or hook body. See the comment on\n * `EffectStoreUsage` for more details.\n */\nfunction createEffectStore(_usage: EffectStoreUsage): EffectStore {\n\tlet effectInstance!: Effect;\n\tlet endEffect: (() => void) | undefined;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\teffectInstance = this;\n\t});\n\teffectInstance._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\t_usage,\n\t\teffect: effectInstance,\n\t\tsubscribe(onStoreChange) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t\t_start() {\n\t\t\t// In general, we want to support two kinds of usages of useSignals:\n\t\t\t//\n\t\t\t// A) Managed: calling useSignals in a component or hook body wrapped in a\n\t\t\t// try/finally (like what the react-transform plugin does)\n\t\t\t//\n\t\t\t// B) Unmanaged: Calling useSignals directly without wrapping in a\n\t\t\t// try/finally\n\t\t\t//\n\t\t\t// For managed, we finish the effect in the finally block of the component\n\t\t\t// or hook body. For unmanaged, we finish the effect in the next\n\t\t\t// useSignals call or after a microtask.\n\t\t\t//\n\t\t\t// There are different tradeoffs which each approach. With managed, using\n\t\t\t// a try/finally ensures that only signals used in the component or hook\n\t\t\t// body are tracked. However, signals accessed in render props are missed\n\t\t\t// because the render prop is invoked in another component that may or may\n\t\t\t// not realize it is rendering signals accessed in the render prop it is\n\t\t\t// given.\n\t\t\t//\n\t\t\t// The other approach is \"unmanaged\": to call useSignals directly without\n\t\t\t// wrapping in a try/finally. This approach is easier to manually write in\n\t\t\t// situations where a build step isn't available but does open up the\n\t\t\t// possibility of catching signals accessed in other code before the\n\t\t\t// effect is closed (e.g. in a layout effect). Most situations where this\n\t\t\t// could happen are generally consider bad patterns or bugs. For example,\n\t\t\t// using a signal in a component and not having a call to `useSignals`\n\t\t\t// would be an bug. Or using a signal in `useLayoutEffect` is generally\n\t\t\t// not recommended since that layout effect won't update when the signals'\n\t\t\t// value change.\n\t\t\t//\n\t\t\t// To support both approaches, we need to track how each invocation of\n\t\t\t// useSignals is used, so we can properly transition between different\n\t\t\t// kinds of usages.\n\t\t\t//\n\t\t\t// The following table shows the different scenarios and how we should\n\t\t\t// handle them.\n\t\t\t//\n\t\t\t// Key:\n\t\t\t// 0 = UNMANAGED\n\t\t\t// 1 = MANAGED_COMPONENT\n\t\t\t// 2 = MANAGED_HOOK\n\t\t\t//\n\t\t\t// Pattern:\n\t\t\t// prev store usage -> this store usage: action to take\n\t\t\t//\n\t\t\t// - 0 -> 0: finish previous effect (unknown to unknown)\n\t\t\t//\n\t\t\t// We don't know how the previous effect was used, so we need to finish\n\t\t\t// it before starting the next effect.\n\t\t\t//\n\t\t\t// - 0 -> 1: finish previous effect\n\t\t\t//\n\t\t\t// Assume previous invocation was another component or hook from another\n\t\t\t// component. Nested component renders (renderToStaticMarkup within a\n\t\t\t// component's render) won't be supported with bare useSignals calls.\n\t\t\t//\n\t\t\t// - 0 -> 2: capture & restore\n\t\t\t//\n\t\t\t// Previous invocation could be a component or a hook. Either way,\n\t\t\t// restore it after our invocation so that it can continue to capture\n\t\t\t// any signals after we exit.\n\t\t\t//\n\t\t\t// - 1 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 1 -> 1: capture & restore (e.g. component calls renderToStaticMarkup)\n\t\t\t// - 1 -> 2: capture & restore (e.g. hook)\n\t\t\t//\n\t\t\t// - 2 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 2 -> 1: capture & restore (e.g. hook calls renderToStaticMarkup)\n\t\t\t// - 2 -> 2: capture & restore (e.g. nested hook calls)\n\n\t\t\tif (currentStore == undefined) {\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst prevUsage = currentStore._usage;\n\t\t\tconst thisUsage = this._usage;\n\n\t\t\tif (\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == UNMANAGED) || // 0 -> 0\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == MANAGED_COMPONENT) // 0 -> 1\n\t\t\t) {\n\t\t\t\t// finish previous effect\n\t\t\t\tcurrentStore.f();\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t} else if (\n\t\t\t\t(prevUsage == MANAGED_COMPONENT && thisUsage == UNMANAGED) || // 1 -> 0\n\t\t\t\t(prevUsage == MANAGED_HOOK && thisUsage == UNMANAGED) // 2 -> 0\n\t\t\t) {\n\t\t\t\t// Do nothing since it'll be captured by current effect store\n\t\t\t} else {\n\t\t\t\t// nested scenarios, so capture and restore the previous effect store\n\t\t\t\tendEffect = startComponentEffect(currentStore, this);\n\t\t\t}\n\t\t},\n\t\tf() {\n\t\t\tconst end = endEffect;\n\t\t\tendEffect = undefined;\n\t\t\tend?.();\n\t\t},\n\t\t[symDispose]() {\n\t\t\tthis.f();\n\t\t},\n\t};\n}\n\nconst noop = () => {};\n\nfunction createEmptyEffectStore(): EffectStore {\n\treturn {\n\t\t_usage: UNMANAGED,\n\t\teffect: {\n\t\t\t_sources: undefined,\n\t\t\t_callback() {},\n\t\t\t_start() {\n\t\t\t\treturn /* endEffect */ noop;\n\t\t\t},\n\t\t\t_dispose() {},\n\t\t},\n\t\tsubscribe() {\n\t\t\treturn /* unsubscribe */ noop;\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn 0;\n\t\t},\n\t\t_start() {},\n\t\tf() {},\n\t\t[symDispose]() {},\n\t};\n}\n\nconst emptyEffectStore = createEmptyEffectStore();\n\nconst _queueMicroTask = Promise.prototype.then.bind(Promise.resolve());\n\nlet finalCleanup: Promise<void> | undefined;\nexport function ensureFinalCleanup() {\n\tif (!finalCleanup) {\n\t\tfinalCleanup = _queueMicroTask(cleanupTrailingStore);\n\t}\n}\nfunction cleanupTrailingStore() {\n\tfinalCleanup = undefined;\n\tcurrentStore?.f();\n}\n\nconst useIsomorphicLayoutEffect =\n\ttypeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\n/**\n * Custom hook to create the effect to track signals used during render and\n * subscribe to changes to rerender the component when the signals change.\n */\nexport function _useSignalsImplementation(\n\t_usage: EffectStoreUsage = UNMANAGED\n): EffectStore {\n\tensureFinalCleanup();\n\n\tconst storeRef = useRef<EffectStore>();\n\tif (storeRef.current == null) {\n\t\tif (typeof window === \"undefined\") {\n\t\t\tstoreRef.current = emptyEffectStore;\n\t\t} else {\n\t\t\tstoreRef.current = createEffectStore(_usage);\n\t\t}\n\t}\n\n\tconst store = storeRef.current;\n\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\tstore._start();\n\t// note: _usage is a constant here, so conditional is okay\n\tif (_usage === UNMANAGED) useIsomorphicLayoutEffect(cleanupTrailingStore);\n\n\treturn store;\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node or JSX.\n */\nfunction SignalValue({ data }: { data: Signal }) {\n\tconst store = _useSignalsImplementation(1);\n\ttry {\n\t\treturn data.value;\n\t} finally {\n\t\tstore.f();\n\t}\n}\n\n// Decorate Signals so React renders them as <SignalValue> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: SignalValue },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignals(usage?: EffectStoreUsage): EffectStore {\n\treturn _useSignalsImplementation(usage);\n}\n\nexport function useSignal<T>(value: T): Signal<T>;\nexport function useSignal<T = undefined>(): Signal<T | undefined>;\nexport function useSignal<T>(value?: T) {\n\treturn useMemo(() => signal<T | undefined>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => T): ReadonlySignal<T> {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(function (this: Effect) {\n\t\t\treturn callback.current();\n\t\t});\n\t}, Empty);\n}\n"],"names":["currentStore","major","reactVersion","split","map","Number","Empty","ReactElemType","Symbol","symDispose","dispose","startComponentEffect","prevStore","nextStore","endEffect","effect","_start","finishComponentEffect","bind","_ref2","finalCleanup","noop","emptyEffectStore","_usage","_sources","undefined","_callback","_dispose","subscribe","getSnapshot","f","_queueMicroTask","Promise","prototype","then","resolve","ensureFinalCleanup","cleanupTrailingStore","_currentStore","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","_useSignalsImplementation","storeRef","useRef","current","_ref","effectInstance","onChangeNotifyReact","version","unsubscribe","this","onStoreChange","prevUsage","thisUsage","end","createEffectStore","store","useSyncExternalStore","Object","defineProperties","Signal","$$typeof","configurable","value","type","_ref3","data","props","get","ref","exports","useComputed","compute","$compute","useMemo","computed","useSignal","signal","useSignalEffect","cb","callback","useSignals","usage","wrapJsx","jsx","i","v","call","apply","concat","slice","arguments"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.min.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tsignal,\n\tcomputed,\n\teffect,\n\tSignal,\n\tReadonlySignal,\n\tSignalOptions,\n} from \"@preact/signals-core\";\nimport {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tuseLayoutEffect,\n\tversion as reactVersion,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nconst [major] = reactVersion.split(\".\").map(Number);\nconst Empty = [] as const;\n// V19 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\n// V18 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactElemType = Symbol.for(\n\tmajor >= 19 ? \"react.transitional.element\" : \"react.element\"\n);\n\nexport function wrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst symDispose: unique symbol =\n\t(Symbol as any).dispose || Symbol.for(\"Symbol.dispose\");\n\ninterface Effect {\n\t_sources: object | undefined;\n\t_start(): () => void;\n\t_callback(): void;\n\t_dispose(): void;\n}\n\n/**\n * Use this flag to represent a bare `useSignals` call that doesn't manually\n * close its effect store and relies on auto-closing when the next useSignals is\n * called or after a microtask\n */\nconst UNMANAGED = 0;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a component's render method. This is the default usage\n * that the react-transform plugin uses.\n */\nconst MANAGED_COMPONENT = 1;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a hook body. This is the default usage that the\n * react-transform plugin uses.\n */\nconst MANAGED_HOOK = 2;\n\n/**\n * An enum defining how this store is used. See the documentation for each enum\n * member for more details.\n * @see {@link UNMANAGED}\n * @see {@link MANAGED_COMPONENT}\n * @see {@link MANAGED_HOOK}\n */\ntype EffectStoreUsage =\n\t| typeof UNMANAGED\n\t| typeof MANAGED_COMPONENT\n\t| typeof MANAGED_HOOK;\n\nexport interface EffectStore {\n\t/**\n\t * An enum defining how this hook is used and whether it is invoked in a\n\t * component's body or hook body. See the comment on `EffectStoreUsage` for\n\t * more details.\n\t */\n\treadonly _usage: EffectStoreUsage;\n\treadonly effect: Effect;\n\tsubscribe(onStoreChange: () => void): () => void;\n\tgetSnapshot(): number;\n\t/** startEffect - begin tracking signals used in this component */\n\t_start(): void;\n\t/** finishEffect - stop tracking the signals used in this component */\n\tf(): void;\n\t[symDispose](): void;\n}\n\nlet currentStore: EffectStore | undefined;\n\nfunction startComponentEffect(\n\tprevStore: EffectStore | undefined,\n\tnextStore: EffectStore\n) {\n\tconst endEffect = nextStore.effect._start();\n\tcurrentStore = nextStore;\n\n\treturn finishComponentEffect.bind(nextStore, prevStore, endEffect);\n}\n\nfunction finishComponentEffect(\n\tthis: EffectStore,\n\tprevStore: EffectStore | undefined,\n\tendEffect: () => void\n) {\n\tendEffect();\n\tcurrentStore = prevStore;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a\n * 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the\n * component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the\n * `effect._callback' is called, we update our store version and tell React to\n * re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://react.dev/reference/react/useSyncExternalStore\n * @see\n * https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n *\n * @param _usage An enum defining how this hook is used and whether it is\n * invoked in a component's body or hook body. See the comment on\n * `EffectStoreUsage` for more details.\n */\nfunction createEffectStore(_usage: EffectStoreUsage): EffectStore {\n\tlet effectInstance!: Effect;\n\tlet endEffect: (() => void) | undefined;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\teffectInstance = this;\n\t});\n\teffectInstance._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\t_usage,\n\t\teffect: effectInstance,\n\t\tsubscribe(onStoreChange) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t\t_start() {\n\t\t\t// In general, we want to support two kinds of usages of useSignals:\n\t\t\t//\n\t\t\t// A) Managed: calling useSignals in a component or hook body wrapped in a\n\t\t\t// try/finally (like what the react-transform plugin does)\n\t\t\t//\n\t\t\t// B) Unmanaged: Calling useSignals directly without wrapping in a\n\t\t\t// try/finally\n\t\t\t//\n\t\t\t// For managed, we finish the effect in the finally block of the component\n\t\t\t// or hook body. For unmanaged, we finish the effect in the next\n\t\t\t// useSignals call or after a microtask.\n\t\t\t//\n\t\t\t// There are different tradeoffs which each approach. With managed, using\n\t\t\t// a try/finally ensures that only signals used in the component or hook\n\t\t\t// body are tracked. However, signals accessed in render props are missed\n\t\t\t// because the render prop is invoked in another component that may or may\n\t\t\t// not realize it is rendering signals accessed in the render prop it is\n\t\t\t// given.\n\t\t\t//\n\t\t\t// The other approach is \"unmanaged\": to call useSignals directly without\n\t\t\t// wrapping in a try/finally. This approach is easier to manually write in\n\t\t\t// situations where a build step isn't available but does open up the\n\t\t\t// possibility of catching signals accessed in other code before the\n\t\t\t// effect is closed (e.g. in a layout effect). Most situations where this\n\t\t\t// could happen are generally consider bad patterns or bugs. For example,\n\t\t\t// using a signal in a component and not having a call to `useSignals`\n\t\t\t// would be an bug. Or using a signal in `useLayoutEffect` is generally\n\t\t\t// not recommended since that layout effect won't update when the signals'\n\t\t\t// value change.\n\t\t\t//\n\t\t\t// To support both approaches, we need to track how each invocation of\n\t\t\t// useSignals is used, so we can properly transition between different\n\t\t\t// kinds of usages.\n\t\t\t//\n\t\t\t// The following table shows the different scenarios and how we should\n\t\t\t// handle them.\n\t\t\t//\n\t\t\t// Key:\n\t\t\t// 0 = UNMANAGED\n\t\t\t// 1 = MANAGED_COMPONENT\n\t\t\t// 2 = MANAGED_HOOK\n\t\t\t//\n\t\t\t// Pattern:\n\t\t\t// prev store usage -> this store usage: action to take\n\t\t\t//\n\t\t\t// - 0 -> 0: finish previous effect (unknown to unknown)\n\t\t\t//\n\t\t\t// We don't know how the previous effect was used, so we need to finish\n\t\t\t// it before starting the next effect.\n\t\t\t//\n\t\t\t// - 0 -> 1: finish previous effect\n\t\t\t//\n\t\t\t// Assume previous invocation was another component or hook from another\n\t\t\t// component. Nested component renders (renderToStaticMarkup within a\n\t\t\t// component's render) won't be supported with bare useSignals calls.\n\t\t\t//\n\t\t\t// - 0 -> 2: capture & restore\n\t\t\t//\n\t\t\t// Previous invocation could be a component or a hook. Either way,\n\t\t\t// restore it after our invocation so that it can continue to capture\n\t\t\t// any signals after we exit.\n\t\t\t//\n\t\t\t// - 1 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 1 -> 1: capture & restore (e.g. component calls renderToStaticMarkup)\n\t\t\t// - 1 -> 2: capture & restore (e.g. hook)\n\t\t\t//\n\t\t\t// - 2 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 2 -> 1: capture & restore (e.g. hook calls renderToStaticMarkup)\n\t\t\t// - 2 -> 2: capture & restore (e.g. nested hook calls)\n\n\t\t\tif (currentStore == undefined) {\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst prevUsage = currentStore._usage;\n\t\t\tconst thisUsage = this._usage;\n\n\t\t\tif (\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == UNMANAGED) || // 0 -> 0\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == MANAGED_COMPONENT) // 0 -> 1\n\t\t\t) {\n\t\t\t\t// finish previous effect\n\t\t\t\tcurrentStore.f();\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t} else if (\n\t\t\t\t(prevUsage == MANAGED_COMPONENT && thisUsage == UNMANAGED) || // 1 -> 0\n\t\t\t\t(prevUsage == MANAGED_HOOK && thisUsage == UNMANAGED) // 2 -> 0\n\t\t\t) {\n\t\t\t\t// Do nothing since it'll be captured by current effect store\n\t\t\t} else {\n\t\t\t\t// nested scenarios, so capture and restore the previous effect store\n\t\t\t\tendEffect = startComponentEffect(currentStore, this);\n\t\t\t}\n\t\t},\n\t\tf() {\n\t\t\tconst end = endEffect;\n\t\t\tendEffect = undefined;\n\t\t\tend?.();\n\t\t},\n\t\t[symDispose]() {\n\t\t\tthis.f();\n\t\t},\n\t};\n}\n\nconst noop = () => {};\n\nfunction createEmptyEffectStore(): EffectStore {\n\treturn {\n\t\t_usage: UNMANAGED,\n\t\teffect: {\n\t\t\t_sources: undefined,\n\t\t\t_callback() {},\n\t\t\t_start() {\n\t\t\t\treturn /* endEffect */ noop;\n\t\t\t},\n\t\t\t_dispose() {},\n\t\t},\n\t\tsubscribe() {\n\t\t\treturn /* unsubscribe */ noop;\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn 0;\n\t\t},\n\t\t_start() {},\n\t\tf() {},\n\t\t[symDispose]() {},\n\t};\n}\n\nconst emptyEffectStore = createEmptyEffectStore();\n\nconst _queueMicroTask = Promise.prototype.then.bind(Promise.resolve());\n\nlet finalCleanup: Promise<void> | undefined;\nexport function ensureFinalCleanup() {\n\tif (!finalCleanup) {\n\t\tfinalCleanup = _queueMicroTask(cleanupTrailingStore);\n\t}\n}\nfunction cleanupTrailingStore() {\n\tfinalCleanup = undefined;\n\tcurrentStore?.f();\n}\n\nconst useIsomorphicLayoutEffect =\n\ttypeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\n/**\n * Custom hook to create the effect to track signals used during render and\n * subscribe to changes to rerender the component when the signals change.\n */\nexport function _useSignalsImplementation(\n\t_usage: EffectStoreUsage = UNMANAGED\n): EffectStore {\n\tensureFinalCleanup();\n\n\tconst storeRef = useRef<EffectStore>();\n\tif (storeRef.current == null) {\n\t\tif (typeof window === \"undefined\") {\n\t\t\tstoreRef.current = emptyEffectStore;\n\t\t} else {\n\t\t\tstoreRef.current = createEffectStore(_usage);\n\t\t}\n\t}\n\n\tconst store = storeRef.current;\n\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\tstore._start();\n\t// note: _usage is a constant here, so conditional is okay\n\tif (_usage === UNMANAGED) useIsomorphicLayoutEffect(cleanupTrailingStore);\n\n\treturn store;\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node or JSX.\n */\nfunction SignalValue({ data }: { data: Signal }) {\n\tconst store = _useSignalsImplementation(1);\n\ttry {\n\t\treturn data.value;\n\t} finally {\n\t\tstore.f();\n\t}\n}\n\n// Decorate Signals so React renders them as <SignalValue> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: SignalValue },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignals(usage?: EffectStoreUsage): EffectStore {\n\treturn _useSignalsImplementation(usage);\n}\n\nexport function useSignal<T>(value: T, options?: SignalOptions<T>): Signal<T>;\nexport function useSignal<T = undefined>(): Signal<T | undefined>;\nexport function useSignal<T>(value?: T, options?: SignalOptions<T>) {\n\treturn useMemo(\n\t\t() => signal<T | undefined>(value, options as SignalOptions),\n\t\tEmpty\n\t);\n}\n\nexport function useComputed<T>(\n\tcompute: () => T,\n\toptions?: SignalOptions<T>\n): ReadonlySignal<T> {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current(), options), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(function (this: Effect) {\n\t\t\treturn callback.current();\n\t\t});\n\t}, Empty);\n}\n"],"names":["currentStore","major","reactVersion","split","map","Number","Empty","ReactElemType","Symbol","symDispose","dispose","startComponentEffect","prevStore","nextStore","endEffect","effect","_start","finishComponentEffect","bind","_ref2","finalCleanup","noop","emptyEffectStore","_usage","_sources","undefined","_callback","_dispose","subscribe","getSnapshot","f","_queueMicroTask","Promise","prototype","then","resolve","ensureFinalCleanup","cleanupTrailingStore","_currentStore","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","_useSignalsImplementation","storeRef","useRef","current","_ref","effectInstance","onChangeNotifyReact","version","unsubscribe","this","onStoreChange","prevUsage","thisUsage","end","createEffectStore","store","useSyncExternalStore","Object","defineProperties","Signal","$$typeof","configurable","value","type","_ref3","data","props","get","ref","exports","useComputed","compute","options","$compute","useMemo","computed","useSignal","signal","useSignalEffect","cb","callback","useSignals","usage","wrapJsx","jsx","i","v","call","apply","concat","slice","arguments"],"mappings":"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"}
|
package/runtime/dist/runtime.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Signal as t,signal as n,computed as e,effect as o}from"@preact/signals-core";import{version as i,useRef as r,useMemo as f,useEffect as s,useLayoutEffect as u}from"react";import{useSyncExternalStore as c}from"use-sync-external-store/shim/index.js";const[l]=i.split(".").map(Number),a=[],d=Symbol.for(l>=19?"react.transitional.element":"react.element");function p(n){if("function"!=typeof n)return n;else return function(e,o,...i){if("string"==typeof e&&o)for(let n in o){let e=o[n];if("children"!==n&&e instanceof t)o[n]=e.value}return n.call(n,e,o,...i)}}const m=Symbol.dispose||Symbol.for("Symbol.dispose");let b;function y(t,n){const e=n.effect.S();b=n;return g.bind(n,t,e)}function g(t,n){n();b=t}const h=()=>{},v={o:0,effect:{s:void 0,c(){},S:()=>h,d(){}},subscribe:()=>h,getSnapshot:()=>0,S(){},f(){},[m](){}},_=Promise.prototype.then.bind(Promise.resolve());let S;function w(){if(!S)S=_(x)}function x(){var t;S=void 0;null==(t=b)||t.f()}const j="undefined"!=typeof window?u:s;function P(t=0){w();const n=r();if(null==n.current)if("undefined"==typeof window)n.current=v;else n.current=function(t){let n,e,i,r=0,f=o(function(){n=this});n.c=function(){r=r+1|0;if(i)i()};return{o:t,effect:n,subscribe(t){i=t;return function(){r=r+1|0;i=void 0;f()}},getSnapshot:()=>r,S(){if(null==b){e=y(void 0,this);return}const t=b.o,n=this.o;if(0==t&&0==n||0==t&&1==n){b.f();e=y(void 0,this)}else if(1==t&&0==n||2==t&&0==n);else e=y(b,this)},f(){const t=e;e=void 0;null==t||t()},[m](){this.f()}}}(t);const e=n.current;c(e.subscribe,e.getSnapshot,e.getSnapshot);e.S();if(0===t)j(x);return e}Object.defineProperties(t.prototype,{$$typeof:{configurable:!0,value:d},type:{configurable:!0,value:function({data:t}){const n=P(1);try{return t.value}finally{n.f()}}},props:{configurable:!0,get(){return{data:this}}},ref:{configurable:!0,value:null}});function $(t){return P(t)}function useSignal(t){return f(()=>n(t),a)}function useComputed(t){const
|
|
1
|
+
import{Signal as t,signal as n,computed as e,effect as o}from"@preact/signals-core";import{version as i,useRef as r,useMemo as f,useEffect as s,useLayoutEffect as u}from"react";import{useSyncExternalStore as c}from"use-sync-external-store/shim/index.js";const[l]=i.split(".").map(Number),a=[],d=Symbol.for(l>=19?"react.transitional.element":"react.element");function p(n){if("function"!=typeof n)return n;else return function(e,o,...i){if("string"==typeof e&&o)for(let n in o){let e=o[n];if("children"!==n&&e instanceof t)o[n]=e.value}return n.call(n,e,o,...i)}}const m=Symbol.dispose||Symbol.for("Symbol.dispose");let b;function y(t,n){const e=n.effect.S();b=n;return g.bind(n,t,e)}function g(t,n){n();b=t}const h=()=>{},v={o:0,effect:{s:void 0,c(){},S:()=>h,d(){}},subscribe:()=>h,getSnapshot:()=>0,S(){},f(){},[m](){}},_=Promise.prototype.then.bind(Promise.resolve());let S;function w(){if(!S)S=_(x)}function x(){var t;S=void 0;null==(t=b)||t.f()}const j="undefined"!=typeof window?u:s;function P(t=0){w();const n=r();if(null==n.current)if("undefined"==typeof window)n.current=v;else n.current=function(t){let n,e,i,r=0,f=o(function(){n=this});n.c=function(){r=r+1|0;if(i)i()};return{o:t,effect:n,subscribe(t){i=t;return function(){r=r+1|0;i=void 0;f()}},getSnapshot:()=>r,S(){if(null==b){e=y(void 0,this);return}const t=b.o,n=this.o;if(0==t&&0==n||0==t&&1==n){b.f();e=y(void 0,this)}else if(1==t&&0==n||2==t&&0==n);else e=y(b,this)},f(){const t=e;e=void 0;null==t||t()},[m](){this.f()}}}(t);const e=n.current;c(e.subscribe,e.getSnapshot,e.getSnapshot);e.S();if(0===t)j(x);return e}Object.defineProperties(t.prototype,{$$typeof:{configurable:!0,value:d},type:{configurable:!0,value:function({data:t}){const n=P(1);try{return t.value}finally{n.f()}}},props:{configurable:!0,get(){return{data:this}}},ref:{configurable:!0,value:null}});function $(t){return P(t)}function useSignal(t,e){return f(()=>n(t,e),a)}function useComputed(t,n){const o=r(t);o.current=t;return f(()=>e(()=>o.current(),n),a)}function useSignalEffect(t){const n=r(t);n.current=t;s(()=>o(function(){return n.current()}),a)}export{P as _useSignalsImplementation,w as ensureFinalCleanup,useComputed,useSignal,useSignalEffect,$ as useSignals,p as wrapJsx};//# sourceMappingURL=runtime.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.mjs","sources":["../src/index.ts"],"sourcesContent":["import {\n\tsignal,\n\tcomputed,\n\teffect,\n\tSignal,\n\tReadonlySignal,\n} from \"@preact/signals-core\";\nimport {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tuseLayoutEffect,\n\tversion as reactVersion,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nconst [major] = reactVersion.split(\".\").map(Number);\nconst Empty = [] as const;\n// V19 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\n// V18 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactElemType = Symbol.for(\n\tmajor >= 19 ? \"react.transitional.element\" : \"react.element\"\n);\n\nexport function wrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst symDispose: unique symbol =\n\t(Symbol as any).dispose || Symbol.for(\"Symbol.dispose\");\n\ninterface Effect {\n\t_sources: object | undefined;\n\t_start(): () => void;\n\t_callback(): void;\n\t_dispose(): void;\n}\n\n/**\n * Use this flag to represent a bare `useSignals` call that doesn't manually\n * close its effect store and relies on auto-closing when the next useSignals is\n * called or after a microtask\n */\nconst UNMANAGED = 0;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a component's render method. This is the default usage\n * that the react-transform plugin uses.\n */\nconst MANAGED_COMPONENT = 1;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a hook body. This is the default usage that the\n * react-transform plugin uses.\n */\nconst MANAGED_HOOK = 2;\n\n/**\n * An enum defining how this store is used. See the documentation for each enum\n * member for more details.\n * @see {@link UNMANAGED}\n * @see {@link MANAGED_COMPONENT}\n * @see {@link MANAGED_HOOK}\n */\ntype EffectStoreUsage =\n\t| typeof UNMANAGED\n\t| typeof MANAGED_COMPONENT\n\t| typeof MANAGED_HOOK;\n\nexport interface EffectStore {\n\t/**\n\t * An enum defining how this hook is used and whether it is invoked in a\n\t * component's body or hook body. See the comment on `EffectStoreUsage` for\n\t * more details.\n\t */\n\treadonly _usage: EffectStoreUsage;\n\treadonly effect: Effect;\n\tsubscribe(onStoreChange: () => void): () => void;\n\tgetSnapshot(): number;\n\t/** startEffect - begin tracking signals used in this component */\n\t_start(): void;\n\t/** finishEffect - stop tracking the signals used in this component */\n\tf(): void;\n\t[symDispose](): void;\n}\n\nlet currentStore: EffectStore | undefined;\n\nfunction startComponentEffect(\n\tprevStore: EffectStore | undefined,\n\tnextStore: EffectStore\n) {\n\tconst endEffect = nextStore.effect._start();\n\tcurrentStore = nextStore;\n\n\treturn finishComponentEffect.bind(nextStore, prevStore, endEffect);\n}\n\nfunction finishComponentEffect(\n\tthis: EffectStore,\n\tprevStore: EffectStore | undefined,\n\tendEffect: () => void\n) {\n\tendEffect();\n\tcurrentStore = prevStore;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a\n * 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the\n * component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the\n * `effect._callback' is called, we update our store version and tell React to\n * re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://react.dev/reference/react/useSyncExternalStore\n * @see\n * https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n *\n * @param _usage An enum defining how this hook is used and whether it is\n * invoked in a component's body or hook body. See the comment on\n * `EffectStoreUsage` for more details.\n */\nfunction createEffectStore(_usage: EffectStoreUsage): EffectStore {\n\tlet effectInstance!: Effect;\n\tlet endEffect: (() => void) | undefined;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\teffectInstance = this;\n\t});\n\teffectInstance._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\t_usage,\n\t\teffect: effectInstance,\n\t\tsubscribe(onStoreChange) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t\t_start() {\n\t\t\t// In general, we want to support two kinds of usages of useSignals:\n\t\t\t//\n\t\t\t// A) Managed: calling useSignals in a component or hook body wrapped in a\n\t\t\t// try/finally (like what the react-transform plugin does)\n\t\t\t//\n\t\t\t// B) Unmanaged: Calling useSignals directly without wrapping in a\n\t\t\t// try/finally\n\t\t\t//\n\t\t\t// For managed, we finish the effect in the finally block of the component\n\t\t\t// or hook body. For unmanaged, we finish the effect in the next\n\t\t\t// useSignals call or after a microtask.\n\t\t\t//\n\t\t\t// There are different tradeoffs which each approach. With managed, using\n\t\t\t// a try/finally ensures that only signals used in the component or hook\n\t\t\t// body are tracked. However, signals accessed in render props are missed\n\t\t\t// because the render prop is invoked in another component that may or may\n\t\t\t// not realize it is rendering signals accessed in the render prop it is\n\t\t\t// given.\n\t\t\t//\n\t\t\t// The other approach is \"unmanaged\": to call useSignals directly without\n\t\t\t// wrapping in a try/finally. This approach is easier to manually write in\n\t\t\t// situations where a build step isn't available but does open up the\n\t\t\t// possibility of catching signals accessed in other code before the\n\t\t\t// effect is closed (e.g. in a layout effect). Most situations where this\n\t\t\t// could happen are generally consider bad patterns or bugs. For example,\n\t\t\t// using a signal in a component and not having a call to `useSignals`\n\t\t\t// would be an bug. Or using a signal in `useLayoutEffect` is generally\n\t\t\t// not recommended since that layout effect won't update when the signals'\n\t\t\t// value change.\n\t\t\t//\n\t\t\t// To support both approaches, we need to track how each invocation of\n\t\t\t// useSignals is used, so we can properly transition between different\n\t\t\t// kinds of usages.\n\t\t\t//\n\t\t\t// The following table shows the different scenarios and how we should\n\t\t\t// handle them.\n\t\t\t//\n\t\t\t// Key:\n\t\t\t// 0 = UNMANAGED\n\t\t\t// 1 = MANAGED_COMPONENT\n\t\t\t// 2 = MANAGED_HOOK\n\t\t\t//\n\t\t\t// Pattern:\n\t\t\t// prev store usage -> this store usage: action to take\n\t\t\t//\n\t\t\t// - 0 -> 0: finish previous effect (unknown to unknown)\n\t\t\t//\n\t\t\t// We don't know how the previous effect was used, so we need to finish\n\t\t\t// it before starting the next effect.\n\t\t\t//\n\t\t\t// - 0 -> 1: finish previous effect\n\t\t\t//\n\t\t\t// Assume previous invocation was another component or hook from another\n\t\t\t// component. Nested component renders (renderToStaticMarkup within a\n\t\t\t// component's render) won't be supported with bare useSignals calls.\n\t\t\t//\n\t\t\t// - 0 -> 2: capture & restore\n\t\t\t//\n\t\t\t// Previous invocation could be a component or a hook. Either way,\n\t\t\t// restore it after our invocation so that it can continue to capture\n\t\t\t// any signals after we exit.\n\t\t\t//\n\t\t\t// - 1 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 1 -> 1: capture & restore (e.g. component calls renderToStaticMarkup)\n\t\t\t// - 1 -> 2: capture & restore (e.g. hook)\n\t\t\t//\n\t\t\t// - 2 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 2 -> 1: capture & restore (e.g. hook calls renderToStaticMarkup)\n\t\t\t// - 2 -> 2: capture & restore (e.g. nested hook calls)\n\n\t\t\tif (currentStore == undefined) {\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst prevUsage = currentStore._usage;\n\t\t\tconst thisUsage = this._usage;\n\n\t\t\tif (\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == UNMANAGED) || // 0 -> 0\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == MANAGED_COMPONENT) // 0 -> 1\n\t\t\t) {\n\t\t\t\t// finish previous effect\n\t\t\t\tcurrentStore.f();\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t} else if (\n\t\t\t\t(prevUsage == MANAGED_COMPONENT && thisUsage == UNMANAGED) || // 1 -> 0\n\t\t\t\t(prevUsage == MANAGED_HOOK && thisUsage == UNMANAGED) // 2 -> 0\n\t\t\t) {\n\t\t\t\t// Do nothing since it'll be captured by current effect store\n\t\t\t} else {\n\t\t\t\t// nested scenarios, so capture and restore the previous effect store\n\t\t\t\tendEffect = startComponentEffect(currentStore, this);\n\t\t\t}\n\t\t},\n\t\tf() {\n\t\t\tconst end = endEffect;\n\t\t\tendEffect = undefined;\n\t\t\tend?.();\n\t\t},\n\t\t[symDispose]() {\n\t\t\tthis.f();\n\t\t},\n\t};\n}\n\nconst noop = () => {};\n\nfunction createEmptyEffectStore(): EffectStore {\n\treturn {\n\t\t_usage: UNMANAGED,\n\t\teffect: {\n\t\t\t_sources: undefined,\n\t\t\t_callback() {},\n\t\t\t_start() {\n\t\t\t\treturn /* endEffect */ noop;\n\t\t\t},\n\t\t\t_dispose() {},\n\t\t},\n\t\tsubscribe() {\n\t\t\treturn /* unsubscribe */ noop;\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn 0;\n\t\t},\n\t\t_start() {},\n\t\tf() {},\n\t\t[symDispose]() {},\n\t};\n}\n\nconst emptyEffectStore = createEmptyEffectStore();\n\nconst _queueMicroTask = Promise.prototype.then.bind(Promise.resolve());\n\nlet finalCleanup: Promise<void> | undefined;\nexport function ensureFinalCleanup() {\n\tif (!finalCleanup) {\n\t\tfinalCleanup = _queueMicroTask(cleanupTrailingStore);\n\t}\n}\nfunction cleanupTrailingStore() {\n\tfinalCleanup = undefined;\n\tcurrentStore?.f();\n}\n\nconst useIsomorphicLayoutEffect =\n\ttypeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\n/**\n * Custom hook to create the effect to track signals used during render and\n * subscribe to changes to rerender the component when the signals change.\n */\nexport function _useSignalsImplementation(\n\t_usage: EffectStoreUsage = UNMANAGED\n): EffectStore {\n\tensureFinalCleanup();\n\n\tconst storeRef = useRef<EffectStore>();\n\tif (storeRef.current == null) {\n\t\tif (typeof window === \"undefined\") {\n\t\t\tstoreRef.current = emptyEffectStore;\n\t\t} else {\n\t\t\tstoreRef.current = createEffectStore(_usage);\n\t\t}\n\t}\n\n\tconst store = storeRef.current;\n\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\tstore._start();\n\t// note: _usage is a constant here, so conditional is okay\n\tif (_usage === UNMANAGED) useIsomorphicLayoutEffect(cleanupTrailingStore);\n\n\treturn store;\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node or JSX.\n */\nfunction SignalValue({ data }: { data: Signal }) {\n\tconst store = _useSignalsImplementation(1);\n\ttry {\n\t\treturn data.value;\n\t} finally {\n\t\tstore.f();\n\t}\n}\n\n// Decorate Signals so React renders them as <SignalValue> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: SignalValue },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignals(usage?: EffectStoreUsage): EffectStore {\n\treturn _useSignalsImplementation(usage);\n}\n\nexport function useSignal<T>(value: T): Signal<T>;\nexport function useSignal<T = undefined>(): Signal<T | undefined>;\nexport function useSignal<T>(value?: T) {\n\treturn useMemo(() => signal<T | undefined>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => T): ReadonlySignal<T> {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(function (this: Effect) {\n\t\t\treturn callback.current();\n\t\t});\n\t}, Empty);\n}\n"],"names":["major","reactVersion","split","map","Number","Empty","ReactElemType","Symbol","for","wrapJsx","jsx","type","props","rest","i","v","Signal","value","call","symDispose","dispose","currentStore","startComponentEffect","prevStore","nextStore","endEffect","effect","_start","finishComponentEffect","bind","noop","emptyEffectStore","_usage","_sources","undefined","_callback","_dispose","subscribe","getSnapshot","f","_queueMicroTask","Promise","prototype","then","resolve","finalCleanup","ensureFinalCleanup","cleanupTrailingStore","_currentStore","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","_useSignalsImplementation","storeRef","useRef","current","effectInstance","onChangeNotifyReact","version","unsubscribe","this","onStoreChange","prevUsage","thisUsage","end","createEffectStore","store","useSyncExternalStore","Object","defineProperties","$$typeof","configurable","data","get","ref","useSignals","usage","useSignal","useMemo","signal","useComputed","compute","$compute","computed","useSignalEffect","cb","callback"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.mjs","sources":["../src/index.ts"],"sourcesContent":["import {\n\tsignal,\n\tcomputed,\n\teffect,\n\tSignal,\n\tReadonlySignal,\n\tSignalOptions,\n} from \"@preact/signals-core\";\nimport {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tuseLayoutEffect,\n\tversion as reactVersion,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nconst [major] = reactVersion.split(\".\").map(Number);\nconst Empty = [] as const;\n// V19 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\n// V18 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactElemType = Symbol.for(\n\tmajor >= 19 ? \"react.transitional.element\" : \"react.element\"\n);\n\nexport function wrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst symDispose: unique symbol =\n\t(Symbol as any).dispose || Symbol.for(\"Symbol.dispose\");\n\ninterface Effect {\n\t_sources: object | undefined;\n\t_start(): () => void;\n\t_callback(): void;\n\t_dispose(): void;\n}\n\n/**\n * Use this flag to represent a bare `useSignals` call that doesn't manually\n * close its effect store and relies on auto-closing when the next useSignals is\n * called or after a microtask\n */\nconst UNMANAGED = 0;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a component's render method. This is the default usage\n * that the react-transform plugin uses.\n */\nconst MANAGED_COMPONENT = 1;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a hook body. This is the default usage that the\n * react-transform plugin uses.\n */\nconst MANAGED_HOOK = 2;\n\n/**\n * An enum defining how this store is used. See the documentation for each enum\n * member for more details.\n * @see {@link UNMANAGED}\n * @see {@link MANAGED_COMPONENT}\n * @see {@link MANAGED_HOOK}\n */\ntype EffectStoreUsage =\n\t| typeof UNMANAGED\n\t| typeof MANAGED_COMPONENT\n\t| typeof MANAGED_HOOK;\n\nexport interface EffectStore {\n\t/**\n\t * An enum defining how this hook is used and whether it is invoked in a\n\t * component's body or hook body. See the comment on `EffectStoreUsage` for\n\t * more details.\n\t */\n\treadonly _usage: EffectStoreUsage;\n\treadonly effect: Effect;\n\tsubscribe(onStoreChange: () => void): () => void;\n\tgetSnapshot(): number;\n\t/** startEffect - begin tracking signals used in this component */\n\t_start(): void;\n\t/** finishEffect - stop tracking the signals used in this component */\n\tf(): void;\n\t[symDispose](): void;\n}\n\nlet currentStore: EffectStore | undefined;\n\nfunction startComponentEffect(\n\tprevStore: EffectStore | undefined,\n\tnextStore: EffectStore\n) {\n\tconst endEffect = nextStore.effect._start();\n\tcurrentStore = nextStore;\n\n\treturn finishComponentEffect.bind(nextStore, prevStore, endEffect);\n}\n\nfunction finishComponentEffect(\n\tthis: EffectStore,\n\tprevStore: EffectStore | undefined,\n\tendEffect: () => void\n) {\n\tendEffect();\n\tcurrentStore = prevStore;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a\n * 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the\n * component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the\n * `effect._callback' is called, we update our store version and tell React to\n * re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://react.dev/reference/react/useSyncExternalStore\n * @see\n * https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n *\n * @param _usage An enum defining how this hook is used and whether it is\n * invoked in a component's body or hook body. See the comment on\n * `EffectStoreUsage` for more details.\n */\nfunction createEffectStore(_usage: EffectStoreUsage): EffectStore {\n\tlet effectInstance!: Effect;\n\tlet endEffect: (() => void) | undefined;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\teffectInstance = this;\n\t});\n\teffectInstance._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\t_usage,\n\t\teffect: effectInstance,\n\t\tsubscribe(onStoreChange) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t\t_start() {\n\t\t\t// In general, we want to support two kinds of usages of useSignals:\n\t\t\t//\n\t\t\t// A) Managed: calling useSignals in a component or hook body wrapped in a\n\t\t\t// try/finally (like what the react-transform plugin does)\n\t\t\t//\n\t\t\t// B) Unmanaged: Calling useSignals directly without wrapping in a\n\t\t\t// try/finally\n\t\t\t//\n\t\t\t// For managed, we finish the effect in the finally block of the component\n\t\t\t// or hook body. For unmanaged, we finish the effect in the next\n\t\t\t// useSignals call or after a microtask.\n\t\t\t//\n\t\t\t// There are different tradeoffs which each approach. With managed, using\n\t\t\t// a try/finally ensures that only signals used in the component or hook\n\t\t\t// body are tracked. However, signals accessed in render props are missed\n\t\t\t// because the render prop is invoked in another component that may or may\n\t\t\t// not realize it is rendering signals accessed in the render prop it is\n\t\t\t// given.\n\t\t\t//\n\t\t\t// The other approach is \"unmanaged\": to call useSignals directly without\n\t\t\t// wrapping in a try/finally. This approach is easier to manually write in\n\t\t\t// situations where a build step isn't available but does open up the\n\t\t\t// possibility of catching signals accessed in other code before the\n\t\t\t// effect is closed (e.g. in a layout effect). Most situations where this\n\t\t\t// could happen are generally consider bad patterns or bugs. For example,\n\t\t\t// using a signal in a component and not having a call to `useSignals`\n\t\t\t// would be an bug. Or using a signal in `useLayoutEffect` is generally\n\t\t\t// not recommended since that layout effect won't update when the signals'\n\t\t\t// value change.\n\t\t\t//\n\t\t\t// To support both approaches, we need to track how each invocation of\n\t\t\t// useSignals is used, so we can properly transition between different\n\t\t\t// kinds of usages.\n\t\t\t//\n\t\t\t// The following table shows the different scenarios and how we should\n\t\t\t// handle them.\n\t\t\t//\n\t\t\t// Key:\n\t\t\t// 0 = UNMANAGED\n\t\t\t// 1 = MANAGED_COMPONENT\n\t\t\t// 2 = MANAGED_HOOK\n\t\t\t//\n\t\t\t// Pattern:\n\t\t\t// prev store usage -> this store usage: action to take\n\t\t\t//\n\t\t\t// - 0 -> 0: finish previous effect (unknown to unknown)\n\t\t\t//\n\t\t\t// We don't know how the previous effect was used, so we need to finish\n\t\t\t// it before starting the next effect.\n\t\t\t//\n\t\t\t// - 0 -> 1: finish previous effect\n\t\t\t//\n\t\t\t// Assume previous invocation was another component or hook from another\n\t\t\t// component. Nested component renders (renderToStaticMarkup within a\n\t\t\t// component's render) won't be supported with bare useSignals calls.\n\t\t\t//\n\t\t\t// - 0 -> 2: capture & restore\n\t\t\t//\n\t\t\t// Previous invocation could be a component or a hook. Either way,\n\t\t\t// restore it after our invocation so that it can continue to capture\n\t\t\t// any signals after we exit.\n\t\t\t//\n\t\t\t// - 1 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 1 -> 1: capture & restore (e.g. component calls renderToStaticMarkup)\n\t\t\t// - 1 -> 2: capture & restore (e.g. hook)\n\t\t\t//\n\t\t\t// - 2 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 2 -> 1: capture & restore (e.g. hook calls renderToStaticMarkup)\n\t\t\t// - 2 -> 2: capture & restore (e.g. nested hook calls)\n\n\t\t\tif (currentStore == undefined) {\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst prevUsage = currentStore._usage;\n\t\t\tconst thisUsage = this._usage;\n\n\t\t\tif (\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == UNMANAGED) || // 0 -> 0\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == MANAGED_COMPONENT) // 0 -> 1\n\t\t\t) {\n\t\t\t\t// finish previous effect\n\t\t\t\tcurrentStore.f();\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t} else if (\n\t\t\t\t(prevUsage == MANAGED_COMPONENT && thisUsage == UNMANAGED) || // 1 -> 0\n\t\t\t\t(prevUsage == MANAGED_HOOK && thisUsage == UNMANAGED) // 2 -> 0\n\t\t\t) {\n\t\t\t\t// Do nothing since it'll be captured by current effect store\n\t\t\t} else {\n\t\t\t\t// nested scenarios, so capture and restore the previous effect store\n\t\t\t\tendEffect = startComponentEffect(currentStore, this);\n\t\t\t}\n\t\t},\n\t\tf() {\n\t\t\tconst end = endEffect;\n\t\t\tendEffect = undefined;\n\t\t\tend?.();\n\t\t},\n\t\t[symDispose]() {\n\t\t\tthis.f();\n\t\t},\n\t};\n}\n\nconst noop = () => {};\n\nfunction createEmptyEffectStore(): EffectStore {\n\treturn {\n\t\t_usage: UNMANAGED,\n\t\teffect: {\n\t\t\t_sources: undefined,\n\t\t\t_callback() {},\n\t\t\t_start() {\n\t\t\t\treturn /* endEffect */ noop;\n\t\t\t},\n\t\t\t_dispose() {},\n\t\t},\n\t\tsubscribe() {\n\t\t\treturn /* unsubscribe */ noop;\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn 0;\n\t\t},\n\t\t_start() {},\n\t\tf() {},\n\t\t[symDispose]() {},\n\t};\n}\n\nconst emptyEffectStore = createEmptyEffectStore();\n\nconst _queueMicroTask = Promise.prototype.then.bind(Promise.resolve());\n\nlet finalCleanup: Promise<void> | undefined;\nexport function ensureFinalCleanup() {\n\tif (!finalCleanup) {\n\t\tfinalCleanup = _queueMicroTask(cleanupTrailingStore);\n\t}\n}\nfunction cleanupTrailingStore() {\n\tfinalCleanup = undefined;\n\tcurrentStore?.f();\n}\n\nconst useIsomorphicLayoutEffect =\n\ttypeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\n/**\n * Custom hook to create the effect to track signals used during render and\n * subscribe to changes to rerender the component when the signals change.\n */\nexport function _useSignalsImplementation(\n\t_usage: EffectStoreUsage = UNMANAGED\n): EffectStore {\n\tensureFinalCleanup();\n\n\tconst storeRef = useRef<EffectStore>();\n\tif (storeRef.current == null) {\n\t\tif (typeof window === \"undefined\") {\n\t\t\tstoreRef.current = emptyEffectStore;\n\t\t} else {\n\t\t\tstoreRef.current = createEffectStore(_usage);\n\t\t}\n\t}\n\n\tconst store = storeRef.current;\n\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\tstore._start();\n\t// note: _usage is a constant here, so conditional is okay\n\tif (_usage === UNMANAGED) useIsomorphicLayoutEffect(cleanupTrailingStore);\n\n\treturn store;\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node or JSX.\n */\nfunction SignalValue({ data }: { data: Signal }) {\n\tconst store = _useSignalsImplementation(1);\n\ttry {\n\t\treturn data.value;\n\t} finally {\n\t\tstore.f();\n\t}\n}\n\n// Decorate Signals so React renders them as <SignalValue> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: SignalValue },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignals(usage?: EffectStoreUsage): EffectStore {\n\treturn _useSignalsImplementation(usage);\n}\n\nexport function useSignal<T>(value: T, options?: SignalOptions<T>): Signal<T>;\nexport function useSignal<T = undefined>(): Signal<T | undefined>;\nexport function useSignal<T>(value?: T, options?: SignalOptions<T>) {\n\treturn useMemo(\n\t\t() => signal<T | undefined>(value, options as SignalOptions),\n\t\tEmpty\n\t);\n}\n\nexport function useComputed<T>(\n\tcompute: () => T,\n\toptions?: SignalOptions<T>\n): ReadonlySignal<T> {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current(), options), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(function (this: Effect) {\n\t\t\treturn callback.current();\n\t\t});\n\t}, Empty);\n}\n"],"names":["major","reactVersion","split","map","Number","Empty","ReactElemType","Symbol","for","wrapJsx","jsx","type","props","rest","i","v","Signal","value","call","symDispose","dispose","currentStore","startComponentEffect","prevStore","nextStore","endEffect","effect","_start","finishComponentEffect","bind","noop","emptyEffectStore","_usage","_sources","undefined","_callback","_dispose","subscribe","getSnapshot","f","_queueMicroTask","Promise","prototype","then","resolve","finalCleanup","ensureFinalCleanup","cleanupTrailingStore","_currentStore","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","_useSignalsImplementation","storeRef","useRef","current","effectInstance","onChangeNotifyReact","version","unsubscribe","this","onStoreChange","prevUsage","thisUsage","end","createEffectStore","store","useSyncExternalStore","Object","defineProperties","$$typeof","configurable","data","get","ref","useSignals","usage","useSignal","options","useMemo","signal","useComputed","compute","$compute","computed","useSignalEffect","cb","callback"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Signal as n,signal as t,computed as r,effect as i}from"@preact/signals-core";import{version as e,useRef as o,useMemo as u,useEffect as f,useLayoutEffect as c}from"react";import{useSyncExternalStore as a}from"use-sync-external-store/shim/index.js";var s=e.split(".").map(Number)[0],l=[],v=Symbol.for(s>=19?"react.transitional.element":"react.element");function d(t){if("function"!=typeof t)return t;else return function(r,i){if("string"==typeof r&&i)for(var e in i){var o=i[e];if("children"!==e&&o instanceof n)i[e]=o.value}return t.call.apply(t,[t,r,i].concat([].slice.call(arguments,2)))}}var p,m=Symbol.dispose||Symbol.for("Symbol.dispose");function b(n,t){var r=t.effect.S();p=t;return y.bind(t,n,r)}function y(n,t){t();p=n}var g,h,_=function(){},S=((g={o:0,effect:{s:void 0,c:function(){},S:function(){return _},d:function(){}},subscribe:function(){return _},getSnapshot:function(){return 0},S:function(){},f:function(){}})[m]=function(){},g),w=Promise.prototype.then.bind(Promise.resolve());function x(){if(!h)h=w(j)}function j(){var n;h=void 0;null==(n=p)||n.f()}var P="undefined"!=typeof window?c:f;function $(n){if(void 0===n)n=0;x();var t=o();if(null==t.current)if("undefined"==typeof window)t.current=S;else t.current=function(n){var t,r,e,o,u=0,f=i(function(){r=this});r.c=function(){u=u+1|0;if(o)o()};return(t={o:n,effect:r,subscribe:function(n){o=n;return function(){u=u+1|0;o=void 0;f()}},getSnapshot:function(){return u},S:function(){if(null!=p){var n=p.o,t=this.o;if(0==n&&0==t||0==n&&1==t){p.f();e=b(void 0,this)}else if(1==n&&0==t||2==n&&0==t);else e=b(p,this)}else e=b(void 0,this)},f:function(){var n=e;e=void 0;null==n||n()}})[m]=function(){this.f()},t}(n);var r=t.current;a(r.subscribe,r.getSnapshot,r.getSnapshot);r.S();if(0===n)P(j);return r}Object.defineProperties(n.prototype,{$$typeof:{configurable:!0,value:v},type:{configurable:!0,value:function(n){var t=n.data,r=$(1);try{return t.value}finally{r.f()}}},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});function k(n){return $(n)}function useSignal(n){return u(function(){return t(n)},l)}function useComputed(n){var
|
|
1
|
+
import{Signal as n,signal as t,computed as r,effect as i}from"@preact/signals-core";import{version as e,useRef as o,useMemo as u,useEffect as f,useLayoutEffect as c}from"react";import{useSyncExternalStore as a}from"use-sync-external-store/shim/index.js";var s=e.split(".").map(Number)[0],l=[],v=Symbol.for(s>=19?"react.transitional.element":"react.element");function d(t){if("function"!=typeof t)return t;else return function(r,i){if("string"==typeof r&&i)for(var e in i){var o=i[e];if("children"!==e&&o instanceof n)i[e]=o.value}return t.call.apply(t,[t,r,i].concat([].slice.call(arguments,2)))}}var p,m=Symbol.dispose||Symbol.for("Symbol.dispose");function b(n,t){var r=t.effect.S();p=t;return y.bind(t,n,r)}function y(n,t){t();p=n}var g,h,_=function(){},S=((g={o:0,effect:{s:void 0,c:function(){},S:function(){return _},d:function(){}},subscribe:function(){return _},getSnapshot:function(){return 0},S:function(){},f:function(){}})[m]=function(){},g),w=Promise.prototype.then.bind(Promise.resolve());function x(){if(!h)h=w(j)}function j(){var n;h=void 0;null==(n=p)||n.f()}var P="undefined"!=typeof window?c:f;function $(n){if(void 0===n)n=0;x();var t=o();if(null==t.current)if("undefined"==typeof window)t.current=S;else t.current=function(n){var t,r,e,o,u=0,f=i(function(){r=this});r.c=function(){u=u+1|0;if(o)o()};return(t={o:n,effect:r,subscribe:function(n){o=n;return function(){u=u+1|0;o=void 0;f()}},getSnapshot:function(){return u},S:function(){if(null!=p){var n=p.o,t=this.o;if(0==n&&0==t||0==n&&1==t){p.f();e=b(void 0,this)}else if(1==n&&0==t||2==n&&0==t);else e=b(p,this)}else e=b(void 0,this)},f:function(){var n=e;e=void 0;null==n||n()}})[m]=function(){this.f()},t}(n);var r=t.current;a(r.subscribe,r.getSnapshot,r.getSnapshot);r.S();if(0===n)P(j);return r}Object.defineProperties(n.prototype,{$$typeof:{configurable:!0,value:v},type:{configurable:!0,value:function(n){var t=n.data,r=$(1);try{return t.value}finally{r.f()}}},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});function k(n){return $(n)}function useSignal(n,r){return u(function(){return t(n,r)},l)}function useComputed(n,t){var i=o(n);i.current=n;return u(function(){return r(function(){return i.current()},t)},l)}function useSignalEffect(n){var t=o(n);t.current=n;f(function(){return i(function(){return t.current()})},l)}export{$ as _useSignalsImplementation,x as ensureFinalCleanup,useComputed,useSignal,useSignalEffect,k as useSignals,d as wrapJsx};//# sourceMappingURL=runtime.module.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.module.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tsignal,\n\tcomputed,\n\teffect,\n\tSignal,\n\tReadonlySignal,\n} from \"@preact/signals-core\";\nimport {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tuseLayoutEffect,\n\tversion as reactVersion,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nconst [major] = reactVersion.split(\".\").map(Number);\nconst Empty = [] as const;\n// V19 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\n// V18 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactElemType = Symbol.for(\n\tmajor >= 19 ? \"react.transitional.element\" : \"react.element\"\n);\n\nexport function wrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst symDispose: unique symbol =\n\t(Symbol as any).dispose || Symbol.for(\"Symbol.dispose\");\n\ninterface Effect {\n\t_sources: object | undefined;\n\t_start(): () => void;\n\t_callback(): void;\n\t_dispose(): void;\n}\n\n/**\n * Use this flag to represent a bare `useSignals` call that doesn't manually\n * close its effect store and relies on auto-closing when the next useSignals is\n * called or after a microtask\n */\nconst UNMANAGED = 0;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a component's render method. This is the default usage\n * that the react-transform plugin uses.\n */\nconst MANAGED_COMPONENT = 1;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a hook body. This is the default usage that the\n * react-transform plugin uses.\n */\nconst MANAGED_HOOK = 2;\n\n/**\n * An enum defining how this store is used. See the documentation for each enum\n * member for more details.\n * @see {@link UNMANAGED}\n * @see {@link MANAGED_COMPONENT}\n * @see {@link MANAGED_HOOK}\n */\ntype EffectStoreUsage =\n\t| typeof UNMANAGED\n\t| typeof MANAGED_COMPONENT\n\t| typeof MANAGED_HOOK;\n\nexport interface EffectStore {\n\t/**\n\t * An enum defining how this hook is used and whether it is invoked in a\n\t * component's body or hook body. See the comment on `EffectStoreUsage` for\n\t * more details.\n\t */\n\treadonly _usage: EffectStoreUsage;\n\treadonly effect: Effect;\n\tsubscribe(onStoreChange: () => void): () => void;\n\tgetSnapshot(): number;\n\t/** startEffect - begin tracking signals used in this component */\n\t_start(): void;\n\t/** finishEffect - stop tracking the signals used in this component */\n\tf(): void;\n\t[symDispose](): void;\n}\n\nlet currentStore: EffectStore | undefined;\n\nfunction startComponentEffect(\n\tprevStore: EffectStore | undefined,\n\tnextStore: EffectStore\n) {\n\tconst endEffect = nextStore.effect._start();\n\tcurrentStore = nextStore;\n\n\treturn finishComponentEffect.bind(nextStore, prevStore, endEffect);\n}\n\nfunction finishComponentEffect(\n\tthis: EffectStore,\n\tprevStore: EffectStore | undefined,\n\tendEffect: () => void\n) {\n\tendEffect();\n\tcurrentStore = prevStore;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a\n * 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the\n * component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the\n * `effect._callback' is called, we update our store version and tell React to\n * re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://react.dev/reference/react/useSyncExternalStore\n * @see\n * https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n *\n * @param _usage An enum defining how this hook is used and whether it is\n * invoked in a component's body or hook body. See the comment on\n * `EffectStoreUsage` for more details.\n */\nfunction createEffectStore(_usage: EffectStoreUsage): EffectStore {\n\tlet effectInstance!: Effect;\n\tlet endEffect: (() => void) | undefined;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\teffectInstance = this;\n\t});\n\teffectInstance._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\t_usage,\n\t\teffect: effectInstance,\n\t\tsubscribe(onStoreChange) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t\t_start() {\n\t\t\t// In general, we want to support two kinds of usages of useSignals:\n\t\t\t//\n\t\t\t// A) Managed: calling useSignals in a component or hook body wrapped in a\n\t\t\t// try/finally (like what the react-transform plugin does)\n\t\t\t//\n\t\t\t// B) Unmanaged: Calling useSignals directly without wrapping in a\n\t\t\t// try/finally\n\t\t\t//\n\t\t\t// For managed, we finish the effect in the finally block of the component\n\t\t\t// or hook body. For unmanaged, we finish the effect in the next\n\t\t\t// useSignals call or after a microtask.\n\t\t\t//\n\t\t\t// There are different tradeoffs which each approach. With managed, using\n\t\t\t// a try/finally ensures that only signals used in the component or hook\n\t\t\t// body are tracked. However, signals accessed in render props are missed\n\t\t\t// because the render prop is invoked in another component that may or may\n\t\t\t// not realize it is rendering signals accessed in the render prop it is\n\t\t\t// given.\n\t\t\t//\n\t\t\t// The other approach is \"unmanaged\": to call useSignals directly without\n\t\t\t// wrapping in a try/finally. This approach is easier to manually write in\n\t\t\t// situations where a build step isn't available but does open up the\n\t\t\t// possibility of catching signals accessed in other code before the\n\t\t\t// effect is closed (e.g. in a layout effect). Most situations where this\n\t\t\t// could happen are generally consider bad patterns or bugs. For example,\n\t\t\t// using a signal in a component and not having a call to `useSignals`\n\t\t\t// would be an bug. Or using a signal in `useLayoutEffect` is generally\n\t\t\t// not recommended since that layout effect won't update when the signals'\n\t\t\t// value change.\n\t\t\t//\n\t\t\t// To support both approaches, we need to track how each invocation of\n\t\t\t// useSignals is used, so we can properly transition between different\n\t\t\t// kinds of usages.\n\t\t\t//\n\t\t\t// The following table shows the different scenarios and how we should\n\t\t\t// handle them.\n\t\t\t//\n\t\t\t// Key:\n\t\t\t// 0 = UNMANAGED\n\t\t\t// 1 = MANAGED_COMPONENT\n\t\t\t// 2 = MANAGED_HOOK\n\t\t\t//\n\t\t\t// Pattern:\n\t\t\t// prev store usage -> this store usage: action to take\n\t\t\t//\n\t\t\t// - 0 -> 0: finish previous effect (unknown to unknown)\n\t\t\t//\n\t\t\t// We don't know how the previous effect was used, so we need to finish\n\t\t\t// it before starting the next effect.\n\t\t\t//\n\t\t\t// - 0 -> 1: finish previous effect\n\t\t\t//\n\t\t\t// Assume previous invocation was another component or hook from another\n\t\t\t// component. Nested component renders (renderToStaticMarkup within a\n\t\t\t// component's render) won't be supported with bare useSignals calls.\n\t\t\t//\n\t\t\t// - 0 -> 2: capture & restore\n\t\t\t//\n\t\t\t// Previous invocation could be a component or a hook. Either way,\n\t\t\t// restore it after our invocation so that it can continue to capture\n\t\t\t// any signals after we exit.\n\t\t\t//\n\t\t\t// - 1 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 1 -> 1: capture & restore (e.g. component calls renderToStaticMarkup)\n\t\t\t// - 1 -> 2: capture & restore (e.g. hook)\n\t\t\t//\n\t\t\t// - 2 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 2 -> 1: capture & restore (e.g. hook calls renderToStaticMarkup)\n\t\t\t// - 2 -> 2: capture & restore (e.g. nested hook calls)\n\n\t\t\tif (currentStore == undefined) {\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst prevUsage = currentStore._usage;\n\t\t\tconst thisUsage = this._usage;\n\n\t\t\tif (\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == UNMANAGED) || // 0 -> 0\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == MANAGED_COMPONENT) // 0 -> 1\n\t\t\t) {\n\t\t\t\t// finish previous effect\n\t\t\t\tcurrentStore.f();\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t} else if (\n\t\t\t\t(prevUsage == MANAGED_COMPONENT && thisUsage == UNMANAGED) || // 1 -> 0\n\t\t\t\t(prevUsage == MANAGED_HOOK && thisUsage == UNMANAGED) // 2 -> 0\n\t\t\t) {\n\t\t\t\t// Do nothing since it'll be captured by current effect store\n\t\t\t} else {\n\t\t\t\t// nested scenarios, so capture and restore the previous effect store\n\t\t\t\tendEffect = startComponentEffect(currentStore, this);\n\t\t\t}\n\t\t},\n\t\tf() {\n\t\t\tconst end = endEffect;\n\t\t\tendEffect = undefined;\n\t\t\tend?.();\n\t\t},\n\t\t[symDispose]() {\n\t\t\tthis.f();\n\t\t},\n\t};\n}\n\nconst noop = () => {};\n\nfunction createEmptyEffectStore(): EffectStore {\n\treturn {\n\t\t_usage: UNMANAGED,\n\t\teffect: {\n\t\t\t_sources: undefined,\n\t\t\t_callback() {},\n\t\t\t_start() {\n\t\t\t\treturn /* endEffect */ noop;\n\t\t\t},\n\t\t\t_dispose() {},\n\t\t},\n\t\tsubscribe() {\n\t\t\treturn /* unsubscribe */ noop;\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn 0;\n\t\t},\n\t\t_start() {},\n\t\tf() {},\n\t\t[symDispose]() {},\n\t};\n}\n\nconst emptyEffectStore = createEmptyEffectStore();\n\nconst _queueMicroTask = Promise.prototype.then.bind(Promise.resolve());\n\nlet finalCleanup: Promise<void> | undefined;\nexport function ensureFinalCleanup() {\n\tif (!finalCleanup) {\n\t\tfinalCleanup = _queueMicroTask(cleanupTrailingStore);\n\t}\n}\nfunction cleanupTrailingStore() {\n\tfinalCleanup = undefined;\n\tcurrentStore?.f();\n}\n\nconst useIsomorphicLayoutEffect =\n\ttypeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\n/**\n * Custom hook to create the effect to track signals used during render and\n * subscribe to changes to rerender the component when the signals change.\n */\nexport function _useSignalsImplementation(\n\t_usage: EffectStoreUsage = UNMANAGED\n): EffectStore {\n\tensureFinalCleanup();\n\n\tconst storeRef = useRef<EffectStore>();\n\tif (storeRef.current == null) {\n\t\tif (typeof window === \"undefined\") {\n\t\t\tstoreRef.current = emptyEffectStore;\n\t\t} else {\n\t\t\tstoreRef.current = createEffectStore(_usage);\n\t\t}\n\t}\n\n\tconst store = storeRef.current;\n\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\tstore._start();\n\t// note: _usage is a constant here, so conditional is okay\n\tif (_usage === UNMANAGED) useIsomorphicLayoutEffect(cleanupTrailingStore);\n\n\treturn store;\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node or JSX.\n */\nfunction SignalValue({ data }: { data: Signal }) {\n\tconst store = _useSignalsImplementation(1);\n\ttry {\n\t\treturn data.value;\n\t} finally {\n\t\tstore.f();\n\t}\n}\n\n// Decorate Signals so React renders them as <SignalValue> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: SignalValue },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignals(usage?: EffectStoreUsage): EffectStore {\n\treturn _useSignalsImplementation(usage);\n}\n\nexport function useSignal<T>(value: T): Signal<T>;\nexport function useSignal<T = undefined>(): Signal<T | undefined>;\nexport function useSignal<T>(value?: T) {\n\treturn useMemo(() => signal<T | undefined>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => T): ReadonlySignal<T> {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(function (this: Effect) {\n\t\t\treturn callback.current();\n\t\t});\n\t}, Empty);\n}\n"],"names":["major","reactVersion","split","map","Number","Empty","ReactElemType","Symbol","wrapJsx","jsx","type","props","i","v","Signal","value","call","apply","concat","slice","arguments","currentStore","symDispose","dispose","startComponentEffect","prevStore","nextStore","endEffect","effect","_start","finishComponentEffect","bind","_ref2","finalCleanup","noop","emptyEffectStore","_usage","_sources","undefined","_callback","_dispose","subscribe","getSnapshot","f","_queueMicroTask","Promise","prototype","then","resolve","ensureFinalCleanup","cleanupTrailingStore","_currentStore","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","_useSignalsImplementation","storeRef","useRef","current","_ref","effectInstance","onChangeNotifyReact","version","unsubscribe","this","onStoreChange","prevUsage","thisUsage","end","createEffectStore","store","useSyncExternalStore","Object","defineProperties","$$typeof","configurable","_ref3","data","get","ref","useSignals","usage","useSignal","useMemo","signal","useComputed","compute","$compute","computed","useSignalEffect","cb","callback"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.module.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tsignal,\n\tcomputed,\n\teffect,\n\tSignal,\n\tReadonlySignal,\n\tSignalOptions,\n} from \"@preact/signals-core\";\nimport {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tuseLayoutEffect,\n\tversion as reactVersion,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nconst [major] = reactVersion.split(\".\").map(Number);\nconst Empty = [] as const;\n// V19 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\n// V18 https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactElemType = Symbol.for(\n\tmajor >= 19 ? \"react.transitional.element\" : \"react.element\"\n);\n\nexport function wrapJsx<T>(jsx: T): T {\n\tif (typeof jsx !== \"function\") return jsx;\n\n\treturn function (type: any, props: any, ...rest: any[]) {\n\t\tif (typeof type === \"string\" && props) {\n\t\t\tfor (let i in props) {\n\t\t\t\tlet v = props[i];\n\t\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t\tprops[i] = v.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsx.call(jsx, type, props, ...rest);\n\t} as any as T;\n}\n\nconst symDispose: unique symbol =\n\t(Symbol as any).dispose || Symbol.for(\"Symbol.dispose\");\n\ninterface Effect {\n\t_sources: object | undefined;\n\t_start(): () => void;\n\t_callback(): void;\n\t_dispose(): void;\n}\n\n/**\n * Use this flag to represent a bare `useSignals` call that doesn't manually\n * close its effect store and relies on auto-closing when the next useSignals is\n * called or after a microtask\n */\nconst UNMANAGED = 0;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a component's render method. This is the default usage\n * that the react-transform plugin uses.\n */\nconst MANAGED_COMPONENT = 1;\n/**\n * Use this flag to represent a `useSignals` call that is manually closed by a\n * try/finally block in a hook body. This is the default usage that the\n * react-transform plugin uses.\n */\nconst MANAGED_HOOK = 2;\n\n/**\n * An enum defining how this store is used. See the documentation for each enum\n * member for more details.\n * @see {@link UNMANAGED}\n * @see {@link MANAGED_COMPONENT}\n * @see {@link MANAGED_HOOK}\n */\ntype EffectStoreUsage =\n\t| typeof UNMANAGED\n\t| typeof MANAGED_COMPONENT\n\t| typeof MANAGED_HOOK;\n\nexport interface EffectStore {\n\t/**\n\t * An enum defining how this hook is used and whether it is invoked in a\n\t * component's body or hook body. See the comment on `EffectStoreUsage` for\n\t * more details.\n\t */\n\treadonly _usage: EffectStoreUsage;\n\treadonly effect: Effect;\n\tsubscribe(onStoreChange: () => void): () => void;\n\tgetSnapshot(): number;\n\t/** startEffect - begin tracking signals used in this component */\n\t_start(): void;\n\t/** finishEffect - stop tracking the signals used in this component */\n\tf(): void;\n\t[symDispose](): void;\n}\n\nlet currentStore: EffectStore | undefined;\n\nfunction startComponentEffect(\n\tprevStore: EffectStore | undefined,\n\tnextStore: EffectStore\n) {\n\tconst endEffect = nextStore.effect._start();\n\tcurrentStore = nextStore;\n\n\treturn finishComponentEffect.bind(nextStore, prevStore, endEffect);\n}\n\nfunction finishComponentEffect(\n\tthis: EffectStore,\n\tprevStore: EffectStore | undefined,\n\tendEffect: () => void\n) {\n\tendEffect();\n\tcurrentStore = prevStore;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a\n * 'version').\n *\n * React subscribes to this store and gets a snapshot of the current 'version',\n * whenever the 'version' changes, we tell React it's time to update the\n * component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the\n * `effect._callback' is called, we update our store version and tell React to\n * re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://react.dev/reference/react/useSyncExternalStore\n * @see\n * https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n *\n * @param _usage An enum defining how this hook is used and whether it is\n * invoked in a component's body or hook body. See the comment on\n * `EffectStoreUsage` for more details.\n */\nfunction createEffectStore(_usage: EffectStoreUsage): EffectStore {\n\tlet effectInstance!: Effect;\n\tlet endEffect: (() => void) | undefined;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\teffectInstance = this;\n\t});\n\teffectInstance._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\t_usage,\n\t\teffect: effectInstance,\n\t\tsubscribe(onStoreChange) {\n\t\t\tonChangeNotifyReact = onStoreChange;\n\n\t\t\treturn function () {\n\t\t\t\t/**\n\t\t\t\t * Rotate to next version when unsubscribing to ensure that components are re-run\n\t\t\t\t * when subscribing again.\n\t\t\t\t *\n\t\t\t\t * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so\n\t\t\t\t * don't re-run after subscribing again if the version is the same as last time.\n\t\t\t\t *\n\t\t\t\t * Because we unsubscribe from the effect, the version may not change. We simply\n\t\t\t\t * set a new initial version in case of stale snapshots here.\n\t\t\t\t */\n\t\t\t\tversion = (version + 1) | 0;\n\t\t\t\tonChangeNotifyReact = undefined;\n\t\t\t\tunsubscribe();\n\t\t\t};\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn version;\n\t\t},\n\t\t_start() {\n\t\t\t// In general, we want to support two kinds of usages of useSignals:\n\t\t\t//\n\t\t\t// A) Managed: calling useSignals in a component or hook body wrapped in a\n\t\t\t// try/finally (like what the react-transform plugin does)\n\t\t\t//\n\t\t\t// B) Unmanaged: Calling useSignals directly without wrapping in a\n\t\t\t// try/finally\n\t\t\t//\n\t\t\t// For managed, we finish the effect in the finally block of the component\n\t\t\t// or hook body. For unmanaged, we finish the effect in the next\n\t\t\t// useSignals call or after a microtask.\n\t\t\t//\n\t\t\t// There are different tradeoffs which each approach. With managed, using\n\t\t\t// a try/finally ensures that only signals used in the component or hook\n\t\t\t// body are tracked. However, signals accessed in render props are missed\n\t\t\t// because the render prop is invoked in another component that may or may\n\t\t\t// not realize it is rendering signals accessed in the render prop it is\n\t\t\t// given.\n\t\t\t//\n\t\t\t// The other approach is \"unmanaged\": to call useSignals directly without\n\t\t\t// wrapping in a try/finally. This approach is easier to manually write in\n\t\t\t// situations where a build step isn't available but does open up the\n\t\t\t// possibility of catching signals accessed in other code before the\n\t\t\t// effect is closed (e.g. in a layout effect). Most situations where this\n\t\t\t// could happen are generally consider bad patterns or bugs. For example,\n\t\t\t// using a signal in a component and not having a call to `useSignals`\n\t\t\t// would be an bug. Or using a signal in `useLayoutEffect` is generally\n\t\t\t// not recommended since that layout effect won't update when the signals'\n\t\t\t// value change.\n\t\t\t//\n\t\t\t// To support both approaches, we need to track how each invocation of\n\t\t\t// useSignals is used, so we can properly transition between different\n\t\t\t// kinds of usages.\n\t\t\t//\n\t\t\t// The following table shows the different scenarios and how we should\n\t\t\t// handle them.\n\t\t\t//\n\t\t\t// Key:\n\t\t\t// 0 = UNMANAGED\n\t\t\t// 1 = MANAGED_COMPONENT\n\t\t\t// 2 = MANAGED_HOOK\n\t\t\t//\n\t\t\t// Pattern:\n\t\t\t// prev store usage -> this store usage: action to take\n\t\t\t//\n\t\t\t// - 0 -> 0: finish previous effect (unknown to unknown)\n\t\t\t//\n\t\t\t// We don't know how the previous effect was used, so we need to finish\n\t\t\t// it before starting the next effect.\n\t\t\t//\n\t\t\t// - 0 -> 1: finish previous effect\n\t\t\t//\n\t\t\t// Assume previous invocation was another component or hook from another\n\t\t\t// component. Nested component renders (renderToStaticMarkup within a\n\t\t\t// component's render) won't be supported with bare useSignals calls.\n\t\t\t//\n\t\t\t// - 0 -> 2: capture & restore\n\t\t\t//\n\t\t\t// Previous invocation could be a component or a hook. Either way,\n\t\t\t// restore it after our invocation so that it can continue to capture\n\t\t\t// any signals after we exit.\n\t\t\t//\n\t\t\t// - 1 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 1 -> 1: capture & restore (e.g. component calls renderToStaticMarkup)\n\t\t\t// - 1 -> 2: capture & restore (e.g. hook)\n\t\t\t//\n\t\t\t// - 2 -> 0: Do nothing. Signals already captured by current effect store\n\t\t\t// - 2 -> 1: capture & restore (e.g. hook calls renderToStaticMarkup)\n\t\t\t// - 2 -> 2: capture & restore (e.g. nested hook calls)\n\n\t\t\tif (currentStore == undefined) {\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst prevUsage = currentStore._usage;\n\t\t\tconst thisUsage = this._usage;\n\n\t\t\tif (\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == UNMANAGED) || // 0 -> 0\n\t\t\t\t(prevUsage == UNMANAGED && thisUsage == MANAGED_COMPONENT) // 0 -> 1\n\t\t\t) {\n\t\t\t\t// finish previous effect\n\t\t\t\tcurrentStore.f();\n\t\t\t\tendEffect = startComponentEffect(undefined, this);\n\t\t\t} else if (\n\t\t\t\t(prevUsage == MANAGED_COMPONENT && thisUsage == UNMANAGED) || // 1 -> 0\n\t\t\t\t(prevUsage == MANAGED_HOOK && thisUsage == UNMANAGED) // 2 -> 0\n\t\t\t) {\n\t\t\t\t// Do nothing since it'll be captured by current effect store\n\t\t\t} else {\n\t\t\t\t// nested scenarios, so capture and restore the previous effect store\n\t\t\t\tendEffect = startComponentEffect(currentStore, this);\n\t\t\t}\n\t\t},\n\t\tf() {\n\t\t\tconst end = endEffect;\n\t\t\tendEffect = undefined;\n\t\t\tend?.();\n\t\t},\n\t\t[symDispose]() {\n\t\t\tthis.f();\n\t\t},\n\t};\n}\n\nconst noop = () => {};\n\nfunction createEmptyEffectStore(): EffectStore {\n\treturn {\n\t\t_usage: UNMANAGED,\n\t\teffect: {\n\t\t\t_sources: undefined,\n\t\t\t_callback() {},\n\t\t\t_start() {\n\t\t\t\treturn /* endEffect */ noop;\n\t\t\t},\n\t\t\t_dispose() {},\n\t\t},\n\t\tsubscribe() {\n\t\t\treturn /* unsubscribe */ noop;\n\t\t},\n\t\tgetSnapshot() {\n\t\t\treturn 0;\n\t\t},\n\t\t_start() {},\n\t\tf() {},\n\t\t[symDispose]() {},\n\t};\n}\n\nconst emptyEffectStore = createEmptyEffectStore();\n\nconst _queueMicroTask = Promise.prototype.then.bind(Promise.resolve());\n\nlet finalCleanup: Promise<void> | undefined;\nexport function ensureFinalCleanup() {\n\tif (!finalCleanup) {\n\t\tfinalCleanup = _queueMicroTask(cleanupTrailingStore);\n\t}\n}\nfunction cleanupTrailingStore() {\n\tfinalCleanup = undefined;\n\tcurrentStore?.f();\n}\n\nconst useIsomorphicLayoutEffect =\n\ttypeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\n/**\n * Custom hook to create the effect to track signals used during render and\n * subscribe to changes to rerender the component when the signals change.\n */\nexport function _useSignalsImplementation(\n\t_usage: EffectStoreUsage = UNMANAGED\n): EffectStore {\n\tensureFinalCleanup();\n\n\tconst storeRef = useRef<EffectStore>();\n\tif (storeRef.current == null) {\n\t\tif (typeof window === \"undefined\") {\n\t\t\tstoreRef.current = emptyEffectStore;\n\t\t} else {\n\t\t\tstoreRef.current = createEffectStore(_usage);\n\t\t}\n\t}\n\n\tconst store = storeRef.current;\n\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\tstore._start();\n\t// note: _usage is a constant here, so conditional is okay\n\tif (_usage === UNMANAGED) useIsomorphicLayoutEffect(cleanupTrailingStore);\n\n\treturn store;\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node or JSX.\n */\nfunction SignalValue({ data }: { data: Signal }) {\n\tconst store = _useSignalsImplementation(1);\n\ttry {\n\t\treturn data.value;\n\t} finally {\n\t\tstore.f();\n\t}\n}\n\n// Decorate Signals so React renders them as <SignalValue> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: SignalValue },\n\tprops: {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn { data: this };\n\t\t},\n\t},\n\tref: { configurable: true, value: null },\n});\n\nexport function useSignals(usage?: EffectStoreUsage): EffectStore {\n\treturn _useSignalsImplementation(usage);\n}\n\nexport function useSignal<T>(value: T, options?: SignalOptions<T>): Signal<T>;\nexport function useSignal<T = undefined>(): Signal<T | undefined>;\nexport function useSignal<T>(value?: T, options?: SignalOptions<T>) {\n\treturn useMemo(\n\t\t() => signal<T | undefined>(value, options as SignalOptions),\n\t\tEmpty\n\t);\n}\n\nexport function useComputed<T>(\n\tcompute: () => T,\n\toptions?: SignalOptions<T>\n): ReadonlySignal<T> {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current(), options), Empty);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(function (this: Effect) {\n\t\t\treturn callback.current();\n\t\t});\n\t}, Empty);\n}\n"],"names":["major","reactVersion","split","map","Number","Empty","ReactElemType","Symbol","wrapJsx","jsx","type","props","i","v","Signal","value","call","apply","concat","slice","arguments","currentStore","symDispose","dispose","startComponentEffect","prevStore","nextStore","endEffect","effect","_start","finishComponentEffect","bind","_ref2","finalCleanup","noop","emptyEffectStore","_usage","_sources","undefined","_callback","_dispose","subscribe","getSnapshot","f","_queueMicroTask","Promise","prototype","then","resolve","ensureFinalCleanup","cleanupTrailingStore","_currentStore","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","_useSignalsImplementation","storeRef","useRef","current","_ref","effectInstance","onChangeNotifyReact","version","unsubscribe","this","onStoreChange","prevUsage","thisUsage","end","createEffectStore","store","useSyncExternalStore","Object","defineProperties","$$typeof","configurable","_ref3","data","get","ref","useSignals","usage","useSignal","options","useMemo","signal","useComputed","compute","$compute","computed","useSignalEffect","cb","callback"],"mappings":"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"}
|
package/runtime/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
effect,
|
|
5
5
|
Signal,
|
|
6
6
|
ReadonlySignal,
|
|
7
|
+
SignalOptions,
|
|
7
8
|
} from "@preact/signals-core";
|
|
8
9
|
import {
|
|
9
10
|
useRef,
|
|
@@ -384,16 +385,22 @@ export function useSignals(usage?: EffectStoreUsage): EffectStore {
|
|
|
384
385
|
return _useSignalsImplementation(usage);
|
|
385
386
|
}
|
|
386
387
|
|
|
387
|
-
export function useSignal<T>(value: T): Signal<T>;
|
|
388
|
+
export function useSignal<T>(value: T, options?: SignalOptions<T>): Signal<T>;
|
|
388
389
|
export function useSignal<T = undefined>(): Signal<T | undefined>;
|
|
389
|
-
export function useSignal<T>(value?: T) {
|
|
390
|
-
return useMemo(
|
|
390
|
+
export function useSignal<T>(value?: T, options?: SignalOptions<T>) {
|
|
391
|
+
return useMemo(
|
|
392
|
+
() => signal<T | undefined>(value, options as SignalOptions),
|
|
393
|
+
Empty
|
|
394
|
+
);
|
|
391
395
|
}
|
|
392
396
|
|
|
393
|
-
export function useComputed<T>(
|
|
397
|
+
export function useComputed<T>(
|
|
398
|
+
compute: () => T,
|
|
399
|
+
options?: SignalOptions<T>
|
|
400
|
+
): ReadonlySignal<T> {
|
|
394
401
|
const $compute = useRef(compute);
|
|
395
402
|
$compute.current = compute;
|
|
396
|
-
return useMemo(() => computed<T>(() => $compute.current()), Empty);
|
|
403
|
+
return useMemo(() => computed<T>(() => $compute.current(), options), Empty);
|
|
397
404
|
}
|
|
398
405
|
|
|
399
406
|
export function useSignalEffect(cb: () => void | (() => void)) {
|
package/utils/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { ReadonlySignal, Signal } from "@preact/signals-core";
|
|
|
2
2
|
interface ShowProps<T = boolean> {
|
|
3
3
|
when: Signal<T> | ReadonlySignal<T>;
|
|
4
4
|
fallback?: JSX.Element;
|
|
5
|
-
children: JSX.Element | ((value: T) => JSX.Element);
|
|
5
|
+
children: JSX.Element | ((value: NonNullable<T>) => JSX.Element);
|
|
6
6
|
}
|
|
7
7
|
export declare function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null;
|
|
8
8
|
interface ForProps<T> {
|
package/utils/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../src/index.ts"],"sourcesContent":["import { ReadonlySignal, Signal } from \"@preact/signals-core\";\nimport { useSignal } from \"@preact/signals-react\";\nimport { useSignals } from \"@preact/signals-react/runtime\";\nimport { Fragment, createElement, useMemo } from \"react\";\n\ninterface ShowProps<T = boolean> {\n\twhen: Signal<T> | ReadonlySignal<T>;\n\tfallback?: JSX.Element;\n\tchildren: JSX.Element | ((value: T) => JSX.Element);\n}\n\nexport function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst value = props.when.value;\n\tif (!value) return props.fallback || null;\n\treturn typeof props.children === \"function\"\n\t\t? props.children(value)\n\t\t: props.children;\n}\n\ninterface ForProps<T> {\n\teach:\n\t\t| Signal<Array<T>>\n\t\t| ReadonlySignal<Array<T>>\n\t\t| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);\n\tfallback?: JSX.Element;\n\tchildren: (value: T, index: number) => JSX.Element;\n}\n\nexport function For<T>(props: ForProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst cache = useMemo(() => new Map(), []);\n\tlet list = (\n\t\t(typeof props.each === \"function\" ? props.each() : props.each) as Signal<\n\t\t\tArray<T>\n\t\t>\n\t).value;\n\n\tif (!list.length) return props.fallback || null;\n\n\tconst items = list.map((value, key) => {\n\t\tif (!cache.has(value)) {\n\t\t\tcache.set(value, props.children(value, key));\n\t\t}\n\t\treturn cache.get(value);\n\t});\n\treturn createElement(Fragment, { children: items });\n}\n\nexport function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {\n\tconst s = useSignal(value);\n\tif (s.peek() !== value) s.value = value;\n\treturn s;\n}\n\nexport function useSignalRef<T>(value: T) {\n\tconst ref = useSignal(value) as Signal<T> & { current: T };\n\tif (!(\"current\" in ref))\n\t\tObject.defineProperty(ref, \"current\", refSignalProto);\n\treturn ref;\n}\nconst refSignalProto = {\n\tconfigurable: true,\n\tget(this: Signal) {\n\t\treturn this.value;\n\t},\n\tset(this: Signal, v: any) {\n\t\tthis.value = v;\n\t},\n};\n"],"names":["refSignalProto","configurable","get","this","value","set","v","exports","For","props","useSignals","cache","useMemo","Map","list","each","length","fallback","items","map","key","has","children","createElement","Fragment","Show","when","useLiveSignal","s","useSignal","peek","useSignalRef","ref","Object","defineProperty"],"mappings":"qGA6DMA,EAAiB,CACtBC,cAAc,EACdC,
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../src/index.ts"],"sourcesContent":["import { ReadonlySignal, Signal } from \"@preact/signals-core\";\nimport { useSignal } from \"@preact/signals-react\";\nimport { useSignals } from \"@preact/signals-react/runtime\";\nimport { Fragment, createElement, useMemo } from \"react\";\n\ninterface ShowProps<T = boolean> {\n\twhen: Signal<T> | ReadonlySignal<T>;\n\tfallback?: JSX.Element;\n\tchildren: JSX.Element | ((value: NonNullable<T>) => JSX.Element);\n}\n\nexport function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst value = props.when.value;\n\tif (!value) return props.fallback || null;\n\treturn typeof props.children === \"function\"\n\t\t? props.children(value)\n\t\t: props.children;\n}\n\ninterface ForProps<T> {\n\teach:\n\t\t| Signal<Array<T>>\n\t\t| ReadonlySignal<Array<T>>\n\t\t| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);\n\tfallback?: JSX.Element;\n\tchildren: (value: T, index: number) => JSX.Element;\n}\n\nexport function For<T>(props: ForProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst cache = useMemo(() => new Map(), []);\n\tlet list = (\n\t\t(typeof props.each === \"function\" ? props.each() : props.each) as Signal<\n\t\t\tArray<T>\n\t\t>\n\t).value;\n\n\tif (!list.length) return props.fallback || null;\n\n\tconst items = list.map((value, key) => {\n\t\tif (!cache.has(value)) {\n\t\t\tcache.set(value, props.children(value, key));\n\t\t}\n\t\treturn cache.get(value);\n\t});\n\treturn createElement(Fragment, { children: items });\n}\n\nexport function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {\n\tconst s = useSignal(value);\n\tif (s.peek() !== value) s.value = value;\n\treturn s;\n}\n\nexport function useSignalRef<T>(value: T) {\n\tconst ref = useSignal(value) as Signal<T> & { current: T };\n\tif (!(\"current\" in ref))\n\t\tObject.defineProperty(ref, \"current\", refSignalProto);\n\treturn ref;\n}\nconst refSignalProto = {\n\tconfigurable: true,\n\tget(this: Signal) {\n\t\treturn this.value;\n\t},\n\tset(this: Signal, v: any) {\n\t\tthis.value = v;\n\t},\n};\n"],"names":["refSignalProto","configurable","get","this","value","set","v","exports","For","props","useSignals","cache","useMemo","Map","list","each","length","fallback","items","map","key","has","children","createElement","Fragment","Show","when","useLiveSignal","s","useSignal","peek","useSignalRef","ref","Object","defineProperty"],"mappings":"qGA6DMA,EAAiB,CACtBC,cAAc,EACdC,eACC,OAAOC,KAAKC,KACb,EACAC,IAAA,SAAkBC,GACjBH,KAAKC,MAAQE,CACd,GACAC,QAAAC,IAxCK,SAAiBC,GACtBC,EAAAA,aACA,IAAMC,EAAQC,EAAAA,QAAQ,WAAA,OAAU,IAAAC,GAAK,EAAE,IACnCC,GACoB,mBAAfL,EAAMM,KAAsBN,EAAMM,OAASN,EAAMM,MAGxDX,MAEF,IAAKU,EAAKE,OAAQ,OAAOP,EAAMQ,UAAY,KAE3C,IAAMC,EAAQJ,EAAKK,IAAI,SAACf,EAAOgB,GAC9B,IAAKT,EAAMU,IAAIjB,GACdO,EAAMN,IAAID,EAAOK,EAAMa,SAASlB,EAAOgB,IAExC,OAAOT,EAAMT,IAAIE,EAClB,GACA,OAAOmB,EAAaA,cAACC,EAAQA,SAAE,CAAEF,SAAUJ,GAC5C,EAsBCX,QAAAkB,cA1DiChB,GACjCC,EAAAA,aACA,IAAMN,EAAQK,EAAMiB,KAAKtB,MACzB,IAAKA,EAAO,OAAOK,EAAMQ,UAAY,UACrC,MAAiC,mBAAnBR,EAAMa,SACjBb,EAAMa,SAASlB,GACfK,EAAMa,QACV,EAmDCf,QAAAoB,uBApBgCvB,GAChC,IAAMwB,EAAIC,EAAAA,UAAUzB,GACpB,GAAIwB,EAAEE,SAAW1B,EAAOwB,EAAExB,MAAQA,EAClC,OAAOwB,CACR,EAgBCrB,QAAAwB,aAde,SAAgB3B,GAC/B,IAAM4B,EAAMH,EAASA,UAACzB,GACtB,KAAM,YAAa4B,GAClBC,OAAOC,eAAeF,EAAK,UAAWhC,GACvC,OAAOgC,CACR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.min.js","sources":["../src/index.ts"],"sourcesContent":["import { ReadonlySignal, Signal } from \"@preact/signals-core\";\nimport { useSignal } from \"@preact/signals-react\";\nimport { useSignals } from \"@preact/signals-react/runtime\";\nimport { Fragment, createElement, useMemo } from \"react\";\n\ninterface ShowProps<T = boolean> {\n\twhen: Signal<T> | ReadonlySignal<T>;\n\tfallback?: JSX.Element;\n\tchildren: JSX.Element | ((value: T) => JSX.Element);\n}\n\nexport function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst value = props.when.value;\n\tif (!value) return props.fallback || null;\n\treturn typeof props.children === \"function\"\n\t\t? props.children(value)\n\t\t: props.children;\n}\n\ninterface ForProps<T> {\n\teach:\n\t\t| Signal<Array<T>>\n\t\t| ReadonlySignal<Array<T>>\n\t\t| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);\n\tfallback?: JSX.Element;\n\tchildren: (value: T, index: number) => JSX.Element;\n}\n\nexport function For<T>(props: ForProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst cache = useMemo(() => new Map(), []);\n\tlet list = (\n\t\t(typeof props.each === \"function\" ? props.each() : props.each) as Signal<\n\t\t\tArray<T>\n\t\t>\n\t).value;\n\n\tif (!list.length) return props.fallback || null;\n\n\tconst items = list.map((value, key) => {\n\t\tif (!cache.has(value)) {\n\t\t\tcache.set(value, props.children(value, key));\n\t\t}\n\t\treturn cache.get(value);\n\t});\n\treturn createElement(Fragment, { children: items });\n}\n\nexport function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {\n\tconst s = useSignal(value);\n\tif (s.peek() !== value) s.value = value;\n\treturn s;\n}\n\nexport function useSignalRef<T>(value: T) {\n\tconst ref = useSignal(value) as Signal<T> & { current: T };\n\tif (!(\"current\" in ref))\n\t\tObject.defineProperty(ref, \"current\", refSignalProto);\n\treturn ref;\n}\nconst refSignalProto = {\n\tconfigurable: true,\n\tget(this: Signal) {\n\t\treturn this.value;\n\t},\n\tset(this: Signal, v: any) {\n\t\tthis.value = v;\n\t},\n};\n"],"names":["refSignalProto","configurable","get","this","value","set","v","exports","For","props","useSignals","cache","useMemo","Map","list","each","length","fallback","items","map","key","has","children","createElement","Fragment","Show","when","useLiveSignal","s","useSignal","peek","useSignalRef","ref","Object","defineProperty"],"mappings":"ybA6DA,IAAMA,EAAiB,CACtBC,cAAc,EACdC,
|
|
1
|
+
{"version":3,"file":"utils.min.js","sources":["../src/index.ts"],"sourcesContent":["import { ReadonlySignal, Signal } from \"@preact/signals-core\";\nimport { useSignal } from \"@preact/signals-react\";\nimport { useSignals } from \"@preact/signals-react/runtime\";\nimport { Fragment, createElement, useMemo } from \"react\";\n\ninterface ShowProps<T = boolean> {\n\twhen: Signal<T> | ReadonlySignal<T>;\n\tfallback?: JSX.Element;\n\tchildren: JSX.Element | ((value: NonNullable<T>) => JSX.Element);\n}\n\nexport function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst value = props.when.value;\n\tif (!value) return props.fallback || null;\n\treturn typeof props.children === \"function\"\n\t\t? props.children(value)\n\t\t: props.children;\n}\n\ninterface ForProps<T> {\n\teach:\n\t\t| Signal<Array<T>>\n\t\t| ReadonlySignal<Array<T>>\n\t\t| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);\n\tfallback?: JSX.Element;\n\tchildren: (value: T, index: number) => JSX.Element;\n}\n\nexport function For<T>(props: ForProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst cache = useMemo(() => new Map(), []);\n\tlet list = (\n\t\t(typeof props.each === \"function\" ? props.each() : props.each) as Signal<\n\t\t\tArray<T>\n\t\t>\n\t).value;\n\n\tif (!list.length) return props.fallback || null;\n\n\tconst items = list.map((value, key) => {\n\t\tif (!cache.has(value)) {\n\t\t\tcache.set(value, props.children(value, key));\n\t\t}\n\t\treturn cache.get(value);\n\t});\n\treturn createElement(Fragment, { children: items });\n}\n\nexport function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {\n\tconst s = useSignal(value);\n\tif (s.peek() !== value) s.value = value;\n\treturn s;\n}\n\nexport function useSignalRef<T>(value: T) {\n\tconst ref = useSignal(value) as Signal<T> & { current: T };\n\tif (!(\"current\" in ref))\n\t\tObject.defineProperty(ref, \"current\", refSignalProto);\n\treturn ref;\n}\nconst refSignalProto = {\n\tconfigurable: true,\n\tget(this: Signal) {\n\t\treturn this.value;\n\t},\n\tset(this: Signal, v: any) {\n\t\tthis.value = v;\n\t},\n};\n"],"names":["refSignalProto","configurable","get","this","value","set","v","exports","For","props","useSignals","cache","useMemo","Map","list","each","length","fallback","items","map","key","has","children","createElement","Fragment","Show","when","useLiveSignal","s","useSignal","peek","useSignalRef","ref","Object","defineProperty"],"mappings":"ybA6DA,IAAMA,EAAiB,CACtBC,cAAc,EACdC,eACC,OAAOC,KAAKC,KACb,EACAC,IAAA,SAAkBC,GACjBH,KAAKC,MAAQE,CACd,GACAC,EAAAC,IAxCK,SAAiBC,GACtBC,EAAAA,aACA,IAAMC,EAAQC,EAAAA,QAAQ,WAAA,OAAU,IAAAC,GAAK,EAAE,IACnCC,GACoB,mBAAfL,EAAMM,KAAsBN,EAAMM,OAASN,EAAMM,MAGxDX,MAEF,IAAKU,EAAKE,OAAQ,OAAOP,EAAMQ,UAAY,KAE3C,IAAMC,EAAQJ,EAAKK,IAAI,SAACf,EAAOgB,GAC9B,IAAKT,EAAMU,IAAIjB,GACdO,EAAMN,IAAID,EAAOK,EAAMa,SAASlB,EAAOgB,IAExC,OAAOT,EAAMT,IAAIE,EAClB,GACA,OAAOmB,EAAaA,cAACC,EAAQA,SAAE,CAAEF,SAAUJ,GAC5C,EAsBCX,EAAAkB,cA1DiChB,GACjCC,EAAAA,aACA,IAAMN,EAAQK,EAAMiB,KAAKtB,MACzB,IAAKA,EAAO,OAAOK,EAAMQ,UAAY,UACrC,MAAiC,mBAAnBR,EAAMa,SACjBb,EAAMa,SAASlB,GACfK,EAAMa,QACV,EAmDCf,EAAAoB,uBApBgCvB,GAChC,IAAMwB,EAAIC,EAAAA,UAAUzB,GACpB,GAAIwB,EAAEE,SAAW1B,EAAOwB,EAAExB,MAAQA,EAClC,OAAOwB,CACR,EAgBCrB,EAAAwB,aAde,SAAgB3B,GAC/B,IAAM4B,EAAMH,EAASA,UAACzB,GACtB,KAAM,YAAa4B,GAClBC,OAAOC,eAAeF,EAAK,UAAWhC,GACvC,OAAOgC,CACR,CASC"}
|
package/utils/dist/utils.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","sources":["../src/index.ts"],"sourcesContent":["import { ReadonlySignal, Signal } from \"@preact/signals-core\";\nimport { useSignal } from \"@preact/signals-react\";\nimport { useSignals } from \"@preact/signals-react/runtime\";\nimport { Fragment, createElement, useMemo } from \"react\";\n\ninterface ShowProps<T = boolean> {\n\twhen: Signal<T> | ReadonlySignal<T>;\n\tfallback?: JSX.Element;\n\tchildren: JSX.Element | ((value: T) => JSX.Element);\n}\n\nexport function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst value = props.when.value;\n\tif (!value) return props.fallback || null;\n\treturn typeof props.children === \"function\"\n\t\t? props.children(value)\n\t\t: props.children;\n}\n\ninterface ForProps<T> {\n\teach:\n\t\t| Signal<Array<T>>\n\t\t| ReadonlySignal<Array<T>>\n\t\t| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);\n\tfallback?: JSX.Element;\n\tchildren: (value: T, index: number) => JSX.Element;\n}\n\nexport function For<T>(props: ForProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst cache = useMemo(() => new Map(), []);\n\tlet list = (\n\t\t(typeof props.each === \"function\" ? props.each() : props.each) as Signal<\n\t\t\tArray<T>\n\t\t>\n\t).value;\n\n\tif (!list.length) return props.fallback || null;\n\n\tconst items = list.map((value, key) => {\n\t\tif (!cache.has(value)) {\n\t\t\tcache.set(value, props.children(value, key));\n\t\t}\n\t\treturn cache.get(value);\n\t});\n\treturn createElement(Fragment, { children: items });\n}\n\nexport function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {\n\tconst s = useSignal(value);\n\tif (s.peek() !== value) s.value = value;\n\treturn s;\n}\n\nexport function useSignalRef<T>(value: T) {\n\tconst ref = useSignal(value) as Signal<T> & { current: T };\n\tif (!(\"current\" in ref))\n\t\tObject.defineProperty(ref, \"current\", refSignalProto);\n\treturn ref;\n}\nconst refSignalProto = {\n\tconfigurable: true,\n\tget(this: Signal) {\n\t\treturn this.value;\n\t},\n\tset(this: Signal, v: any) {\n\t\tthis.value = v;\n\t},\n};\n"],"names":["useSignal","useSignals","useMemo","createElement","Fragment","Show","props","value","when","fallback","children","For","cache","Map","list","each","length","items","map","key","has","set","get","useLiveSignal","s","peek","useSignalRef","ref","Object","defineProperty","refSignalProto","configurable","v","this"],"mappings":"OAWgBA,cAAA,6CAAAC,MAAA,kDAAAC,mBAAAC,cAAAC,MAAA,QAAA,SAAAC,EAAkBC,GACjCL,IACA,MAAMM,EAAQD,EAAME,KAAKD,MACzB,IAAKA,EAAO,OAAOD,EAAMG,UAAY,UACrC,MAAiC,mBAAnBH,EAAMI,SACjBJ,EAAMI,SAASH,GACfD,EAAMI,QACV,CAWgB,SAAAC,EAAOL,GACtBL,IACA,MAAMW,EAAQV,EAAQ,IAAM,IAAIW,IAAO,IACvC,IAAIC,GACoB,mBAAfR,EAAMS,KAAsBT,EAAMS,OAAST,EAAMS,MAGxDR,MAEF,IAAKO,EAAKE,OAAQ,OAAOV,EAAMG,UAAY,KAE3C,MAAMQ,EAAQH,EAAKI,IAAI,CAACX,EAAOY,KAC9B,IAAKP,EAAMQ,IAAIb,GACdK,EAAMS,IAAId,EAAOD,EAAMI,SAASH,EAAOY,IAExC,OAAOP,EAAMU,IAAIf,EAAK,GAEvB,OAAOJ,EAAcC,EAAU,CAAEM,SAAUO,GAC5C,CAEM,SAAUM,EAAiBhB,GAChC,MAAMiB,EAAIxB,UAAUO,GACpB,GAAIiB,EAAEC,SAAWlB,EAAOiB,EAAEjB,MAAQA,EAClC,OAAOiB,CACR,CAEgB,SAAAE,EAAgBnB,GAC/B,MAAMoB,EAAM3B,UAAUO,GACtB,KAAM,YAAaoB,GAClBC,OAAOC,eAAeF,EAAK,UAAWG,GACvC,OAAOH,CACR,CACA,MAAMG,EAAiB,CACtBC,cAAc,EACdT,MACC,YAAYf,KACb,EACAc,IAAkBW,GACjBC,KAAK1B,MAAQyB,CACd,UACArB,SAAAN,UAAAkB,mBAAAG"}
|
|
1
|
+
{"version":3,"file":"utils.mjs","sources":["../src/index.ts"],"sourcesContent":["import { ReadonlySignal, Signal } from \"@preact/signals-core\";\nimport { useSignal } from \"@preact/signals-react\";\nimport { useSignals } from \"@preact/signals-react/runtime\";\nimport { Fragment, createElement, useMemo } from \"react\";\n\ninterface ShowProps<T = boolean> {\n\twhen: Signal<T> | ReadonlySignal<T>;\n\tfallback?: JSX.Element;\n\tchildren: JSX.Element | ((value: NonNullable<T>) => JSX.Element);\n}\n\nexport function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst value = props.when.value;\n\tif (!value) return props.fallback || null;\n\treturn typeof props.children === \"function\"\n\t\t? props.children(value)\n\t\t: props.children;\n}\n\ninterface ForProps<T> {\n\teach:\n\t\t| Signal<Array<T>>\n\t\t| ReadonlySignal<Array<T>>\n\t\t| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);\n\tfallback?: JSX.Element;\n\tchildren: (value: T, index: number) => JSX.Element;\n}\n\nexport function For<T>(props: ForProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst cache = useMemo(() => new Map(), []);\n\tlet list = (\n\t\t(typeof props.each === \"function\" ? props.each() : props.each) as Signal<\n\t\t\tArray<T>\n\t\t>\n\t).value;\n\n\tif (!list.length) return props.fallback || null;\n\n\tconst items = list.map((value, key) => {\n\t\tif (!cache.has(value)) {\n\t\t\tcache.set(value, props.children(value, key));\n\t\t}\n\t\treturn cache.get(value);\n\t});\n\treturn createElement(Fragment, { children: items });\n}\n\nexport function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {\n\tconst s = useSignal(value);\n\tif (s.peek() !== value) s.value = value;\n\treturn s;\n}\n\nexport function useSignalRef<T>(value: T) {\n\tconst ref = useSignal(value) as Signal<T> & { current: T };\n\tif (!(\"current\" in ref))\n\t\tObject.defineProperty(ref, \"current\", refSignalProto);\n\treturn ref;\n}\nconst refSignalProto = {\n\tconfigurable: true,\n\tget(this: Signal) {\n\t\treturn this.value;\n\t},\n\tset(this: Signal, v: any) {\n\t\tthis.value = v;\n\t},\n};\n"],"names":["useSignal","useSignals","useMemo","createElement","Fragment","Show","props","value","when","fallback","children","For","cache","Map","list","each","length","items","map","key","has","set","get","useLiveSignal","s","peek","useSignalRef","ref","Object","defineProperty","refSignalProto","configurable","v","this"],"mappings":"OAWgBA,cAAA,6CAAAC,MAAA,kDAAAC,mBAAAC,cAAAC,MAAA,QAAA,SAAAC,EAAkBC,GACjCL,IACA,MAAMM,EAAQD,EAAME,KAAKD,MACzB,IAAKA,EAAO,OAAOD,EAAMG,UAAY,UACrC,MAAiC,mBAAnBH,EAAMI,SACjBJ,EAAMI,SAASH,GACfD,EAAMI,QACV,CAWgB,SAAAC,EAAOL,GACtBL,IACA,MAAMW,EAAQV,EAAQ,IAAM,IAAIW,IAAO,IACvC,IAAIC,GACoB,mBAAfR,EAAMS,KAAsBT,EAAMS,OAAST,EAAMS,MAGxDR,MAEF,IAAKO,EAAKE,OAAQ,OAAOV,EAAMG,UAAY,KAE3C,MAAMQ,EAAQH,EAAKI,IAAI,CAACX,EAAOY,KAC9B,IAAKP,EAAMQ,IAAIb,GACdK,EAAMS,IAAId,EAAOD,EAAMI,SAASH,EAAOY,IAExC,OAAOP,EAAMU,IAAIf,EAAK,GAEvB,OAAOJ,EAAcC,EAAU,CAAEM,SAAUO,GAC5C,CAEM,SAAUM,EAAiBhB,GAChC,MAAMiB,EAAIxB,UAAUO,GACpB,GAAIiB,EAAEC,SAAWlB,EAAOiB,EAAEjB,MAAQA,EAClC,OAAOiB,CACR,CAEgB,SAAAE,EAAgBnB,GAC/B,MAAMoB,EAAM3B,UAAUO,GACtB,KAAM,YAAaoB,GAClBC,OAAOC,eAAeF,EAAK,UAAWG,GACvC,OAAOH,CACR,CACA,MAAMG,EAAiB,CACtBC,cAAc,EACdT,MACC,YAAYf,KACb,EACAc,IAAkBW,GACjBC,KAAK1B,MAAQyB,CACd,UACArB,SAAAN,UAAAkB,mBAAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.module.js","sources":["../src/index.ts"],"sourcesContent":["import { ReadonlySignal, Signal } from \"@preact/signals-core\";\nimport { useSignal } from \"@preact/signals-react\";\nimport { useSignals } from \"@preact/signals-react/runtime\";\nimport { Fragment, createElement, useMemo } from \"react\";\n\ninterface ShowProps<T = boolean> {\n\twhen: Signal<T> | ReadonlySignal<T>;\n\tfallback?: JSX.Element;\n\tchildren: JSX.Element | ((value: T) => JSX.Element);\n}\n\nexport function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst value = props.when.value;\n\tif (!value) return props.fallback || null;\n\treturn typeof props.children === \"function\"\n\t\t? props.children(value)\n\t\t: props.children;\n}\n\ninterface ForProps<T> {\n\teach:\n\t\t| Signal<Array<T>>\n\t\t| ReadonlySignal<Array<T>>\n\t\t| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);\n\tfallback?: JSX.Element;\n\tchildren: (value: T, index: number) => JSX.Element;\n}\n\nexport function For<T>(props: ForProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst cache = useMemo(() => new Map(), []);\n\tlet list = (\n\t\t(typeof props.each === \"function\" ? props.each() : props.each) as Signal<\n\t\t\tArray<T>\n\t\t>\n\t).value;\n\n\tif (!list.length) return props.fallback || null;\n\n\tconst items = list.map((value, key) => {\n\t\tif (!cache.has(value)) {\n\t\t\tcache.set(value, props.children(value, key));\n\t\t}\n\t\treturn cache.get(value);\n\t});\n\treturn createElement(Fragment, { children: items });\n}\n\nexport function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {\n\tconst s = useSignal(value);\n\tif (s.peek() !== value) s.value = value;\n\treturn s;\n}\n\nexport function useSignalRef<T>(value: T) {\n\tconst ref = useSignal(value) as Signal<T> & { current: T };\n\tif (!(\"current\" in ref))\n\t\tObject.defineProperty(ref, \"current\", refSignalProto);\n\treturn ref;\n}\nconst refSignalProto = {\n\tconfigurable: true,\n\tget(this: Signal) {\n\t\treturn this.value;\n\t},\n\tset(this: Signal, v: any) {\n\t\tthis.value = v;\n\t},\n};\n"],"names":["Show","props","useSignals","value","when","fallback","children","For","cache","useMemo","Map","list","each","length","items","map","key","has","set","get","createElement","Fragment","useLiveSignal","s","useSignal","peek","useSignalRef","ref","Object","defineProperty","refSignalProto","configurable","this","v"],"mappings":"kLAWgBA,EAAkBC,GACjCC,IACA,IAAMC,EAAQF,EAAMG,KAAKD,MACzB,IAAKA,EAAO,OAAOF,EAAMI,UAAY,UACrC,MAAiC,mBAAnBJ,EAAMK,SACjBL,EAAMK,SAASH,GACfF,EAAMK,QACV,
|
|
1
|
+
{"version":3,"file":"utils.module.js","sources":["../src/index.ts"],"sourcesContent":["import { ReadonlySignal, Signal } from \"@preact/signals-core\";\nimport { useSignal } from \"@preact/signals-react\";\nimport { useSignals } from \"@preact/signals-react/runtime\";\nimport { Fragment, createElement, useMemo } from \"react\";\n\ninterface ShowProps<T = boolean> {\n\twhen: Signal<T> | ReadonlySignal<T>;\n\tfallback?: JSX.Element;\n\tchildren: JSX.Element | ((value: NonNullable<T>) => JSX.Element);\n}\n\nexport function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst value = props.when.value;\n\tif (!value) return props.fallback || null;\n\treturn typeof props.children === \"function\"\n\t\t? props.children(value)\n\t\t: props.children;\n}\n\ninterface ForProps<T> {\n\teach:\n\t\t| Signal<Array<T>>\n\t\t| ReadonlySignal<Array<T>>\n\t\t| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);\n\tfallback?: JSX.Element;\n\tchildren: (value: T, index: number) => JSX.Element;\n}\n\nexport function For<T>(props: ForProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst cache = useMemo(() => new Map(), []);\n\tlet list = (\n\t\t(typeof props.each === \"function\" ? props.each() : props.each) as Signal<\n\t\t\tArray<T>\n\t\t>\n\t).value;\n\n\tif (!list.length) return props.fallback || null;\n\n\tconst items = list.map((value, key) => {\n\t\tif (!cache.has(value)) {\n\t\t\tcache.set(value, props.children(value, key));\n\t\t}\n\t\treturn cache.get(value);\n\t});\n\treturn createElement(Fragment, { children: items });\n}\n\nexport function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {\n\tconst s = useSignal(value);\n\tif (s.peek() !== value) s.value = value;\n\treturn s;\n}\n\nexport function useSignalRef<T>(value: T) {\n\tconst ref = useSignal(value) as Signal<T> & { current: T };\n\tif (!(\"current\" in ref))\n\t\tObject.defineProperty(ref, \"current\", refSignalProto);\n\treturn ref;\n}\nconst refSignalProto = {\n\tconfigurable: true,\n\tget(this: Signal) {\n\t\treturn this.value;\n\t},\n\tset(this: Signal, v: any) {\n\t\tthis.value = v;\n\t},\n};\n"],"names":["Show","props","useSignals","value","when","fallback","children","For","cache","useMemo","Map","list","each","length","items","map","key","has","set","get","createElement","Fragment","useLiveSignal","s","useSignal","peek","useSignalRef","ref","Object","defineProperty","refSignalProto","configurable","this","v"],"mappings":"kLAWgBA,EAAkBC,GACjCC,IACA,IAAMC,EAAQF,EAAMG,KAAKD,MACzB,IAAKA,EAAO,OAAOF,EAAMI,UAAY,UACrC,MAAiC,mBAAnBJ,EAAMK,SACjBL,EAAMK,SAASH,GACfF,EAAMK,QACV,CAWM,SAAUC,EAAON,GACtBC,IACA,IAAMM,EAAQC,EAAQ,WAAA,OAAU,IAAAC,GAAK,EAAE,IACnCC,GACoB,mBAAfV,EAAMW,KAAsBX,EAAMW,OAASX,EAAMW,MAGxDT,MAEF,IAAKQ,EAAKE,OAAQ,OAAOZ,EAAMI,UAAY,KAE3C,IAAMS,EAAQH,EAAKI,IAAI,SAACZ,EAAOa,GAC9B,IAAKR,EAAMS,IAAId,GACdK,EAAMU,IAAIf,EAAOF,EAAMK,SAASH,EAAOa,IAExC,OAAOR,EAAMW,IAAIhB,EAClB,GACA,OAAOiB,EAAcC,EAAU,CAAEf,SAAUQ,GAC5C,UAEgBQ,EAAiBnB,GAChC,IAAMoB,EAAIC,UAAUrB,GACpB,GAAIoB,EAAEE,SAAWtB,EAAOoB,EAAEpB,MAAQA,EAClC,OAAOoB,CACR,CAEgB,SAAAG,EAAgBvB,GAC/B,IAAMwB,EAAMH,UAAUrB,GACtB,KAAM,YAAawB,GAClBC,OAAOC,eAAeF,EAAK,UAAWG,GACvC,OAAOH,CACR,CACA,IAAMG,EAAiB,CACtBC,cAAc,EACdZ,eACC,OAAOa,KAAK7B,KACb,EACAe,IAAA,SAAkBe,GACjBD,KAAK7B,MAAQ8B,CACd,UACA1B,SAAAP,UAAAsB,mBAAAI"}
|
package/utils/src/index.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { Fragment, createElement, useMemo } from "react";
|
|
|
6
6
|
interface ShowProps<T = boolean> {
|
|
7
7
|
when: Signal<T> | ReadonlySignal<T>;
|
|
8
8
|
fallback?: JSX.Element;
|
|
9
|
-
children: JSX.Element | ((value: T) => JSX.Element);
|
|
9
|
+
children: JSX.Element | ((value: NonNullable<T>) => JSX.Element);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {
|