@preact/signals-react 1.1.1 → 1.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 CHANGED
@@ -1,5 +1,24 @@
1
1
  # @preact/signals-react
2
2
 
3
+ ## 1.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#238](https://github.com/preactjs/signals/pull/238) [`bcf4b0b`](https://github.com/preactjs/signals/commit/bcf4b0b25d774483ddafa29c2fa133c467668b8c) Thanks [@eddyw](https://github.com/eddyw)! - Fix ERR_UNSUPPORTED_DIR_IMPORT error when importing `use-sync-external-store/shim` from ESM build
8
+
9
+ ## 1.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#219](https://github.com/preactjs/signals/pull/219) [`0621526`](https://github.com/preactjs/signals/commit/0621526dd59187f674557e6df42c71980b32efab) Thanks [@eddyw](https://github.com/eddyw)! - Replace useReducer with useSyncExternalStore
14
+
15
+ ### Patch Changes
16
+
17
+ - [#226](https://github.com/preactjs/signals/pull/226) [`ad29826`](https://github.com/preactjs/signals/commit/ad2982606a8894ea8562a0726d7777185987ad60) Thanks [@marvinhagemeister](https://github.com/marvinhagemeister)! - Fix hook names being mangled
18
+
19
+ - Updated dependencies [[`aa4cb7b`](https://github.com/preactjs/signals/commit/aa4cb7bfad744e78952cacc37af5bd4a713f0d3f), [`3f652a7`](https://github.com/preactjs/signals/commit/3f652a77d2a125a02a0cfc29fe661c81beeda16d)]:
20
+ - @preact/signals-core@1.2.2
21
+
3
22
  ## 1.1.1
4
23
 
5
24
  ### Patch Changes
package/dist/signals.js CHANGED
@@ -1 +1 @@
1
- var r=require("react"),n=require("@preact/signals-core");function t(r){return r&&"object"==typeof r&&"default"in r?r.default:r}var e,u=/*#__PURE__*/t(r),i=u.createElement;u.createElement=function(r,t){if("string"==typeof r&&t)for(var e in t){var u=t[e];if("children"!==e&&u instanceof n.Signal)t[e]=u.value}return i.apply(this,arguments)};var o=new WeakMap;function f(r){if(e)e();e=r&&r.S()}var a=i("a").$$typeof;Object.defineProperties(n.Signal.prototype,{$$typeof:{configurable:!0,value:a},type:{configurable:!0,value:function(r){return r.data.value}},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});var c,v=!1,s=function(){return{}};Object.defineProperty(r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher,"current",{get:function(){return c},set:function(r){c=r;if(!v)if(r&&!function(r){var n=p.get(r);if(void 0!==n)return n;var t=r.useCallback.length<2||/Invalid/.test(r.useCallback);p.set(r,t);return t}(r)){v=!0;var t=r.useReducer(s,{})[1];v=!1;var e=o.get(t);if(!e){e=function(r){var t;n.effect(function(){t=this});t.c=r;return t}(t);o.set(t,e)}else e.c=t;f(e)}else f()}});var p=new Map;exports.Signal=n.Signal;exports.batch=n.batch;exports.computed=n.computed;exports.effect=n.effect;exports.signal=n.signal;exports.useComputed=function(t){var e=r.useRef(t);e.current=t;return r.useMemo(function(){return n.computed(function(){return e.current()})},[])};exports.useSignal=function(t){return r.useMemo(function(){return n.signal(t)},[])};exports.useSignalEffect=function(t){var e=r.useRef(t);e.current=t;r.useEffect(function(){return n.effect(function(){return e.current()})},[])};//# sourceMappingURL=signals.js.map
1
+ var r=require("react"),n=require("react/jsx-runtime"),t=require("react/jsx-dev-runtime"),e=require("use-sync-external-store/shim/index.js"),u=require("@preact/signals-core");function o(r){return r&&"object"==typeof r&&"default"in r?r.default:r}var i=/*#__PURE__*/o(r),f=/*#__PURE__*/o(n),c=/*#__PURE__*/o(t),a=[],s=Symbol.for("react.element"),p=Symbol.for("react.memo"),l=new Map,v="function"==typeof Proxy,y={apply:function(n,t,u){var o=r.useMemo(b,a);e.useSyncExternalStore(o.subscribe,o.getSnapshot,o.getSnapshot);var i=o.updater.S();try{return n.apply(t,u)}catch(r){throw r}finally{i()}}};function x(r){return l.get(r)||function(r){if(v){var n=new Proxy(r,y);l.set(r,n);l.set(n,n);return n}var t=function(){return y.apply(r,void 0,arguments)};l.set(r,t);l.set(t,t);return t}(r)}function b(){var r,n,t=0,e=u.effect(function(){r=this});r.c=function(){t=t+1|0;if(n)n()};return{updater:r,subscribe:function(r){n=r;return function(){t=t+1|0;n=void 0;e()}},getSnapshot:function(){return t}}}function d(n){if("function"!=typeof n)return n;else return function(t,e){var o=[].slice.call(arguments,2);if("function"==typeof t&&!(t instanceof r.Component))return n.call.apply(n,[n,x(t),e].concat(o));if(t&&"object"==typeof t&&t.$$typeof===p){t.type=x(t.type);return n.call.apply(n,[n,t,e].concat(o))}if("string"==typeof t&&e)for(var i in e){var f=e[i];if("children"!==i&&f instanceof u.Signal)e[i]=f.value}return n.call.apply(n,[n,t,e].concat(o))}}var g=f,m=c;i.createElement=d(i.createElement);m.jsx&&(m.jsx=d(m.jsx));g.jsx&&(g.jsx=d(g.jsx));m.jsxs&&(m.jsxs=d(m.jsxs));g.jsxs&&(g.jsxs=d(g.jsxs));m.jsxDEV&&(m.jsxDEV=d(m.jsxDEV));g.jsxDEV&&(g.jsxDEV=d(g.jsxDEV));Object.defineProperties(u.Signal.prototype,{$$typeof:{configurable:!0,value:s},type:{configurable:!0,value:x(function(r){return r.data.value})},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});exports.Signal=u.Signal;exports.batch=u.batch;exports.computed=u.computed;exports.effect=u.effect;exports.signal=u.signal;exports.useComputed=function(n){var t=r.useRef(n);t.current=n;return r.useMemo(function(){return u.computed(function(){return t.current()})},a)};exports.useSignal=function(n){return r.useMemo(function(){return u.signal(n)},a)};exports.useSignalEffect=function(n){var t=r.useRef(n);t.current=n;r.useEffect(function(){return u.effect(function(){return t.current()})},a)};//# sourceMappingURL=signals.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"signals.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\t// @ts-ignore-next-line\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as internals,\n} from \"react\";\nimport React from \"react\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport { Effect, ReactDispatcher } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\n/**\n * Install a middleware into React.createElement to replace any Signals in props with their value.\n * @todo this likely needs to be duplicated for jsx()...\n */\nconst createElement = React.createElement;\n// @ts-ignore-next-line\nReact.createElement = function (type, props) {\n\tif (typeof type === \"string\" && props) {\n\t\tfor (let i in props) {\n\t\t\tlet v = props[i];\n\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t// createPropUpdater(props, i, v);\n\t\t\t\tprops[i] = v.value;\n\t\t\t}\n\t\t}\n\t}\n\t// @ts-ignore-next-line\n\treturn createElement.apply(this, arguments);\n};\n\n/*\n// This breaks React's controlled components implementation\nfunction createPropUpdater(props: any, prop: string, signal: Signal) {\n\tlet ref = props.ref;\n\tif (!ref) ref = props.ref = React.createRef();\n\teffect(() => {\n\t\tif (props) props[prop] = signal.value;\n\t\tlet el = ref.current;\n\t\tif (!el) return; // unsubscribe\n\t\t(el as any)[prop] = signal.value;\n\t});\n\tprops = null;\n}\n*/\n\nlet finishUpdate: (() => void) | undefined;\nconst updaterForComponent = new WeakMap<() => void, Effect>();\n\nfunction setCurrentUpdater(updater?: Effect) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate();\n\t// start tracking the new update:\n\tfinishUpdate = updater && updater._start();\n}\n\nfunction createUpdater(update: () => void) {\n\tlet updater!: Effect;\n\teffect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = update;\n\treturn updater;\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\n//@ts-ignore-next-line\nconst $$typeof = createElement(\"a\").$$typeof;\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: $$typeof },\n\ttype: { configurable: true, value: Text },\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\n// Track the current dispatcher (roughly equiv to current component impl)\nlet lock = false;\nconst UPDATE = () => ({});\nlet currentDispatcher: ReactDispatcher;\nObject.defineProperty(internals.ReactCurrentDispatcher, \"current\", {\n\tget() {\n\t\treturn currentDispatcher;\n\t},\n\tset(api) {\n\t\tcurrentDispatcher = api;\n\t\tif (lock) return;\n\t\tif (api && !isInvalidHookAccessor(api)) {\n\t\t\t// prevent re-injecting useReducer when the Dispatcher\n\t\t\t// context changes to run the reducer callback:\n\t\t\tlock = true;\n\t\t\tconst rerender = api.useReducer(UPDATE, {})[1];\n\t\t\tlock = false;\n\n\t\t\tlet updater = updaterForComponent.get(rerender);\n\t\t\tif (!updater) {\n\t\t\t\tupdater = createUpdater(rerender);\n\t\t\t\tupdaterForComponent.set(rerender, updater);\n\t\t\t} else {\n\t\t\t\tupdater._callback = rerender;\n\t\t\t}\n\t\t\tsetCurrentUpdater(updater);\n\t\t} else {\n\t\t\tsetCurrentUpdater();\n\t\t}\n\t},\n});\n\n// We inject a useReducer into every function component via CurrentDispatcher.\n// This prevents injecting into anything other than a function component render.\nconst invalidHookAccessors = new Map();\nfunction isInvalidHookAccessor(api: ReactDispatcher) {\n\tconst cached = invalidHookAccessors.get(api);\n\tif (cached !== undefined) return cached;\n\t// we only want the real implementation, not the warning ones\n\tconst invalid =\n\t\tapi.useCallback.length < 2 || /Invalid/.test(api.useCallback as any);\n\tinvalidHookAccessors.set(api, invalid);\n\treturn invalid;\n}\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), []);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), []);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(() => {\n\t\t\treturn callback.current();\n\t\t});\n\t}, []);\n}\n"],"names":["React","require","signalsCore","_interopDefaultLegacy","e","default","React__default","createElement","type","props","i","v","Signal","value","apply","this","arguments","updaterForComponent","WeakMap","updater","finishUpdate","_start","$$typeof","Object","defineProperties","prototype","configurable","_ref","data","get","ref","currentDispatcher","lock","UPDATE","defineProperty","internals","ReactCurrentDispatcher","set","api","cached","invalidHookAccessors","undefined","invalid","useCallback","length","test","isInvalidHookAccessor","rerender","useReducer","update","effect","_callback","createUpdater","setCurrentUpdater","Map","exports","batch","computed","signal","useComputed","compute","useRef","$compute","current","useMemo","useSignal","useSignalEffect","cb","callback","useEffect"],"mappings":"AAyBA,IAAAA,EAAAC,QAAA,SAAAC,EAAAD,QAAA,wBAAA,SAAAE,EAAAC,GAAA,OAAAA,GAAA,iBAAAA,GAAA,YAAAA,EAAAA,EAAAC,QAAAD,CAAA,CAAA,MAAAE,eAAAH,EAAAH,GAAmBO,EAAGP,EAAMO,cAE5BP,EAAMO,cAAgB,SAAUC,EAAMC,GACrC,GAAoB,iBAAhBD,GAA4BC,EAC/B,IAAK,IAALC,KAAAD,EAAqB,CACpB,IAAKE,EAAGF,EAAMC,GACd,GAAU,aAANA,GAAoBC,aAAaC,EAAAA,OAEpCH,EAAMC,GAAKC,EAAEE,KAEd,CAGF,OAAON,EAAcO,MAAMC,KAAMC,UACjC,EAkBD,IAAyBC,EAAG,IAAIC,QAEhC,WAA2BC,GAE1B,GAAIC,EAAcA,IAElBA,EAAeD,GAAWA,EAAQE,GAClC,CAoBD,IAAcC,EAAGf,EAAc,KAAKe,SACpCC,OAAOC,iBAAiBZ,SAAOa,UAAW,CACzCH,SAAU,CAAEI,cAAc,EAAMb,MAAOS,GACvCd,KAAM,CAAEkB,cAAc,EAAMb,MAT7B,SAAAc,GACC,OADeC,EAAAA,KACHf,KACZ,GAQAJ,MAAO,CACNiB,cAAc,EACdG,IAAG,WACF,MAAO,CAAED,KAAMb,KACf,GAEFe,IAAK,CAAEJ,cAAc,EAAMb,MAAO,QAInC,IAEIkB,EAFAC,GAAO,EACLC,EAAS,WAAA,MAAO,CAAP,CAAA,EAEfV,OAAOW,eAAeC,EAAAA,mDAAUC,uBAAwB,UAAW,CAClEP,IADkE,WAEjE,OAAOE,CACP,EACDM,IAJkE,SAI9DC,GACHP,EAAoBO,EACpB,IAAIN,EACJ,GAAIM,IAwBN,SAA+BA,GAC9B,IAAYC,EAAGC,EAAqBX,IAAIS,GACxC,QAAeG,IAAXF,EAAsB,OAAAA,EAE1B,IAAMG,EACLJ,EAAIK,YAAYC,OAAS,GAAK,UAAUC,KAAKP,EAAIK,aAClDH,EAAqBH,IAAIC,EAAKI,GAC9B,OACAA,CAAA,CAhCaI,CAAsBR,GAAM,CAGvCN,GAAO,EACP,IAAMe,EAAWT,EAAIU,WAAWf,EAAQ,CAAA,GAAI,GAC5CD,GAAO,EAEP,IAAIb,EAAUF,EAAoBY,IAAIkB,GACtC,IAAK5B,EAAS,CACbA,EAnDJ,SAAuB8B,GACtB,MACAC,EAAAA,OAAO,WACN/B,EAAUJ,IACV,GACDI,EAAQgC,EAAYF,EACpB,OAAO9B,CACP,CA4CaiC,CAAcL,GACxB9B,EAAoBoB,IAAIU,EAAU5B,EAClC,MACAA,EAAQgC,EAAYJ,EAErBM,EAAkBlC,EAClB,MACAkC,GAED,IAKF,MAA6B,IAA7BC,IA8BCC,QAAA3C,OAAAV,EAAAU,OAAA2C,QAAAC,MAAAtD,EAAAsD,MAAAD,QAAAE,SAAAvD,EAAAuD,SAAAF,QAAAL,OAAAhD,EAAAgD,OAAAK,QAAAG,OAAAxD,EAAAwD,OAAAH,QAAAI,YAfK,SAAyBC,GAC9B,MAAiBC,EAAAA,OAAOD,GACxBE,EAASC,QAAUH,EACnB,OAAOI,EAAOA,QAAC,WAAA,kBAAkB,WAAA,OAAcF,EAACC,SAAf,EAAlB,EAA6C,GAC5D,EAWAR,QAAAU,UAnBK,SAAuBpD,GAC5B,OAAcmD,EAAAA,QAAC,kBAAYN,EAAAA,OAAI7C,EAAhB,EAAwB,GACvC,EAiBA0C,QAAAW,gBATK,SAA0BC,GAC/B,IAAMC,EAAWP,EAAMA,OAACM,GACxBC,EAASL,QAAUI,EAEnBE,EAAAA,UAAU,WACT,OAAanB,EAAAA,OAAC,WACb,OAAekB,EAACL,SAChB,EACD,EAAE,GACH"}
1
+ {"version":3,"file":"signals.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tComponent,\n\ttype FunctionComponent,\n} from \"react\";\nimport React from \"react\";\nimport jsxRuntime from \"react/jsx-runtime\";\nimport jsxRuntimeDev from \"react/jsx-dev-runtime\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport type { Effect, JsxRuntimeModule } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\nconst Empty = [] as const;\nconst ReactElemType = Symbol.for(\"react.element\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactMemoType = Symbol.for(\"react.memo\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L30\nconst ProxyInstance = new Map<FunctionComponent<any>, FunctionComponent<any>>();\nconst SupportsProxy = typeof Proxy === \"function\";\n\nconst ProxyHandlers = {\n\t/**\n\t * This is a function call trap for functional components.\n\t * When this is called, we know it means React did run 'Component()',\n\t * that means we can use any hooks here to setup our effect and store.\n\t *\n\t * With the native Proxy, all other calls such as access/setting to/of properties will\n\t * be forwarded to the target Component, so we don't need to copy the Component's\n\t * own or inherited properties.\n\t *\n\t * @see https://github.com/facebook/react/blob/2d80a0cd690bb5650b6c8a6c079a87b5dc42bd15/packages/react-reconciler/src/ReactFiberHooks.old.js#L460\n\t */\n\tapply(Component: FunctionComponent, thisArg: any, argumentsList: any) {\n\t\tconst store = useMemo(createEffectStore, Empty);\n\n\t\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n\t\tconst stop = store.updater._start();\n\n\t\ttry {\n\t\t\tconst children = Component.apply(thisArg, argumentsList);\n\t\t\treturn children;\n\t\t} catch (e) {\n\t\t\t// Re-throwing promises that'll be handled by suspense\n\t\t\t// or an actual error.\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\t// Stop effects in either case before return or throw,\n\t\t\t// Otherwise the effect will leak.\n\t\t\tstop();\n\t\t}\n\t},\n};\n\nfunction ProxyFunctionalComponent(Component: FunctionComponent<any>) {\n\treturn ProxyInstance.get(Component) || WrapWithProxy(Component);\n}\nfunction WrapWithProxy(Component: FunctionComponent<any>) {\n\tif (SupportsProxy) {\n\t\tconst ProxyComponent = new Proxy(Component, ProxyHandlers);\n\n\t\tProxyInstance.set(Component, ProxyComponent);\n\t\tProxyInstance.set(ProxyComponent, ProxyComponent);\n\n\t\treturn ProxyComponent;\n\t}\n\n\t/**\n\t * Emulate a Proxy if environment doesn't support it.\n\t *\n\t * @TODO - unlike Proxy, it's not possible to access the type/Component's\n\t * static properties this way. Not sure if we want to copy all statics here.\n\t * Omitting this for now.\n\t *\n\t * @example - works with Proxy, doesn't with wrapped function.\n\t * ```\n\t * const el = <SomeFunctionalComponent />\n\t * el.type.someOwnOrInheritedProperty;\n\t * el.type.defaultProps;\n\t * ```\n\t */\n\tconst WrappedComponent = function () {\n\t\treturn ProxyHandlers.apply(Component, undefined, arguments);\n\t};\n\tProxyInstance.set(Component, WrappedComponent);\n\tProxyInstance.set(WrappedComponent, WrappedComponent);\n\n\treturn WrappedComponent;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a '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 component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,\n * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore\n * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n */\nfunction createEffectStore() {\n\tlet updater!: Effect;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\tupdater,\n\t\tsubscribe(onStoreChange: () => void) {\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};\n}\n\nfunction 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 === \"function\" && !(type instanceof Component)) {\n\t\t\treturn jsx.call(jsx, ProxyFunctionalComponent(type), props, ...rest);\n\t\t}\n\n\t\tif (type && typeof type === \"object\" && type.$$typeof === ReactMemoType) {\n\t\t\ttype.type = ProxyFunctionalComponent(type.type);\n\t\t\treturn jsx.call(jsx, type, props, ...rest);\n\t\t}\n\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 JsxPro: JsxRuntimeModule = jsxRuntime;\nconst JsxDev: JsxRuntimeModule = jsxRuntimeDev;\n\n/**\n * createElement _may_ be called by jsx runtime as a fallback in certain cases,\n * so we need to wrap it regardless.\n *\n * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't\n * include both, so one of them will be set with `undefined` values.\n */\nReact.createElement = WrapJsx(React.createElement);\nJsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));\nJsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));\nJsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));\nJsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));\nJsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));\nJsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: ProxyFunctionalComponent(Text) },\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 useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => 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(() => {\n\t\t\treturn callback.current();\n\t\t});\n\t}, Empty);\n}\n"],"names":["Empty","Symbol","ReactMemoType","ProxyInstance","Map","SupportsProxy","Proxy","apply","Component","thisArg","argumentsList","useMemo","createEffectStore","useSyncExternalStore","store","subscribe","getSnapshot","updater","_start","e","stop","ProxyFunctionalComponent","get","ProxyComponent","ProxyHandlers","set","WrappedComponent","undefined","arguments","WrapWithProxy","onChangeNotifyReact","version","unsubscribe","effect","this","_callback","onStoreChange","WrapJsx","jsx","type","props","slice","call","rest","$$typeof","i","v","Signal","value","concat","JsxPro","jsxRuntime","JsxDev","jsxRuntimeDev","React","createElement","jsxs","jsxDEV","Object","defineProperties","prototype","configurable","ReactElemType","_ref","data","ref","exports","signalsCore","batch","computed","signal","useComputed","compute","$compute","useRef","current","useSignal","useSignalEffect","cb","callback","useEffect"],"mappings":"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"}
@@ -1 +1 @@
1
- !function(n,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("react"),require("@preact/signals-core")):"function"==typeof define&&define.amd?define(["exports","react","@preact/signals-core"],e):e((n||self).reactSignals={},n.react,n.signalsCore)}(this,function(n,e,r){function t(n){return n&&"object"==typeof n&&"default"in n?n.default:n}var i,u=/*#__PURE__*/t(e),f=u.createElement;u.createElement=function(n,e){if("string"==typeof n&&e)for(var t in e){var i=e[t];if("children"!==t&&i instanceof r.Signal)e[t]=i.value}return f.apply(this,arguments)};var o=new WeakMap;function c(n){if(i)i();i=n&&n.S()}var a=f("a").$$typeof;Object.defineProperties(r.Signal.prototype,{$$typeof:{configurable:!0,value:a},type:{configurable:!0,value:function(n){return n.data.value}},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});var l,s=!1,v=function(){return{}};Object.defineProperty(e.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher,"current",{get:function(){return l},set:function(n){l=n;if(!s)if(n&&!function(n){var e=p.get(n);if(void 0!==e)return e;var r=n.useCallback.length<2||/Invalid/.test(n.useCallback);p.set(n,r);return r}(n)){s=!0;var e=n.useReducer(v,{})[1];s=!1;var t=o.get(e);if(!t){t=function(n){var e;r.effect(function(){e=this});e.c=n;return e}(e);o.set(e,t)}else t.c=e;c(t)}else c()}});var p=new Map;n.Signal=r.Signal;n.batch=r.batch;n.computed=r.computed;n.effect=r.effect;n.signal=r.signal;n.useComputed=function(n){var t=e.useRef(n);t.current=n;return e.useMemo(function(){return r.computed(function(){return t.current()})},[])};n.useSignal=function(n){return e.useMemo(function(){return r.signal(n)},[])};n.useSignalEffect=function(n){var t=e.useRef(n);t.current=n;e.useEffect(function(){return r.effect(function(){return t.current()})},[])}});//# sourceMappingURL=signals.min.js.map
1
+ !function(n,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("react"),require("react/jsx-runtime"),require("react/jsx-dev-runtime"),require("use-sync-external-store/shim/index.js"),require("@preact/signals-core")):"function"==typeof define&&define.amd?define(["exports","react","react/jsx-runtime","react/jsx-dev-runtime","use-sync-external-store/shim/index.js","@preact/signals-core"],e):e((n||self).reactSignals={},n.react,n.jsxRuntime,n.jsxRuntimeDev,n.index_js,n.signalsCore)}(this,function(n,e,r,t,u,i){function o(n){return n&&"object"==typeof n&&"default"in n?n.default:n}var f=/*#__PURE__*/o(e),c=/*#__PURE__*/o(r),a=/*#__PURE__*/o(t),s=[],l=Symbol.for("react.element"),p=Symbol.for("react.memo"),y=new Map,v="function"==typeof Proxy,d={apply:function(n,r,t){var i=e.useMemo(x,s);u.useSyncExternalStore(i.subscribe,i.getSnapshot,i.getSnapshot);var o=i.updater.S();try{return n.apply(r,t)}catch(n){throw n}finally{o()}}};function b(n){return y.get(n)||function(n){if(v){var e=new Proxy(n,d);y.set(n,e);y.set(e,e);return e}var r=function(){return d.apply(n,void 0,arguments)};y.set(n,r);y.set(r,r);return r}(n)}function x(){var n,e,r=0,t=i.effect(function(){n=this});n.c=function(){r=r+1|0;if(e)e()};return{updater:n,subscribe:function(n){e=n;return function(){r=r+1|0;e=void 0;t()}},getSnapshot:function(){return r}}}function m(n){if("function"!=typeof n)return n;else return function(r,t){var u=[].slice.call(arguments,2);if("function"==typeof r&&!(r instanceof e.Component))return n.call.apply(n,[n,b(r),t].concat(u));if(r&&"object"==typeof r&&r.$$typeof===p){r.type=b(r.type);return n.call.apply(n,[n,r,t].concat(u))}if("string"==typeof r&&t)for(var o in t){var f=t[o];if("children"!==o&&f instanceof i.Signal)t[o]=f.value}return n.call.apply(n,[n,r,t].concat(u))}}var g=c,h=a;f.createElement=m(f.createElement);h.jsx&&(h.jsx=m(h.jsx));g.jsx&&(g.jsx=m(g.jsx));h.jsxs&&(h.jsxs=m(h.jsxs));g.jsxs&&(g.jsxs=m(g.jsxs));h.jsxDEV&&(h.jsxDEV=m(h.jsxDEV));g.jsxDEV&&(g.jsxDEV=m(g.jsxDEV));Object.defineProperties(i.Signal.prototype,{$$typeof:{configurable:!0,value:l},type:{configurable:!0,value:b(function(n){return n.data.value})},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});n.Signal=i.Signal;n.batch=i.batch;n.computed=i.computed;n.effect=i.effect;n.signal=i.signal;n.useComputed=function(n){var r=e.useRef(n);r.current=n;return e.useMemo(function(){return i.computed(function(){return r.current()})},s)};n.useSignal=function(n){return e.useMemo(function(){return i.signal(n)},s)};n.useSignalEffect=function(n){var r=e.useRef(n);r.current=n;e.useEffect(function(){return i.effect(function(){return r.current()})},s)}});//# sourceMappingURL=signals.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"signals.min.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\t// @ts-ignore-next-line\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as internals,\n} from \"react\";\nimport React from \"react\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport { Effect, ReactDispatcher } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\n/**\n * Install a middleware into React.createElement to replace any Signals in props with their value.\n * @todo this likely needs to be duplicated for jsx()...\n */\nconst createElement = React.createElement;\n// @ts-ignore-next-line\nReact.createElement = function (type, props) {\n\tif (typeof type === \"string\" && props) {\n\t\tfor (let i in props) {\n\t\t\tlet v = props[i];\n\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t// createPropUpdater(props, i, v);\n\t\t\t\tprops[i] = v.value;\n\t\t\t}\n\t\t}\n\t}\n\t// @ts-ignore-next-line\n\treturn createElement.apply(this, arguments);\n};\n\n/*\n// This breaks React's controlled components implementation\nfunction createPropUpdater(props: any, prop: string, signal: Signal) {\n\tlet ref = props.ref;\n\tif (!ref) ref = props.ref = React.createRef();\n\teffect(() => {\n\t\tif (props) props[prop] = signal.value;\n\t\tlet el = ref.current;\n\t\tif (!el) return; // unsubscribe\n\t\t(el as any)[prop] = signal.value;\n\t});\n\tprops = null;\n}\n*/\n\nlet finishUpdate: (() => void) | undefined;\nconst updaterForComponent = new WeakMap<() => void, Effect>();\n\nfunction setCurrentUpdater(updater?: Effect) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate();\n\t// start tracking the new update:\n\tfinishUpdate = updater && updater._start();\n}\n\nfunction createUpdater(update: () => void) {\n\tlet updater!: Effect;\n\teffect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = update;\n\treturn updater;\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\n//@ts-ignore-next-line\nconst $$typeof = createElement(\"a\").$$typeof;\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: $$typeof },\n\ttype: { configurable: true, value: Text },\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\n// Track the current dispatcher (roughly equiv to current component impl)\nlet lock = false;\nconst UPDATE = () => ({});\nlet currentDispatcher: ReactDispatcher;\nObject.defineProperty(internals.ReactCurrentDispatcher, \"current\", {\n\tget() {\n\t\treturn currentDispatcher;\n\t},\n\tset(api) {\n\t\tcurrentDispatcher = api;\n\t\tif (lock) return;\n\t\tif (api && !isInvalidHookAccessor(api)) {\n\t\t\t// prevent re-injecting useReducer when the Dispatcher\n\t\t\t// context changes to run the reducer callback:\n\t\t\tlock = true;\n\t\t\tconst rerender = api.useReducer(UPDATE, {})[1];\n\t\t\tlock = false;\n\n\t\t\tlet updater = updaterForComponent.get(rerender);\n\t\t\tif (!updater) {\n\t\t\t\tupdater = createUpdater(rerender);\n\t\t\t\tupdaterForComponent.set(rerender, updater);\n\t\t\t} else {\n\t\t\t\tupdater._callback = rerender;\n\t\t\t}\n\t\t\tsetCurrentUpdater(updater);\n\t\t} else {\n\t\t\tsetCurrentUpdater();\n\t\t}\n\t},\n});\n\n// We inject a useReducer into every function component via CurrentDispatcher.\n// This prevents injecting into anything other than a function component render.\nconst invalidHookAccessors = new Map();\nfunction isInvalidHookAccessor(api: ReactDispatcher) {\n\tconst cached = invalidHookAccessors.get(api);\n\tif (cached !== undefined) return cached;\n\t// we only want the real implementation, not the warning ones\n\tconst invalid =\n\t\tapi.useCallback.length < 2 || /Invalid/.test(api.useCallback as any);\n\tinvalidHookAccessors.set(api, invalid);\n\treturn invalid;\n}\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), []);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), []);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(() => {\n\t\t\treturn callback.current();\n\t\t});\n\t}, []);\n}\n"],"names":["g","f","exports","module","require","define","amd","globalThis","self","reactSignals","react","signalsCore","this","React","_interopDefaultLegacy","e","default","React__default","createElement","type","props","i","v","Signal","value","apply","arguments","updaterForComponent","WeakMap","updater","finishUpdate","_start","$$typeof","Object","defineProperties","prototype","configurable","_ref","data","get","ref","currentDispatcher","lock","UPDATE","defineProperty","internals","ReactCurrentDispatcher","set","api","cached","invalidHookAccessors","undefined","invalid","useCallback","length","test","isInvalidHookAccessor","rerender","useReducer","update","effect","_callback","createUpdater","setCurrentUpdater","Map","batch","computed","signal","useComputed","compute","useRef","$compute","current","useMemo","useSignal","useSignalEffect","cb","callback","useEffect"],"mappings":"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"}
1
+ {"version":3,"file":"signals.min.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tComponent,\n\ttype FunctionComponent,\n} from \"react\";\nimport React from \"react\";\nimport jsxRuntime from \"react/jsx-runtime\";\nimport jsxRuntimeDev from \"react/jsx-dev-runtime\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport type { Effect, JsxRuntimeModule } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\nconst Empty = [] as const;\nconst ReactElemType = Symbol.for(\"react.element\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactMemoType = Symbol.for(\"react.memo\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L30\nconst ProxyInstance = new Map<FunctionComponent<any>, FunctionComponent<any>>();\nconst SupportsProxy = typeof Proxy === \"function\";\n\nconst ProxyHandlers = {\n\t/**\n\t * This is a function call trap for functional components.\n\t * When this is called, we know it means React did run 'Component()',\n\t * that means we can use any hooks here to setup our effect and store.\n\t *\n\t * With the native Proxy, all other calls such as access/setting to/of properties will\n\t * be forwarded to the target Component, so we don't need to copy the Component's\n\t * own or inherited properties.\n\t *\n\t * @see https://github.com/facebook/react/blob/2d80a0cd690bb5650b6c8a6c079a87b5dc42bd15/packages/react-reconciler/src/ReactFiberHooks.old.js#L460\n\t */\n\tapply(Component: FunctionComponent, thisArg: any, argumentsList: any) {\n\t\tconst store = useMemo(createEffectStore, Empty);\n\n\t\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n\t\tconst stop = store.updater._start();\n\n\t\ttry {\n\t\t\tconst children = Component.apply(thisArg, argumentsList);\n\t\t\treturn children;\n\t\t} catch (e) {\n\t\t\t// Re-throwing promises that'll be handled by suspense\n\t\t\t// or an actual error.\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\t// Stop effects in either case before return or throw,\n\t\t\t// Otherwise the effect will leak.\n\t\t\tstop();\n\t\t}\n\t},\n};\n\nfunction ProxyFunctionalComponent(Component: FunctionComponent<any>) {\n\treturn ProxyInstance.get(Component) || WrapWithProxy(Component);\n}\nfunction WrapWithProxy(Component: FunctionComponent<any>) {\n\tif (SupportsProxy) {\n\t\tconst ProxyComponent = new Proxy(Component, ProxyHandlers);\n\n\t\tProxyInstance.set(Component, ProxyComponent);\n\t\tProxyInstance.set(ProxyComponent, ProxyComponent);\n\n\t\treturn ProxyComponent;\n\t}\n\n\t/**\n\t * Emulate a Proxy if environment doesn't support it.\n\t *\n\t * @TODO - unlike Proxy, it's not possible to access the type/Component's\n\t * static properties this way. Not sure if we want to copy all statics here.\n\t * Omitting this for now.\n\t *\n\t * @example - works with Proxy, doesn't with wrapped function.\n\t * ```\n\t * const el = <SomeFunctionalComponent />\n\t * el.type.someOwnOrInheritedProperty;\n\t * el.type.defaultProps;\n\t * ```\n\t */\n\tconst WrappedComponent = function () {\n\t\treturn ProxyHandlers.apply(Component, undefined, arguments);\n\t};\n\tProxyInstance.set(Component, WrappedComponent);\n\tProxyInstance.set(WrappedComponent, WrappedComponent);\n\n\treturn WrappedComponent;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a '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 component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,\n * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore\n * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n */\nfunction createEffectStore() {\n\tlet updater!: Effect;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\tupdater,\n\t\tsubscribe(onStoreChange: () => void) {\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};\n}\n\nfunction 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 === \"function\" && !(type instanceof Component)) {\n\t\t\treturn jsx.call(jsx, ProxyFunctionalComponent(type), props, ...rest);\n\t\t}\n\n\t\tif (type && typeof type === \"object\" && type.$$typeof === ReactMemoType) {\n\t\t\ttype.type = ProxyFunctionalComponent(type.type);\n\t\t\treturn jsx.call(jsx, type, props, ...rest);\n\t\t}\n\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 JsxPro: JsxRuntimeModule = jsxRuntime;\nconst JsxDev: JsxRuntimeModule = jsxRuntimeDev;\n\n/**\n * createElement _may_ be called by jsx runtime as a fallback in certain cases,\n * so we need to wrap it regardless.\n *\n * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't\n * include both, so one of them will be set with `undefined` values.\n */\nReact.createElement = WrapJsx(React.createElement);\nJsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));\nJsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));\nJsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));\nJsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));\nJsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));\nJsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: ProxyFunctionalComponent(Text) },\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 useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => 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(() => {\n\t\t\treturn callback.current();\n\t\t});\n\t}, Empty);\n}\n"],"names":["Empty","Symbol","ReactMemoType","ProxyInstance","Map","SupportsProxy","Proxy","apply","Component","thisArg","argumentsList","useMemo","createEffectStore","useSyncExternalStore","store","subscribe","getSnapshot","updater","_start","e","stop","ProxyFunctionalComponent","get","ProxyComponent","ProxyHandlers","set","WrappedComponent","undefined","arguments","WrapWithProxy","onChangeNotifyReact","version","unsubscribe","effect","this","_callback","onStoreChange","WrapJsx","jsx","type","props","slice","call","rest","$$typeof","i","v","Signal","value","concat","JsxPro","jsxRuntime","JsxDev","jsxRuntimeDev","React","createElement","jsxs","jsxDEV","Object","defineProperties","prototype","configurable","ReactElemType","_ref","data","ref","exports","signalsCore","batch","computed","signal","useComputed","compute","$compute","useRef","current","useSignal","useSignalEffect","cb","callback","useEffect"],"mappings":"usBAuBWA,EAAG,KACQC,WAAW,iBACdC,EAAGD,OAAM,IAAK,cAC3BE,EAAgB,IAAIC,IACPC,EAAoB,mBAAjBC,QAEA,CAYrBC,MAZqB,SAYfC,EAA8BC,EAAcC,GACjD,MAAcC,EAAAA,QAAQC,EAAmBZ,GAEzCa,EAAoBA,qBAACC,EAAMC,UAAWD,EAAME,YAAaF,EAAME,aAE/D,MAAaF,EAAMG,QAAQC,IAE3B,IAEC,OADiBV,EAAUD,MAAME,EAASC,EAU1C,CARC,MAAOS,GAGR,MAAMA,CACN,CAPD,QAUCC,GACA,CACD,GAGF,SAASC,EAAyBb,GACjC,SAAqBc,IAAId,IAE1B,SAAuBA,GACtB,GAAIH,EAAe,CAClB,IAAMkB,EAAiB,IAAIjB,MAAME,EAAWgB,GAE5CrB,EAAcsB,IAAIjB,EAAWe,GAC7BpB,EAAcsB,IAAIF,EAAgBA,GAElC,OACAA,CAAA,CAgBD,IAAsBG,EAAG,WACxB,OAAoBF,EAACjB,MAAMC,OAAWmB,EAAWC,UACjD,EACDzB,EAAcsB,IAAIjB,EAAWkB,GAC7BvB,EAAcsB,IAAIC,EAAkBA,GAEpC,OAAOA,CACP,CAjCuCG,CAAcrB,EACrD,CA+CD,SAASI,IACR,IAAAK,EAEAa,EADIC,EAAU,EAGCC,EAAGC,SAAO,WACxBhB,EAAUiB,IACV,GACDjB,EAAQkB,EAAY,WACnBJ,EAAWA,EAAU,EAAK,EAC1B,GAAID,EAAqBA,GACzB,EAED,MAAO,CACNb,QAAAA,EACAF,UAAUqB,SAAAA,GACTN,EAAsBM,EAEtB,OAAO,WAWNL,EAAWA,EAAU,EAAK,EAC1BD,OAAsBH,EACtBK,GACA,CACD,EACDhB,YArBM,WAsBL,OAAOe,CACP,EAEF,CAED,SAAAM,EAAoBC,GACnB,GAAmB,mBAARA,EAAoB,OAAAA,OAE/B,OAAO,SAAUC,EAAWC,GAA0B,MACrD,GAAAC,MAAAC,KAAAd,UAAA,GAAA,GAAoB,mBAAhBW,KAAgCA,aAAF/B,EAAAA,WACjC,SAAWkC,KAAJJ,MAAAA,EAASA,CAAAA,EAAKjB,EAAyBkB,GAAOC,GAAUG,OAAAA,IAGhE,GAAIJ,GAAwB,oBAAYA,EAAKK,WAAa1C,EAAe,CACxEqC,EAAKA,KAAOlB,EAAyBkB,EAAKA,MAC1C,SAAWG,WAAJJ,EAAG,CAAMA,EAAKC,EAAMC,GAAUG,OAAAA,GACrC,CAED,GAAoB,iBAAhBJ,GAA4BC,EAC/B,IAAK,IAALK,OAAqB,CACpB,IAAKC,EAAGN,EAAMK,GACd,GAAU,aAANA,GAAoBC,aAAaC,EAAAA,OACpCP,EAAMK,GAAKC,EAAEE,KAEd,CAGF,OAAOV,EAAII,WAAJJ,EAAG,CAAMA,EAAKC,EAAMC,GAAjBS,OAA2BN,GACzB,CACb,CAED,IAAMO,EAA2BC,EACrBC,EAAqBC,EASjCC,EAAMC,cAAgBlB,EAAQiB,EAAMC,eACpCH,EAAOd,MAAgBc,EAAOd,IAAMD,EAAQe,EAAOd,MACnDY,EAAOZ,MAAgBY,EAAOZ,IAAMD,EAAQa,EAAOZ,MACnDc,EAAOI,OAAgBJ,EAAOI,KAAOnB,EAAQe,EAAOI,OACpDN,EAAOM,OAAgBN,EAAOM,KAAOnB,EAAQa,EAAOM,OACpDJ,EAAOK,SAAgBL,EAAOK,OAASpB,EAAQe,EAAOK,SACtDP,EAAOO,SAAgBP,EAAOO,OAASpB,EAAQa,EAAOO,SAUtDC,OAAOC,iBAAiBZ,EAAAA,OAAOa,UAAW,CACzChB,SAAU,CAAEiB,cAAc,EAAMb,MAAOc,GACvCvB,KAAM,CAAEsB,cAAc,EAAMb,MAAO3B,EAPpC,SAAA0C,GACC,OADuCA,EAAxBC,KACHhB,KACZ,IAMAR,MAAO,CACNqB,cAAc,EACdvC,eACC,MAAO,CAAE0C,KAAM9B,KACf,GAEF+B,IAAK,CAAEJ,cAAc,EAAMb,MAAO,QAsBlCkB,EAAAnB,OAAAoB,EAAApB,OAAAmB,EAAAE,MAAAD,EAAAC,MAAAF,EAAAG,SAAAF,EAAAE,SAAAH,EAAAjC,OAAAkC,EAAAlC,OAAAiC,EAAAI,OAAAH,EAAAG,OAAAJ,EAAAK,YAfK,SAAyBC,GAC9B,IAAcC,EAAGC,EAAMA,OAACF,GACxBC,EAASE,QAAUH,EACnB,OAAO7D,UAAQ,WAAM0D,OAAAA,EAAAA,SAAY,WAAA,OAAcI,EAACE,SAAf,EAAlB,EAA6C3E,EAC5D,EAWAkE,EAAAU,UAnBK,SAAuB5B,GAC5B,SAAcrC,QAAC,WAAA,gBAAgBqC,EAAhB,EAAwBhD,EACvC,EAiBAkE,EAAAW,gBATeA,SAAgBC,GAC/B,IAAMC,EAAWL,EAAMA,OAACI,GACxBC,EAASJ,QAAUG,EAEnBE,EAAAA,UAAU,WACT,OAAO/C,EAAAA,OAAO,WACb,OAAO8C,EAASJ,SAChB,EACD,EAAE3E,EACH,CAAA"}
package/dist/signals.mjs CHANGED
@@ -1 +1 @@
1
- import t,{__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as n,useMemo as e,useRef as o,useEffect as r}from"react";import{Signal as c,effect as i,signal as f,computed as u}from"@preact/signals-core";export{Signal,batch,computed,effect,signal}from"@preact/signals-core";const a=t.createElement;t.createElement=function(t,n){if("string"==typeof t&&n)for(let t in n){let e=n[t];if("children"!==t&&e instanceof c)n[t]=e.value}return a.apply(this,arguments)};let l;const s=new WeakMap;function p(t){if(l)l();l=t&&t.S()}const g=a("a").$$typeof;Object.defineProperties(c.prototype,{$$typeof:{configurable:!0,value:g},type:{configurable:!0,value:function({data:t}){return t.value}},props:{configurable:!0,get(){return{data:this}}},ref:{configurable:!0,value:null}});let b=!1;const d=()=>({});let m;Object.defineProperty(n.ReactCurrentDispatcher,"current",{get:()=>m,set(t){m=t;if(!b)if(t&&!function(t){const n=h.get(t);if(void 0!==n)return n;const e=t.useCallback.length<2||/Invalid/.test(t.useCallback);h.set(t,e);return e}(t)){b=!0;const n=t.useReducer(d,{})[1];b=!1;let e=s.get(n);if(!e){e=function(t){let n;i(function(){n=this});n.c=t;return n}(n);s.set(n,e)}else e.c=n;p(e)}else p()}});const h=new Map;function v(t){return e(()=>f(t),[])}function y(t){const n=o(t);n.current=t;return e(()=>u(()=>n.current()),[])}function j(t){const n=o(t);n.current=t;r(()=>i(()=>n.current()),[])}export{y as useComputed,v as useSignal,j as useSignalEffect};//# sourceMappingURL=signals.mjs.map
1
+ import t,{Component as n,useMemo as e,useRef as r,useEffect as o}from"react";import i from"react/jsx-runtime";import c from"react/jsx-dev-runtime";import{useSyncExternalStore as f}from"use-sync-external-store/shim/index.js";import{Signal as u,signal as a,computed as s,effect as l}from"@preact/signals-core";export{Signal,batch,computed,effect,signal}from"@preact/signals-core";const p=[],m=Symbol.for("react.element"),y=Symbol.for("react.memo"),b=new Map,g="function"==typeof Proxy,d={apply(t,n,r){const o=e(x,p);f(o.subscribe,o.getSnapshot,o.getSnapshot);const i=o.updater.S();try{return t.apply(n,r)}catch(t){throw t}finally{i()}}};function h(t){return b.get(t)||function(t){if(g){const n=new Proxy(t,d);b.set(t,n);b.set(n,n);return n}const n=function(){return d.apply(t,void 0,arguments)};b.set(t,n);b.set(n,n);return n}(t)}function x(){let t,n,e=0,r=l(function(){t=this});t.c=function(){e=e+1|0;if(n)n()};return{updater:t,subscribe(t){n=t;return function(){e=e+1|0;n=void 0;r()}},getSnapshot:()=>e}}function v(t){if("function"!=typeof t)return t;else return function(e,r,...o){if("function"==typeof e&&!(e instanceof n))return t.call(t,h(e),r,...o);if(e&&"object"==typeof e&&e.$$typeof===y){e.type=h(e.type);return t.call(t,e,r,...o)}if("string"==typeof e&&r)for(let t in r){let n=r[t];if("children"!==t&&n instanceof u)r[t]=n.value}return t.call(t,e,r,...o)}}const j=i,S=c;t.createElement=v(t.createElement);S.jsx&&(S.jsx=v(S.jsx));j.jsx&&(j.jsx=v(j.jsx));S.jsxs&&(S.jsxs=v(S.jsxs));j.jsxs&&(j.jsxs=v(j.jsxs));S.jsxDEV&&(S.jsxDEV=v(S.jsxDEV));j.jsxDEV&&(j.jsxDEV=v(j.jsxDEV));Object.defineProperties(u.prototype,{$$typeof:{configurable:!0,value:m},type:{configurable:!0,value:h(function({data:t}){return t.value})},props:{configurable:!0,get(){return{data:this}}},ref:{configurable:!0,value:null}});function useSignal(t){return e(()=>a(t),p)}function useComputed(t){const n=r(t);n.current=t;return e(()=>s(()=>n.current()),p)}function useSignalEffect(t){const n=r(t);n.current=t;o(()=>l(()=>n.current()),p)}export{useComputed,useSignal,useSignalEffect};//# sourceMappingURL=signals.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"signals.mjs","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\t// @ts-ignore-next-line\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as internals,\n} from \"react\";\nimport React from \"react\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport { Effect, ReactDispatcher } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\n/**\n * Install a middleware into React.createElement to replace any Signals in props with their value.\n * @todo this likely needs to be duplicated for jsx()...\n */\nconst createElement = React.createElement;\n// @ts-ignore-next-line\nReact.createElement = function (type, props) {\n\tif (typeof type === \"string\" && props) {\n\t\tfor (let i in props) {\n\t\t\tlet v = props[i];\n\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t// createPropUpdater(props, i, v);\n\t\t\t\tprops[i] = v.value;\n\t\t\t}\n\t\t}\n\t}\n\t// @ts-ignore-next-line\n\treturn createElement.apply(this, arguments);\n};\n\n/*\n// This breaks React's controlled components implementation\nfunction createPropUpdater(props: any, prop: string, signal: Signal) {\n\tlet ref = props.ref;\n\tif (!ref) ref = props.ref = React.createRef();\n\teffect(() => {\n\t\tif (props) props[prop] = signal.value;\n\t\tlet el = ref.current;\n\t\tif (!el) return; // unsubscribe\n\t\t(el as any)[prop] = signal.value;\n\t});\n\tprops = null;\n}\n*/\n\nlet finishUpdate: (() => void) | undefined;\nconst updaterForComponent = new WeakMap<() => void, Effect>();\n\nfunction setCurrentUpdater(updater?: Effect) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate();\n\t// start tracking the new update:\n\tfinishUpdate = updater && updater._start();\n}\n\nfunction createUpdater(update: () => void) {\n\tlet updater!: Effect;\n\teffect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = update;\n\treturn updater;\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\n//@ts-ignore-next-line\nconst $$typeof = createElement(\"a\").$$typeof;\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: $$typeof },\n\ttype: { configurable: true, value: Text },\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\n// Track the current dispatcher (roughly equiv to current component impl)\nlet lock = false;\nconst UPDATE = () => ({});\nlet currentDispatcher: ReactDispatcher;\nObject.defineProperty(internals.ReactCurrentDispatcher, \"current\", {\n\tget() {\n\t\treturn currentDispatcher;\n\t},\n\tset(api) {\n\t\tcurrentDispatcher = api;\n\t\tif (lock) return;\n\t\tif (api && !isInvalidHookAccessor(api)) {\n\t\t\t// prevent re-injecting useReducer when the Dispatcher\n\t\t\t// context changes to run the reducer callback:\n\t\t\tlock = true;\n\t\t\tconst rerender = api.useReducer(UPDATE, {})[1];\n\t\t\tlock = false;\n\n\t\t\tlet updater = updaterForComponent.get(rerender);\n\t\t\tif (!updater) {\n\t\t\t\tupdater = createUpdater(rerender);\n\t\t\t\tupdaterForComponent.set(rerender, updater);\n\t\t\t} else {\n\t\t\t\tupdater._callback = rerender;\n\t\t\t}\n\t\t\tsetCurrentUpdater(updater);\n\t\t} else {\n\t\t\tsetCurrentUpdater();\n\t\t}\n\t},\n});\n\n// We inject a useReducer into every function component via CurrentDispatcher.\n// This prevents injecting into anything other than a function component render.\nconst invalidHookAccessors = new Map();\nfunction isInvalidHookAccessor(api: ReactDispatcher) {\n\tconst cached = invalidHookAccessors.get(api);\n\tif (cached !== undefined) return cached;\n\t// we only want the real implementation, not the warning ones\n\tconst invalid =\n\t\tapi.useCallback.length < 2 || /Invalid/.test(api.useCallback as any);\n\tinvalidHookAccessors.set(api, invalid);\n\treturn invalid;\n}\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), []);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), []);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(() => {\n\t\t\treturn callback.current();\n\t\t});\n\t}, []);\n}\n"],"names":["createElement","React","type","props","i","v","Signal","value","apply","this","arguments","finishUpdate","updaterForComponent","WeakMap","setCurrentUpdater","updater","_start","$$typeof","Object","defineProperties","prototype","configurable","data","get","ref","UPDATE","currentDispatcher","defineProperty","internals","ReactCurrentDispatcher","set","api","lock","cached","invalidHookAccessors","undefined","invalid","useCallback","length","test","isInvalidHookAccessor","useReducer","rerender","update","effect","_callback","createUpdater","Map","useSignal","signal","useComputed","compute","$compute","useRef","current","useMemo","computed","useSignalEffect","cb","callback","useEffect"],"mappings":"gRAyBA,MAAmBA,EAAGC,EAAMD,cAE5BC,EAAMD,cAAgB,SAAUE,EAAMC,GACrC,GAAoB,iBAATD,GAAqBC,EAC/B,IAAK,IAAIC,KAAKD,EAAO,CACpB,IAAIE,EAAIF,EAAMC,GACd,GAAU,aAANA,GAAoBC,aAAxBC,EAECH,EAAMC,GAAKC,EAAEE,KAEd,CAGF,OAAoBP,EAACQ,MAAMC,KAAMC,UACjC,EAiBD,IAAAC,EACA,MAAMC,EAAsB,IAA5BC,QAEA,SAAAC,EAA2BC,GAE1B,GAAIJ,EAAcA,IAElBA,EAAeI,GAAWA,EAAQC,GAClC,CAoBD,MAAMC,EAAWjB,EAAc,KAAKiB,SACpCC,OAAOC,iBAAiBb,EAAOc,UAAW,CACzCH,SAAU,CAAEI,cAAc,EAAMd,MAAOU,GACvCf,KAAM,CAAEmB,cAAc,EAAMd,MAT7B,UAAce,KAAEA,IACf,OAAOA,EAAKf,KACZ,GAQAJ,MAAO,CACNkB,cAAc,EACdE,MACC,MAAO,CAAED,KAAMb,KACf,GAEFe,IAAK,CAAEH,cAAc,EAAMd,MAAO,QAInC,OAAW,EACX,MAAYkB,EAAG,KAAO,CAAP,GACf,IAAAC,EACAR,OAAOS,eAAeC,EAAUC,uBAAwB,UAAW,CAClEN,IAAG,IAEFG,EACDI,IAAIC,GACHL,EAAoBK,EACpB,IAAIC,EACJ,GAAID,IAwBN,SAA+BA,GAC9B,MAAYE,EAAGC,EAAqBX,IAAIQ,GACxC,QAAeI,IAAXF,EAAsB,OAAAA,EAE1B,MAAMG,EACLL,EAAIM,YAAYC,OAAS,GAAK,UAAUC,KAAKR,EAAIM,aAClDH,EAAqBJ,IAAIC,EAAKK,GAC9B,OACAA,CAAA,CAhCaI,CAAsBT,GAAM,CAGvCC,GAAO,EACP,QAAiBD,EAAIU,WAAWhB,EAAQ,CAAvB,GAA2B,GAC5CO,GAAO,EAEP,IAAWjB,EAAGH,EAAoBW,IAAImB,GACtC,IAAK3B,EAAS,CACbA,EAnDJ,SAAuB4B,GACtB,IAAA5B,EACA6B,EAAO,WACN7B,EAAUN,IACV,GACDM,EAAQ8B,EAAYF,EACpB,OACA5B,CAAA,CA4Ca+B,CAAcJ,GACxB9B,EAAoBkB,IAAIY,EAAU3B,EAClC,MACAA,EAAQ8B,EAAYH,EAErB5B,EAAkBC,EAClB,MACAD,GAED,IAKF,MAAMoB,EAAuB,IAA7Ba,IAWM,SAAAC,EAAuBzC,GAC5B,SAAe,IAAM0C,EAAU1C,GAAQ,GACvC,CAEe2C,SAAAA,EAAeC,GAC9B,MAAcC,EAAGC,EAAOF,GACxBC,EAASE,QAAUH,EACnB,OAAcI,EAAC,IAAMC,EAAY,IAAMJ,EAASE,WAAY,GAC5D,CAEK,SAAAG,EAA0BC,GAC/B,MAAMC,EAAWN,EAAOK,GACxBC,EAASL,QAAUI,EAEnBE,EAAU,IACIhB,EAAC,IACEe,EAACL,WAEf,GACH,QAAAJ,iBAAAF,eAAAS"}
1
+ {"version":3,"file":"signals.mjs","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tComponent,\n\ttype FunctionComponent,\n} from \"react\";\nimport React from \"react\";\nimport jsxRuntime from \"react/jsx-runtime\";\nimport jsxRuntimeDev from \"react/jsx-dev-runtime\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport type { Effect, JsxRuntimeModule } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\nconst Empty = [] as const;\nconst ReactElemType = Symbol.for(\"react.element\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactMemoType = Symbol.for(\"react.memo\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L30\nconst ProxyInstance = new Map<FunctionComponent<any>, FunctionComponent<any>>();\nconst SupportsProxy = typeof Proxy === \"function\";\n\nconst ProxyHandlers = {\n\t/**\n\t * This is a function call trap for functional components.\n\t * When this is called, we know it means React did run 'Component()',\n\t * that means we can use any hooks here to setup our effect and store.\n\t *\n\t * With the native Proxy, all other calls such as access/setting to/of properties will\n\t * be forwarded to the target Component, so we don't need to copy the Component's\n\t * own or inherited properties.\n\t *\n\t * @see https://github.com/facebook/react/blob/2d80a0cd690bb5650b6c8a6c079a87b5dc42bd15/packages/react-reconciler/src/ReactFiberHooks.old.js#L460\n\t */\n\tapply(Component: FunctionComponent, thisArg: any, argumentsList: any) {\n\t\tconst store = useMemo(createEffectStore, Empty);\n\n\t\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n\t\tconst stop = store.updater._start();\n\n\t\ttry {\n\t\t\tconst children = Component.apply(thisArg, argumentsList);\n\t\t\treturn children;\n\t\t} catch (e) {\n\t\t\t// Re-throwing promises that'll be handled by suspense\n\t\t\t// or an actual error.\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\t// Stop effects in either case before return or throw,\n\t\t\t// Otherwise the effect will leak.\n\t\t\tstop();\n\t\t}\n\t},\n};\n\nfunction ProxyFunctionalComponent(Component: FunctionComponent<any>) {\n\treturn ProxyInstance.get(Component) || WrapWithProxy(Component);\n}\nfunction WrapWithProxy(Component: FunctionComponent<any>) {\n\tif (SupportsProxy) {\n\t\tconst ProxyComponent = new Proxy(Component, ProxyHandlers);\n\n\t\tProxyInstance.set(Component, ProxyComponent);\n\t\tProxyInstance.set(ProxyComponent, ProxyComponent);\n\n\t\treturn ProxyComponent;\n\t}\n\n\t/**\n\t * Emulate a Proxy if environment doesn't support it.\n\t *\n\t * @TODO - unlike Proxy, it's not possible to access the type/Component's\n\t * static properties this way. Not sure if we want to copy all statics here.\n\t * Omitting this for now.\n\t *\n\t * @example - works with Proxy, doesn't with wrapped function.\n\t * ```\n\t * const el = <SomeFunctionalComponent />\n\t * el.type.someOwnOrInheritedProperty;\n\t * el.type.defaultProps;\n\t * ```\n\t */\n\tconst WrappedComponent = function () {\n\t\treturn ProxyHandlers.apply(Component, undefined, arguments);\n\t};\n\tProxyInstance.set(Component, WrappedComponent);\n\tProxyInstance.set(WrappedComponent, WrappedComponent);\n\n\treturn WrappedComponent;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a '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 component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,\n * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore\n * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n */\nfunction createEffectStore() {\n\tlet updater!: Effect;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\tupdater,\n\t\tsubscribe(onStoreChange: () => void) {\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};\n}\n\nfunction 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 === \"function\" && !(type instanceof Component)) {\n\t\t\treturn jsx.call(jsx, ProxyFunctionalComponent(type), props, ...rest);\n\t\t}\n\n\t\tif (type && typeof type === \"object\" && type.$$typeof === ReactMemoType) {\n\t\t\ttype.type = ProxyFunctionalComponent(type.type);\n\t\t\treturn jsx.call(jsx, type, props, ...rest);\n\t\t}\n\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 JsxPro: JsxRuntimeModule = jsxRuntime;\nconst JsxDev: JsxRuntimeModule = jsxRuntimeDev;\n\n/**\n * createElement _may_ be called by jsx runtime as a fallback in certain cases,\n * so we need to wrap it regardless.\n *\n * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't\n * include both, so one of them will be set with `undefined` values.\n */\nReact.createElement = WrapJsx(React.createElement);\nJsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));\nJsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));\nJsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));\nJsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));\nJsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));\nJsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: ProxyFunctionalComponent(Text) },\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 useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => 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(() => {\n\t\t\treturn callback.current();\n\t\t});\n\t}, Empty);\n}\n"],"names":["React","Component","useMemo","useRef","useEffect","jsxRuntime","jsxRuntimeDev","useSyncExternalStore","Signal","signal","computed","effect","batch","Empty","Symbol","for","ReactMemoType","ProxyInstance","Map","ProxyHandlers","apply","thisArg","argumentsList","store","createEffectStore","subscribe","getSnapshot","stop","updater","_start","e","get","SupportsProxy","ProxyComponent","Proxy","set","WrappedComponent","undefined","arguments","WrapWithProxy","onChangeNotifyReact","unsubscribe","this","_callback","version","onStoreChange","jsx","type","props","rest","call","ProxyFunctionalComponent","$$typeof","v","i","value","JsxDev","createElement","WrapJsx","JsxPro","jsxs","jsxDEV","Object","defineProperties","prototype","configurable","ReactElemType","data","ref","compute","$compute","current","useSignalEffect","cb","callback","useComputed","useSignal"],"mappings":"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"}
@@ -1 +1 @@
1
- import n,{__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as r,useMemo as t,useRef as e,useEffect as i}from"react";import{Signal as u,effect as f,signal as o,computed as a}from"@preact/signals-core";export{Signal,batch,computed,effect,signal}from"@preact/signals-core";var c,v=n.createElement;n.createElement=function(n,r){if("string"==typeof n&&r)for(var t in r){var e=r[t];if("children"!==t&&e instanceof u)r[t]=e.value}return v.apply(this,arguments)};var l=new WeakMap;function p(n){if(c)c();c=n&&n.S()}var s=v("a").$$typeof;Object.defineProperties(u.prototype,{$$typeof:{configurable:!0,value:s},type:{configurable:!0,value:function(n){return n.data.value}},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});var g,b=!1,m=function(){return{}};Object.defineProperty(r.ReactCurrentDispatcher,"current",{get:function(){return g},set:function(n){g=n;if(!b)if(n&&!function(n){var r=d.get(n);if(void 0!==r)return r;var t=n.useCallback.length<2||/Invalid/.test(n.useCallback);d.set(n,t);return t}(n)){b=!0;var r=n.useReducer(m,{})[1];b=!1;var t=l.get(r);if(!t){t=function(n){var r;f(function(){r=this});r.c=n;return r}(r);l.set(r,t)}else t.c=r;p(t)}else p()}});var d=new Map;function h(n){return t(function(){return o(n)},[])}function y(n){var r=e(n);r.current=n;return t(function(){return a(function(){return r.current()})},[])}function j(n){var r=e(n);r.current=n;i(function(){return f(function(){return r.current()})},[])}export{y as useComputed,h as useSignal,j as useSignalEffect};//# sourceMappingURL=signals.module.js.map
1
+ import n,{Component as r,useMemo as t,useRef as e,useEffect as o}from"react";import u from"react/jsx-runtime";import i from"react/jsx-dev-runtime";import{useSyncExternalStore as f}from"use-sync-external-store/shim/index.js";import{Signal as c,signal as a,computed as p,effect as l}from"@preact/signals-core";export{Signal,batch,computed,effect,signal}from"@preact/signals-core";var s=[],m=Symbol.for("react.element"),v=Symbol.for("react.memo"),y=new Map,b="function"==typeof Proxy,g={apply:function(n,r,e){var o=t(h,s);f(o.subscribe,o.getSnapshot,o.getSnapshot);var u=o.updater.S();try{return n.apply(r,e)}catch(n){throw n}finally{u()}}};function d(n){return y.get(n)||function(n){if(b){var r=new Proxy(n,g);y.set(n,r);y.set(r,r);return r}var t=function(){return g.apply(n,void 0,arguments)};y.set(n,t);y.set(t,t);return t}(n)}function h(){var n,r,t=0,e=l(function(){n=this});n.c=function(){t=t+1|0;if(r)r()};return{updater:n,subscribe:function(n){r=n;return function(){t=t+1|0;r=void 0;e()}},getSnapshot:function(){return t}}}function x(n){if("function"!=typeof n)return n;else return function(t,e){var o=[].slice.call(arguments,2);if("function"==typeof t&&!(t instanceof r))return n.call.apply(n,[n,d(t),e].concat(o));if(t&&"object"==typeof t&&t.$$typeof===v){t.type=d(t.type);return n.call.apply(n,[n,t,e].concat(o))}if("string"==typeof t&&e)for(var u in e){var i=e[u];if("children"!==u&&i instanceof c)e[u]=i.value}return n.call.apply(n,[n,t,e].concat(o))}}var j=u,S=i;n.createElement=x(n.createElement);S.jsx&&(S.jsx=x(S.jsx));j.jsx&&(j.jsx=x(j.jsx));S.jsxs&&(S.jsxs=x(S.jsxs));j.jsxs&&(j.jsxs=x(j.jsxs));S.jsxDEV&&(S.jsxDEV=x(S.jsxDEV));j.jsxDEV&&(j.jsxDEV=x(j.jsxDEV));Object.defineProperties(c.prototype,{$$typeof:{configurable:!0,value:m},type:{configurable:!0,value:d(function(n){return n.data.value})},props:{configurable:!0,get:function(){return{data:this}}},ref:{configurable:!0,value:null}});function useSignal(n){return t(function(){return a(n)},s)}function useComputed(n){var r=e(n);r.current=n;return t(function(){return p(function(){return r.current()})},s)}function useSignalEffect(n){var r=e(n);r.current=n;o(function(){return l(function(){return r.current()})},s)}export{useComputed,useSignal,useSignalEffect};//# sourceMappingURL=signals.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"signals.module.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\t// @ts-ignore-next-line\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as internals,\n} from \"react\";\nimport React from \"react\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport { Effect, ReactDispatcher } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\n/**\n * Install a middleware into React.createElement to replace any Signals in props with their value.\n * @todo this likely needs to be duplicated for jsx()...\n */\nconst createElement = React.createElement;\n// @ts-ignore-next-line\nReact.createElement = function (type, props) {\n\tif (typeof type === \"string\" && props) {\n\t\tfor (let i in props) {\n\t\t\tlet v = props[i];\n\t\t\tif (i !== \"children\" && v instanceof Signal) {\n\t\t\t\t// createPropUpdater(props, i, v);\n\t\t\t\tprops[i] = v.value;\n\t\t\t}\n\t\t}\n\t}\n\t// @ts-ignore-next-line\n\treturn createElement.apply(this, arguments);\n};\n\n/*\n// This breaks React's controlled components implementation\nfunction createPropUpdater(props: any, prop: string, signal: Signal) {\n\tlet ref = props.ref;\n\tif (!ref) ref = props.ref = React.createRef();\n\teffect(() => {\n\t\tif (props) props[prop] = signal.value;\n\t\tlet el = ref.current;\n\t\tif (!el) return; // unsubscribe\n\t\t(el as any)[prop] = signal.value;\n\t});\n\tprops = null;\n}\n*/\n\nlet finishUpdate: (() => void) | undefined;\nconst updaterForComponent = new WeakMap<() => void, Effect>();\n\nfunction setCurrentUpdater(updater?: Effect) {\n\t// end tracking for the current update:\n\tif (finishUpdate) finishUpdate();\n\t// start tracking the new update:\n\tfinishUpdate = updater && updater._start();\n}\n\nfunction createUpdater(update: () => void) {\n\tlet updater!: Effect;\n\teffect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = update;\n\treturn updater;\n}\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\n//@ts-ignore-next-line\nconst $$typeof = createElement(\"a\").$$typeof;\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: $$typeof },\n\ttype: { configurable: true, value: Text },\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\n// Track the current dispatcher (roughly equiv to current component impl)\nlet lock = false;\nconst UPDATE = () => ({});\nlet currentDispatcher: ReactDispatcher;\nObject.defineProperty(internals.ReactCurrentDispatcher, \"current\", {\n\tget() {\n\t\treturn currentDispatcher;\n\t},\n\tset(api) {\n\t\tcurrentDispatcher = api;\n\t\tif (lock) return;\n\t\tif (api && !isInvalidHookAccessor(api)) {\n\t\t\t// prevent re-injecting useReducer when the Dispatcher\n\t\t\t// context changes to run the reducer callback:\n\t\t\tlock = true;\n\t\t\tconst rerender = api.useReducer(UPDATE, {})[1];\n\t\t\tlock = false;\n\n\t\t\tlet updater = updaterForComponent.get(rerender);\n\t\t\tif (!updater) {\n\t\t\t\tupdater = createUpdater(rerender);\n\t\t\t\tupdaterForComponent.set(rerender, updater);\n\t\t\t} else {\n\t\t\t\tupdater._callback = rerender;\n\t\t\t}\n\t\t\tsetCurrentUpdater(updater);\n\t\t} else {\n\t\t\tsetCurrentUpdater();\n\t\t}\n\t},\n});\n\n// We inject a useReducer into every function component via CurrentDispatcher.\n// This prevents injecting into anything other than a function component render.\nconst invalidHookAccessors = new Map();\nfunction isInvalidHookAccessor(api: ReactDispatcher) {\n\tconst cached = invalidHookAccessors.get(api);\n\tif (cached !== undefined) return cached;\n\t// we only want the real implementation, not the warning ones\n\tconst invalid =\n\t\tapi.useCallback.length < 2 || /Invalid/.test(api.useCallback as any);\n\tinvalidHookAccessors.set(api, invalid);\n\treturn invalid;\n}\n\nexport function useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), []);\n}\n\nexport function useComputed<T>(compute: () => T) {\n\tconst $compute = useRef(compute);\n\t$compute.current = compute;\n\treturn useMemo(() => computed<T>(() => $compute.current()), []);\n}\n\nexport function useSignalEffect(cb: () => void | (() => void)) {\n\tconst callback = useRef(cb);\n\tcallback.current = cb;\n\n\tuseEffect(() => {\n\t\treturn effect(() => {\n\t\t\treturn callback.current();\n\t\t});\n\t}, []);\n}\n"],"names":["React","__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","useMemo","useRef","useEffect","Signal","effect","signal","computed","batch","createElement","type","props","i","v","value","apply","this","arguments","updaterForComponent","WeakMap","updater","finishUpdate","_start","$$typeof","Object","defineProperties","prototype","configurable","_ref","data","get","ref","currentDispatcher","lock","UPDATE","defineProperty","internals","ReactCurrentDispatcher","set","api","cached","invalidHookAccessors","undefined","invalid","useCallback","length","test","isInvalidHookAccessor","rerender","useReducer","update","_callback","createUpdater","setCurrentUpdater","Map","useSignal","useComputed","compute","$compute","current","useSignalEffect","cb","callback"],"mappings":"OAyBAA,yDAAAC,aAAAC,YAAAC,eAAAC,MAAA,yBAAAC,YAAAC,YAAAC,cAAAC,MAAA,8BAAAH,OAAAI,MAAAD,SAAAF,OAAAC,WAAA,uBAAA,MAAmBG,EAAGV,EAAMU,cAE5BV,EAAMU,cAAgB,SAAUC,EAAMC,GACrC,GAAoB,iBAAhBD,GAA4BC,EAC/B,IAAK,IAALC,KAAAD,EAAqB,CACpB,IAAKE,EAAGF,EAAMC,GACd,GAAU,aAANA,GAAoBC,aAAaT,EAEpCO,EAAMC,GAAKC,EAAEC,KAEd,CAGF,OAAOL,EAAcM,MAAMC,KAAMC,UACjC,EAkBD,IAAyBC,EAAG,IAAIC,QAEhC,WAA2BC,GAE1B,GAAIC,EAAcA,IAElBA,EAAeD,GAAWA,EAAQE,GAClC,CAoBD,IAAcC,EAAGd,EAAc,KAAKc,SACpCC,OAAOC,iBAAiBrB,EAAOsB,UAAW,CACzCH,SAAU,CAAEI,cAAc,EAAMb,MAAOS,GACvCb,KAAM,CAAEiB,cAAc,EAAMb,MAT7B,SAAAc,GACC,OADeC,EAAAA,KACHf,KACZ,GAQAH,MAAO,CACNgB,cAAc,EACdG,IAAG,WACF,MAAO,CAAED,KAAMb,KACf,GAEFe,IAAK,CAAEJ,cAAc,EAAMb,MAAO,QAInC,IAEIkB,EAFAC,GAAO,EACLC,EAAS,WAAA,MAAO,CAAP,CAAA,EAEfV,OAAOW,eAAeC,EAAUC,uBAAwB,UAAW,CAClEP,IADkE,WAEjE,OAAOE,CACP,EACDM,IAJkE,SAI9DC,GACHP,EAAoBO,EACpB,IAAIN,EACJ,GAAIM,IAwBN,SAA+BA,GAC9B,IAAYC,EAAGC,EAAqBX,IAAIS,GACxC,QAAeG,IAAXF,EAAsB,OAAAA,EAE1B,IAAMG,EACLJ,EAAIK,YAAYC,OAAS,GAAK,UAAUC,KAAKP,EAAIK,aAClDH,EAAqBH,IAAIC,EAAKI,GAC9B,OACAA,CAAA,CAhCaI,CAAsBR,GAAM,CAGvCN,GAAO,EACP,IAAMe,EAAWT,EAAIU,WAAWf,EAAQ,CAAA,GAAI,GAC5CD,GAAO,EAEP,IAAIb,EAAUF,EAAoBY,IAAIkB,GACtC,IAAK5B,EAAS,CACbA,EAnDJ,SAAuB8B,GACtB,MACA7C,EAAO,WACNe,EAAUJ,IACV,GACDI,EAAQ+B,EAAYD,EACpB,OAAO9B,CACP,CA4CagC,CAAcJ,GACxB9B,EAAoBoB,IAAIU,EAAU5B,EAClC,MACAA,EAAQ+B,EAAYH,EAErBK,EAAkBjC,EAClB,MACAiC,GAED,IAKF,MAA6B,IAA7BC,IAWM,SAAAC,EAAuBzC,GAC5B,OAAcb,EAAC,kBAAYK,EAAIQ,EAAhB,EAAwB,GACvC,CAEK,SAAA0C,EAAyBC,GAC9B,MAAiBvD,EAAOuD,GACxBC,EAASC,QAAUF,EACnB,OAAOxD,EAAQ,WAAA,SAAkB,WAAA,OAAcyD,EAACC,SAAf,EAAlB,EAA6C,GAC5D,CAEK,SAAAC,EAA0BC,GAC/B,IAAMC,EAAW5D,EAAO2D,GACxBC,EAASH,QAAUE,EAEnB1D,EAAU,WACT,OAAaE,EAAC,WACb,OAAeyD,EAACH,SAChB,EACD,EAAE,GACH,QAAAH,iBAAAD,eAAAK"}
1
+ {"version":3,"file":"signals.module.js","sources":["../src/index.ts"],"sourcesContent":["import {\n\tuseRef,\n\tuseMemo,\n\tuseEffect,\n\tComponent,\n\ttype FunctionComponent,\n} from \"react\";\nimport React from \"react\";\nimport jsxRuntime from \"react/jsx-runtime\";\nimport jsxRuntimeDev from \"react/jsx-dev-runtime\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport {\n\tsignal,\n\tcomputed,\n\tbatch,\n\teffect,\n\tSignal,\n\ttype ReadonlySignal,\n} from \"@preact/signals-core\";\nimport type { Effect, JsxRuntimeModule } from \"./internal\";\n\nexport { signal, computed, batch, effect, Signal, type ReadonlySignal };\n\nconst Empty = [] as const;\nconst ReactElemType = Symbol.for(\"react.element\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15\nconst ReactMemoType = Symbol.for(\"react.memo\"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L30\nconst ProxyInstance = new Map<FunctionComponent<any>, FunctionComponent<any>>();\nconst SupportsProxy = typeof Proxy === \"function\";\n\nconst ProxyHandlers = {\n\t/**\n\t * This is a function call trap for functional components.\n\t * When this is called, we know it means React did run 'Component()',\n\t * that means we can use any hooks here to setup our effect and store.\n\t *\n\t * With the native Proxy, all other calls such as access/setting to/of properties will\n\t * be forwarded to the target Component, so we don't need to copy the Component's\n\t * own or inherited properties.\n\t *\n\t * @see https://github.com/facebook/react/blob/2d80a0cd690bb5650b6c8a6c079a87b5dc42bd15/packages/react-reconciler/src/ReactFiberHooks.old.js#L460\n\t */\n\tapply(Component: FunctionComponent, thisArg: any, argumentsList: any) {\n\t\tconst store = useMemo(createEffectStore, Empty);\n\n\t\tuseSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n\t\tconst stop = store.updater._start();\n\n\t\ttry {\n\t\t\tconst children = Component.apply(thisArg, argumentsList);\n\t\t\treturn children;\n\t\t} catch (e) {\n\t\t\t// Re-throwing promises that'll be handled by suspense\n\t\t\t// or an actual error.\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\t// Stop effects in either case before return or throw,\n\t\t\t// Otherwise the effect will leak.\n\t\t\tstop();\n\t\t}\n\t},\n};\n\nfunction ProxyFunctionalComponent(Component: FunctionComponent<any>) {\n\treturn ProxyInstance.get(Component) || WrapWithProxy(Component);\n}\nfunction WrapWithProxy(Component: FunctionComponent<any>) {\n\tif (SupportsProxy) {\n\t\tconst ProxyComponent = new Proxy(Component, ProxyHandlers);\n\n\t\tProxyInstance.set(Component, ProxyComponent);\n\t\tProxyInstance.set(ProxyComponent, ProxyComponent);\n\n\t\treturn ProxyComponent;\n\t}\n\n\t/**\n\t * Emulate a Proxy if environment doesn't support it.\n\t *\n\t * @TODO - unlike Proxy, it's not possible to access the type/Component's\n\t * static properties this way. Not sure if we want to copy all statics here.\n\t * Omitting this for now.\n\t *\n\t * @example - works with Proxy, doesn't with wrapped function.\n\t * ```\n\t * const el = <SomeFunctionalComponent />\n\t * el.type.someOwnOrInheritedProperty;\n\t * el.type.defaultProps;\n\t * ```\n\t */\n\tconst WrappedComponent = function () {\n\t\treturn ProxyHandlers.apply(Component, undefined, arguments);\n\t};\n\tProxyInstance.set(Component, WrappedComponent);\n\tProxyInstance.set(WrappedComponent, WrappedComponent);\n\n\treturn WrappedComponent;\n}\n\n/**\n * A redux-like store whose store value is a positive 32bit integer (a '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 component (call 'onStoreChange').\n *\n * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,\n * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).\n *\n * [1]\n * @see https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore\n * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md\n */\nfunction createEffectStore() {\n\tlet updater!: Effect;\n\tlet version = 0;\n\tlet onChangeNotifyReact: (() => void) | undefined;\n\n\tlet unsubscribe = effect(function (this: Effect) {\n\t\tupdater = this;\n\t});\n\tupdater._callback = function () {\n\t\tversion = (version + 1) | 0;\n\t\tif (onChangeNotifyReact) onChangeNotifyReact();\n\t};\n\n\treturn {\n\t\tupdater,\n\t\tsubscribe(onStoreChange: () => void) {\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};\n}\n\nfunction 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 === \"function\" && !(type instanceof Component)) {\n\t\t\treturn jsx.call(jsx, ProxyFunctionalComponent(type), props, ...rest);\n\t\t}\n\n\t\tif (type && typeof type === \"object\" && type.$$typeof === ReactMemoType) {\n\t\t\ttype.type = ProxyFunctionalComponent(type.type);\n\t\t\treturn jsx.call(jsx, type, props, ...rest);\n\t\t}\n\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 JsxPro: JsxRuntimeModule = jsxRuntime;\nconst JsxDev: JsxRuntimeModule = jsxRuntimeDev;\n\n/**\n * createElement _may_ be called by jsx runtime as a fallback in certain cases,\n * so we need to wrap it regardless.\n *\n * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't\n * include both, so one of them will be set with `undefined` values.\n */\nReact.createElement = WrapJsx(React.createElement);\nJsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));\nJsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));\nJsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));\nJsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));\nJsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));\nJsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));\n\n/**\n * A wrapper component that renders a Signal's value directly as a Text node.\n */\nfunction Text({ data }: { data: Signal }) {\n\treturn data.value;\n}\n\n// Decorate Signals so React renders them as <Text> components.\nObject.defineProperties(Signal.prototype, {\n\t$$typeof: { configurable: true, value: ReactElemType },\n\ttype: { configurable: true, value: ProxyFunctionalComponent(Text) },\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 useSignal<T>(value: T) {\n\treturn useMemo(() => signal<T>(value), Empty);\n}\n\nexport function useComputed<T>(compute: () => 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(() => {\n\t\t\treturn callback.current();\n\t\t});\n\t}, Empty);\n}\n"],"names":["Empty","Symbol","ReactMemoType","ProxyInstance","Map","SupportsProxy","Proxy","apply","Component","thisArg","argumentsList","useMemo","createEffectStore","useSyncExternalStore","store","subscribe","getSnapshot","updater","_start","e","stop","ProxyFunctionalComponent","get","ProxyComponent","ProxyHandlers","set","WrappedComponent","undefined","arguments","WrapWithProxy","onChangeNotifyReact","version","unsubscribe","effect","this","_callback","onStoreChange","WrapJsx","jsx","type","props","slice","call","rest","$$typeof","i","v","Signal","value","concat","JsxPro","jsxRuntime","JsxDev","jsxRuntimeDev","React","createElement","jsxs","jsxDEV","Object","defineProperties","prototype","configurable","ReactElemType","_ref","data","ref","useComputed","compute","$compute","useRef","current","computed","useSignalEffect","cb","callback","useEffect","useSignal"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preact/signals-react",
3
- "version": "1.1.1",
3
+ "version": "1.2.1",
4
4
  "license": "MIT",
5
5
  "description": "",
6
6
  "keywords": [],
@@ -35,16 +35,18 @@
35
35
  },
36
36
  "mangle": "../../mangle.json",
37
37
  "dependencies": {
38
- "@preact/signals-core": "^1.2.1"
38
+ "@preact/signals-core": "^1.2.2",
39
+ "use-sync-external-store": "^1.2.0"
39
40
  },
40
41
  "peerDependencies": {
41
42
  "react": "17.x || 18.x"
42
43
  },
43
44
  "devDependencies": {
44
- "react": "^18.2.0",
45
- "react-dom": "^18.2.0",
46
45
  "@types/react": "^18.0.18",
47
- "@types/react-dom": "^18.0.6"
46
+ "@types/react-dom": "^18.0.6",
47
+ "@types/use-sync-external-store": "^0.0.3",
48
+ "react": "^18.2.0",
49
+ "react-dom": "^18.2.0"
48
50
  },
49
51
  "scripts": {}
50
52
  }
package/src/index.ts CHANGED
@@ -2,11 +2,13 @@ import {
2
2
  useRef,
3
3
  useMemo,
4
4
  useEffect,
5
- // @ts-ignore-next-line
6
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
7
- __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as internals,
5
+ Component,
6
+ type FunctionComponent,
8
7
  } from "react";
9
8
  import React from "react";
9
+ import jsxRuntime from "react/jsx-runtime";
10
+ import jsxRuntimeDev from "react/jsx-dev-runtime";
11
+ import { useSyncExternalStore } from "use-sync-external-store/shim/index.js";
10
12
  import {
11
13
  signal,
12
14
  computed,
@@ -15,64 +17,183 @@ import {
15
17
  Signal,
16
18
  type ReadonlySignal,
17
19
  } from "@preact/signals-core";
18
- import { Effect, ReactDispatcher } from "./internal";
20
+ import type { Effect, JsxRuntimeModule } from "./internal";
19
21
 
20
22
  export { signal, computed, batch, effect, Signal, type ReadonlySignal };
21
23
 
22
- /**
23
- * Install a middleware into React.createElement to replace any Signals in props with their value.
24
- * @todo this likely needs to be duplicated for jsx()...
25
- */
26
- const createElement = React.createElement;
27
- // @ts-ignore-next-line
28
- React.createElement = function (type, props) {
29
- if (typeof type === "string" && props) {
30
- for (let i in props) {
31
- let v = props[i];
32
- if (i !== "children" && v instanceof Signal) {
33
- // createPropUpdater(props, i, v);
34
- props[i] = v.value;
35
- }
24
+ const Empty = [] as const;
25
+ const ReactElemType = Symbol.for("react.element"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L15
26
+ const ReactMemoType = Symbol.for("react.memo"); // https://github.com/facebook/react/blob/346c7d4c43a0717302d446da9e7423a8e28d8996/packages/shared/ReactSymbols.js#L30
27
+ const ProxyInstance = new Map<FunctionComponent<any>, FunctionComponent<any>>();
28
+ const SupportsProxy = typeof Proxy === "function";
29
+
30
+ const ProxyHandlers = {
31
+ /**
32
+ * This is a function call trap for functional components.
33
+ * When this is called, we know it means React did run 'Component()',
34
+ * that means we can use any hooks here to setup our effect and store.
35
+ *
36
+ * With the native Proxy, all other calls such as access/setting to/of properties will
37
+ * be forwarded to the target Component, so we don't need to copy the Component's
38
+ * own or inherited properties.
39
+ *
40
+ * @see https://github.com/facebook/react/blob/2d80a0cd690bb5650b6c8a6c079a87b5dc42bd15/packages/react-reconciler/src/ReactFiberHooks.old.js#L460
41
+ */
42
+ apply(Component: FunctionComponent, thisArg: any, argumentsList: any) {
43
+ const store = useMemo(createEffectStore, Empty);
44
+
45
+ useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
46
+
47
+ const stop = store.updater._start();
48
+
49
+ try {
50
+ const children = Component.apply(thisArg, argumentsList);
51
+ return children;
52
+ } catch (e) {
53
+ // Re-throwing promises that'll be handled by suspense
54
+ // or an actual error.
55
+ throw e;
56
+ } finally {
57
+ // Stop effects in either case before return or throw,
58
+ // Otherwise the effect will leak.
59
+ stop();
36
60
  }
37
- }
38
- // @ts-ignore-next-line
39
- return createElement.apply(this, arguments);
61
+ },
40
62
  };
41
63
 
42
- /*
43
- // This breaks React's controlled components implementation
44
- function createPropUpdater(props: any, prop: string, signal: Signal) {
45
- let ref = props.ref;
46
- if (!ref) ref = props.ref = React.createRef();
47
- effect(() => {
48
- if (props) props[prop] = signal.value;
49
- let el = ref.current;
50
- if (!el) return; // unsubscribe
51
- (el as any)[prop] = signal.value;
52
- });
53
- props = null;
64
+ function ProxyFunctionalComponent(Component: FunctionComponent<any>) {
65
+ return ProxyInstance.get(Component) || WrapWithProxy(Component);
54
66
  }
55
- */
67
+ function WrapWithProxy(Component: FunctionComponent<any>) {
68
+ if (SupportsProxy) {
69
+ const ProxyComponent = new Proxy(Component, ProxyHandlers);
56
70
 
57
- let finishUpdate: (() => void) | undefined;
58
- const updaterForComponent = new WeakMap<() => void, Effect>();
71
+ ProxyInstance.set(Component, ProxyComponent);
72
+ ProxyInstance.set(ProxyComponent, ProxyComponent);
59
73
 
60
- function setCurrentUpdater(updater?: Effect) {
61
- // end tracking for the current update:
62
- if (finishUpdate) finishUpdate();
63
- // start tracking the new update:
64
- finishUpdate = updater && updater._start();
74
+ return ProxyComponent;
75
+ }
76
+
77
+ /**
78
+ * Emulate a Proxy if environment doesn't support it.
79
+ *
80
+ * @TODO - unlike Proxy, it's not possible to access the type/Component's
81
+ * static properties this way. Not sure if we want to copy all statics here.
82
+ * Omitting this for now.
83
+ *
84
+ * @example - works with Proxy, doesn't with wrapped function.
85
+ * ```
86
+ * const el = <SomeFunctionalComponent />
87
+ * el.type.someOwnOrInheritedProperty;
88
+ * el.type.defaultProps;
89
+ * ```
90
+ */
91
+ const WrappedComponent = function () {
92
+ return ProxyHandlers.apply(Component, undefined, arguments);
93
+ };
94
+ ProxyInstance.set(Component, WrappedComponent);
95
+ ProxyInstance.set(WrappedComponent, WrappedComponent);
96
+
97
+ return WrappedComponent;
65
98
  }
66
99
 
67
- function createUpdater(update: () => void) {
100
+ /**
101
+ * A redux-like store whose store value is a positive 32bit integer (a 'version').
102
+ *
103
+ * React subscribes to this store and gets a snapshot of the current 'version',
104
+ * whenever the 'version' changes, we tell React it's time to update the component (call 'onStoreChange').
105
+ *
106
+ * How we achieve this is by creating a binding with an 'effect', when the `effect._callback' is called,
107
+ * we update our store version and tell React to re-render the component ([1] We don't really care when/how React does it).
108
+ *
109
+ * [1]
110
+ * @see https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore
111
+ * @see https://github.com/reactjs/rfcs/blob/main/text/0214-use-sync-external-store.md
112
+ */
113
+ function createEffectStore() {
68
114
  let updater!: Effect;
69
- effect(function (this: Effect) {
115
+ let version = 0;
116
+ let onChangeNotifyReact: (() => void) | undefined;
117
+
118
+ let unsubscribe = effect(function (this: Effect) {
70
119
  updater = this;
71
120
  });
72
- updater._callback = update;
73
- return updater;
121
+ updater._callback = function () {
122
+ version = (version + 1) | 0;
123
+ if (onChangeNotifyReact) onChangeNotifyReact();
124
+ };
125
+
126
+ return {
127
+ updater,
128
+ subscribe(onStoreChange: () => void) {
129
+ onChangeNotifyReact = onStoreChange;
130
+
131
+ return function () {
132
+ /**
133
+ * Rotate to next version when unsubscribing to ensure that components are re-run
134
+ * when subscribing again.
135
+ *
136
+ * In StrictMode, 'memo'-ed components seem to keep a stale snapshot version, so
137
+ * don't re-run after subscribing again if the version is the same as last time.
138
+ *
139
+ * Because we unsubscribe from the effect, the version may not change. We simply
140
+ * set a new initial version in case of stale snapshots here.
141
+ */
142
+ version = (version + 1) | 0;
143
+ onChangeNotifyReact = undefined;
144
+ unsubscribe();
145
+ };
146
+ },
147
+ getSnapshot() {
148
+ return version;
149
+ },
150
+ };
151
+ }
152
+
153
+ function WrapJsx<T>(jsx: T): T {
154
+ if (typeof jsx !== "function") return jsx;
155
+
156
+ return function (type: any, props: any, ...rest: any[]) {
157
+ if (typeof type === "function" && !(type instanceof Component)) {
158
+ return jsx.call(jsx, ProxyFunctionalComponent(type), props, ...rest);
159
+ }
160
+
161
+ if (type && typeof type === "object" && type.$$typeof === ReactMemoType) {
162
+ type.type = ProxyFunctionalComponent(type.type);
163
+ return jsx.call(jsx, type, props, ...rest);
164
+ }
165
+
166
+ if (typeof type === "string" && props) {
167
+ for (let i in props) {
168
+ let v = props[i];
169
+ if (i !== "children" && v instanceof Signal) {
170
+ props[i] = v.value;
171
+ }
172
+ }
173
+ }
174
+
175
+ return jsx.call(jsx, type, props, ...rest);
176
+ } as any as T;
74
177
  }
75
178
 
179
+ const JsxPro: JsxRuntimeModule = jsxRuntime;
180
+ const JsxDev: JsxRuntimeModule = jsxRuntimeDev;
181
+
182
+ /**
183
+ * createElement _may_ be called by jsx runtime as a fallback in certain cases,
184
+ * so we need to wrap it regardless.
185
+ *
186
+ * The jsx exports depend on the `NODE_ENV` var to ensure the users' bundler doesn't
187
+ * include both, so one of them will be set with `undefined` values.
188
+ */
189
+ React.createElement = WrapJsx(React.createElement);
190
+ JsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));
191
+ JsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));
192
+ JsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));
193
+ JsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));
194
+ JsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));
195
+ JsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));
196
+
76
197
  /**
77
198
  * A wrapper component that renders a Signal's value directly as a Text node.
78
199
  */
@@ -81,11 +202,9 @@ function Text({ data }: { data: Signal }) {
81
202
  }
82
203
 
83
204
  // Decorate Signals so React renders them as <Text> components.
84
- //@ts-ignore-next-line
85
- const $$typeof = createElement("a").$$typeof;
86
205
  Object.defineProperties(Signal.prototype, {
87
- $$typeof: { configurable: true, value: $$typeof },
88
- type: { configurable: true, value: Text },
206
+ $$typeof: { configurable: true, value: ReactElemType },
207
+ type: { configurable: true, value: ProxyFunctionalComponent(Text) },
89
208
  props: {
90
209
  configurable: true,
91
210
  get() {
@@ -95,59 +214,14 @@ Object.defineProperties(Signal.prototype, {
95
214
  ref: { configurable: true, value: null },
96
215
  });
97
216
 
98
- // Track the current dispatcher (roughly equiv to current component impl)
99
- let lock = false;
100
- const UPDATE = () => ({});
101
- let currentDispatcher: ReactDispatcher;
102
- Object.defineProperty(internals.ReactCurrentDispatcher, "current", {
103
- get() {
104
- return currentDispatcher;
105
- },
106
- set(api) {
107
- currentDispatcher = api;
108
- if (lock) return;
109
- if (api && !isInvalidHookAccessor(api)) {
110
- // prevent re-injecting useReducer when the Dispatcher
111
- // context changes to run the reducer callback:
112
- lock = true;
113
- const rerender = api.useReducer(UPDATE, {})[1];
114
- lock = false;
115
-
116
- let updater = updaterForComponent.get(rerender);
117
- if (!updater) {
118
- updater = createUpdater(rerender);
119
- updaterForComponent.set(rerender, updater);
120
- } else {
121
- updater._callback = rerender;
122
- }
123
- setCurrentUpdater(updater);
124
- } else {
125
- setCurrentUpdater();
126
- }
127
- },
128
- });
129
-
130
- // We inject a useReducer into every function component via CurrentDispatcher.
131
- // This prevents injecting into anything other than a function component render.
132
- const invalidHookAccessors = new Map();
133
- function isInvalidHookAccessor(api: ReactDispatcher) {
134
- const cached = invalidHookAccessors.get(api);
135
- if (cached !== undefined) return cached;
136
- // we only want the real implementation, not the warning ones
137
- const invalid =
138
- api.useCallback.length < 2 || /Invalid/.test(api.useCallback as any);
139
- invalidHookAccessors.set(api, invalid);
140
- return invalid;
141
- }
142
-
143
217
  export function useSignal<T>(value: T) {
144
- return useMemo(() => signal<T>(value), []);
218
+ return useMemo(() => signal<T>(value), Empty);
145
219
  }
146
220
 
147
221
  export function useComputed<T>(compute: () => T) {
148
222
  const $compute = useRef(compute);
149
223
  $compute.current = compute;
150
- return useMemo(() => computed<T>(() => $compute.current()), []);
224
+ return useMemo(() => computed<T>(() => $compute.current()), Empty);
151
225
  }
152
226
 
153
227
  export function useSignalEffect(cb: () => void | (() => void)) {
@@ -158,5 +232,5 @@ export function useSignalEffect(cb: () => void | (() => void)) {
158
232
  return effect(() => {
159
233
  return callback.current();
160
234
  });
161
- }, []);
235
+ }, Empty);
162
236
  }
package/src/internal.d.ts CHANGED
@@ -7,8 +7,10 @@ export interface Effect {
7
7
  _dispose(): void;
8
8
  }
9
9
 
10
- export interface ReactDispatcher {
11
- useCallback(): unknown;
12
- }
13
-
14
10
  export type Updater = Signal<unknown>;
11
+
12
+ export interface JsxRuntimeModule {
13
+ jsx?(type: any, ...rest: any[]): unknown;
14
+ jsxs?(type: any, ...rest: any[]): unknown;
15
+ jsxDEV?(type: any, ...rest: any[]): unknown;
16
+ }
@@ -4,6 +4,7 @@ globalThis.IS_REACT_ACT_ENVIRONMENT = true;
4
4
  import { signal, useComputed } from "@preact/signals-react";
5
5
  import { createElement, useMemo, memo, StrictMode } from "react";
6
6
  import { createRoot, Root } from "react-dom/client";
7
+ import { renderToStaticMarkup } from "react-dom/server";
7
8
  import { act } from "react-dom/test-utils";
8
9
 
9
10
  describe("@preact/signals-react", () => {
@@ -162,6 +163,26 @@ describe("@preact/signals-react", () => {
162
163
  it("should consistently rerender in strict mode", async () => {
163
164
  const sig = signal<string>(null!);
164
165
 
166
+ const Test = () => <p>{sig.value}</p>;
167
+ const App = () => (
168
+ <StrictMode>
169
+ <Test />
170
+ </StrictMode>
171
+ );
172
+
173
+ for (let i = 0; i < 3; i++) {
174
+ const value = `${i}`;
175
+
176
+ act(() => {
177
+ sig.value = value;
178
+ render(<App />);
179
+ });
180
+ expect(scratch.textContent).to.equal(value);
181
+ }
182
+ });
183
+ it("should consistently rerender in strict mode (with memo)", async () => {
184
+ const sig = signal<string>(null!);
185
+
165
186
  const Test = memo(() => <p>{sig.value}</p>);
166
187
  const App = () => (
167
188
  <StrictMode>
@@ -179,5 +200,26 @@ describe("@preact/signals-react", () => {
179
200
  expect(scratch.textContent).to.equal(value);
180
201
  }
181
202
  });
203
+ it("should render static markup of a component", async () => {
204
+ const count = signal(0);
205
+
206
+ const Test = () => {
207
+ return (
208
+ <pre>
209
+ {renderToStaticMarkup(<code>{count}</code>)}
210
+ {renderToStaticMarkup(<code>{count.value}</code>)}
211
+ </pre>
212
+ );
213
+ };
214
+ for (let i = 0; i < 3; i++) {
215
+ act(() => {
216
+ count.value += 1;
217
+ render(<Test />);
218
+ });
219
+ expect(scratch.textContent).to.equal(
220
+ `<code>${count.value}</code><code>${count.value}</code>`
221
+ );
222
+ }
223
+ });
182
224
  });
183
225
  });