@preact/signals-react 3.0.1 → 3.1.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,17 @@
1
1
  # @preact/signals-react
2
2
 
3
+ ## 3.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#684](https://github.com/preactjs/signals/pull/684) [`a34eab2`](https://github.com/preactjs/signals/commit/a34eab2ab5a46f4ef90e05e2af6b99747191333c) Thanks [@JoviDeCroock](https://github.com/JoviDeCroock)! - Ensure we build the thing
8
+
9
+ ## 3.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#627](https://github.com/preactjs/signals/pull/627) [`acfa71c`](https://github.com/preactjs/signals/commit/acfa71cff279ba8bb62a9852c3c47ca4c9461e4d) Thanks [@JoviDeCroock](https://github.com/JoviDeCroock)! - Add a `@preact/signals-react/utils` entrypoint containing common Signal utilities
14
+
3
15
  ## 3.0.1
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -132,6 +132,84 @@ To opt into this optimization, simply pass the signal directly instead of access
132
132
  > **Note**
133
133
  > The content is wrapped in a React Fragment due to React 18's newer, more strict children types.
134
134
 
135
+ ## Utility Components and Hooks
136
+
137
+ The `@preact/signals-react/utils` package provides additional utility components and hooks to make working with signals even easier.
138
+
139
+ ### Show Component
140
+
141
+ The `Show` component provides a declarative way to conditionally render content based on a signal's value.
142
+
143
+ ```js
144
+ import { Show } from "@preact/signals-react/utils";
145
+ import { signal } from "@preact/signals-react";
146
+
147
+ const isVisible = signal(false);
148
+
149
+ function App() {
150
+ return (
151
+ <Show when={isVisible} fallback={<p>Nothing to see here</p>}>
152
+ <p>Now you see me!</p>
153
+ </Show>
154
+ );
155
+ }
156
+
157
+ // You can also use a function to access the value
158
+ function App() {
159
+ return <Show when={isVisible}>{value => <p>The value is {value}</p>}</Show>;
160
+ }
161
+ ```
162
+
163
+ ### For Component
164
+
165
+ The `For` component helps you render lists from signal arrays with automatic caching of rendered items.
166
+
167
+ ```js
168
+ import { For } from "@preact/signals-react/utils";
169
+ import { signal } from "@preact/signals-react";
170
+
171
+ const items = signal(["A", "B", "C"]);
172
+
173
+ function App() {
174
+ return (
175
+ <For each={items} fallback={<p>No items</p>}>
176
+ {(item, index) => <div key={index}>Item: {item}</div>}
177
+ </For>
178
+ );
179
+ }
180
+ ```
181
+
182
+ ### Additional Hooks
183
+
184
+ #### useLiveSignal
185
+
186
+ The `useLiveSignal` hook allows you to create a local signal that stays synchronized with an external signal.
187
+
188
+ ```js
189
+ import { useLiveSignal } from "@preact/signals-react/utils";
190
+ import { signal } from "@preact/signals-react";
191
+
192
+ const external = signal(0);
193
+
194
+ function Component() {
195
+ const local = useLiveSignal(external);
196
+ // local will automatically update when external changes
197
+ }
198
+ ```
199
+
200
+ #### useSignalRef
201
+
202
+ The `useSignalRef` hook creates a signal that behaves like a React ref with a `.current` property.
203
+
204
+ ```js
205
+ import { useSignalRef } from "@preact/signals-react/utils";
206
+
207
+ function Component() {
208
+ const ref = useSignalRef(null);
209
+ return <div ref={ref}>The ref's value is {ref.current}</div>;
210
+ }
211
+ ```
212
+
135
213
  ## Limitations
136
214
 
137
215
  This version of React integration does not support passing signals as DOM attributes. Support for this may be added at a later date.
package/dist/signals.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { signal, computed, batch, effect, Signal, type ReadonlySignal, untracked } from "@preact/signals-core";
2
- import type { ReactElement } from "react";
3
- import { useSignal, useComputed, useSignalEffect } from "@preact/signals-react/runtime";
4
- export { signal, computed, batch, effect, Signal, type ReadonlySignal, useSignal, useComputed, useSignalEffect, untracked, };
5
- declare module "@preact/signals-core" {
6
- interface Signal extends ReactElement {
7
- }
8
- interface ReadonlySignal extends ReactElement {
9
- }
10
- }
1
+ import { signal, computed, batch, effect, Signal, type ReadonlySignal, untracked } from "@preact/signals-core";
2
+ import type { ReactElement } from "react";
3
+ import { useSignal, useComputed, useSignalEffect } from "@preact/signals-react/runtime";
4
+ export { signal, computed, batch, effect, Signal, type ReadonlySignal, useSignal, useComputed, useSignalEffect, untracked, };
5
+ declare module "@preact/signals-core" {
6
+ interface Signal extends ReactElement {
7
+ }
8
+ interface ReadonlySignal extends ReactElement {
9
+ }
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preact/signals-react",
3
- "version": "3.0.1",
3
+ "version": "3.1.1",
4
4
  "license": "MIT",
5
5
  "description": "Manage state with style in React",
6
6
  "keywords": [],
@@ -37,7 +37,14 @@
37
37
  "import": "./runtime/dist/runtime.mjs",
38
38
  "require": "./runtime/dist/runtime.js"
39
39
  },
40
- "./runtime/package.json": "./runtime/package.json"
40
+ "./runtime/package.json": "./runtime/package.json",
41
+ "./utils": {
42
+ "types": "./utils/dist/index.d.ts",
43
+ "browser": "./utils/dist/utils.module.js",
44
+ "import": "./utils/dist/utils.mjs",
45
+ "require": "./utils/dist/utils.js"
46
+ },
47
+ "./utils/package.json": "./utils/package.json"
41
48
  },
42
49
  "mangle": "../../mangle.json",
43
50
  "files": [
@@ -46,6 +53,9 @@
46
53
  "runtime/dist",
47
54
  "runtime/src",
48
55
  "runtime/package.json",
56
+ "utils/dist",
57
+ "utils/src",
58
+ "utils/package.json",
49
59
  "CHANGELOG.md",
50
60
  "LICENSE",
51
61
  "README.md"
@@ -1,63 +1,63 @@
1
- import { Signal, ReadonlySignal } from "@preact/signals-core";
2
- export declare function wrapJsx<T>(jsx: T): T;
3
- declare const symDispose: unique symbol;
4
- interface Effect {
5
- _sources: object | undefined;
6
- _start(): () => void;
7
- _callback(): void;
8
- _dispose(): void;
9
- }
10
- /**
11
- * Use this flag to represent a bare `useSignals` call that doesn't manually
12
- * close its effect store and relies on auto-closing when the next useSignals is
13
- * called or after a microtask
14
- */
15
- declare const UNMANAGED = 0;
16
- /**
17
- * Use this flag to represent a `useSignals` call that is manually closed by a
18
- * try/finally block in a component's render method. This is the default usage
19
- * that the react-transform plugin uses.
20
- */
21
- declare const MANAGED_COMPONENT = 1;
22
- /**
23
- * Use this flag to represent a `useSignals` call that is manually closed by a
24
- * try/finally block in a hook body. This is the default usage that the
25
- * react-transform plugin uses.
26
- */
27
- declare const MANAGED_HOOK = 2;
28
- /**
29
- * An enum defining how this store is used. See the documentation for each enum
30
- * member for more details.
31
- * @see {@link UNMANAGED}
32
- * @see {@link MANAGED_COMPONENT}
33
- * @see {@link MANAGED_HOOK}
34
- */
35
- declare type EffectStoreUsage = typeof UNMANAGED | typeof MANAGED_COMPONENT | typeof MANAGED_HOOK;
36
- export interface EffectStore {
37
- /**
38
- * An enum defining how this hook is used and whether it is invoked in a
39
- * component's body or hook body. See the comment on `EffectStoreUsage` for
40
- * more details.
41
- */
42
- readonly _usage: EffectStoreUsage;
43
- readonly effect: Effect;
44
- subscribe(onStoreChange: () => void): () => void;
45
- getSnapshot(): number;
46
- /** startEffect - begin tracking signals used in this component */
47
- _start(): void;
48
- /** finishEffect - stop tracking the signals used in this component */
49
- f(): void;
50
- [symDispose](): void;
51
- }
52
- export declare function ensureFinalCleanup(): void;
53
- /**
54
- * Custom hook to create the effect to track signals used during render and
55
- * subscribe to changes to rerender the component when the signals change.
56
- */
57
- export declare function _useSignalsImplementation(_usage?: EffectStoreUsage): EffectStore;
58
- export declare function useSignals(usage?: EffectStoreUsage): EffectStore;
59
- export declare function useSignal<T>(value: T): Signal<T>;
60
- export declare function useSignal<T = undefined>(): Signal<T | undefined>;
61
- export declare function useComputed<T>(compute: () => T): ReadonlySignal<T>;
62
- export declare function useSignalEffect(cb: () => void | (() => void)): void;
63
- export {};
1
+ import { Signal, ReadonlySignal } from "@preact/signals-core";
2
+ export declare function wrapJsx<T>(jsx: T): T;
3
+ declare const symDispose: unique symbol;
4
+ interface Effect {
5
+ _sources: object | undefined;
6
+ _start(): () => void;
7
+ _callback(): void;
8
+ _dispose(): void;
9
+ }
10
+ /**
11
+ * Use this flag to represent a bare `useSignals` call that doesn't manually
12
+ * close its effect store and relies on auto-closing when the next useSignals is
13
+ * called or after a microtask
14
+ */
15
+ declare const UNMANAGED = 0;
16
+ /**
17
+ * Use this flag to represent a `useSignals` call that is manually closed by a
18
+ * try/finally block in a component's render method. This is the default usage
19
+ * that the react-transform plugin uses.
20
+ */
21
+ declare const MANAGED_COMPONENT = 1;
22
+ /**
23
+ * Use this flag to represent a `useSignals` call that is manually closed by a
24
+ * try/finally block in a hook body. This is the default usage that the
25
+ * react-transform plugin uses.
26
+ */
27
+ declare const MANAGED_HOOK = 2;
28
+ /**
29
+ * An enum defining how this store is used. See the documentation for each enum
30
+ * member for more details.
31
+ * @see {@link UNMANAGED}
32
+ * @see {@link MANAGED_COMPONENT}
33
+ * @see {@link MANAGED_HOOK}
34
+ */
35
+ type EffectStoreUsage = typeof UNMANAGED | typeof MANAGED_COMPONENT | typeof MANAGED_HOOK;
36
+ export interface EffectStore {
37
+ /**
38
+ * An enum defining how this hook is used and whether it is invoked in a
39
+ * component's body or hook body. See the comment on `EffectStoreUsage` for
40
+ * more details.
41
+ */
42
+ readonly _usage: EffectStoreUsage;
43
+ readonly effect: Effect;
44
+ subscribe(onStoreChange: () => void): () => void;
45
+ getSnapshot(): number;
46
+ /** startEffect - begin tracking signals used in this component */
47
+ _start(): void;
48
+ /** finishEffect - stop tracking the signals used in this component */
49
+ f(): void;
50
+ [symDispose](): void;
51
+ }
52
+ export declare function ensureFinalCleanup(): void;
53
+ /**
54
+ * Custom hook to create the effect to track signals used during render and
55
+ * subscribe to changes to rerender the component when the signals change.
56
+ */
57
+ export declare function _useSignalsImplementation(_usage?: EffectStoreUsage): EffectStore;
58
+ export declare function useSignals(usage?: EffectStoreUsage): EffectStore;
59
+ export declare function useSignal<T>(value: T): Signal<T>;
60
+ export declare function useSignal<T = undefined>(): Signal<T | undefined>;
61
+ export declare function useComputed<T>(compute: () => T): ReadonlySignal<T>;
62
+ export declare function useSignalEffect(cb: () => void | (() => void)): void;
63
+ export {};
@@ -0,0 +1,18 @@
1
+ import { ReadonlySignal, Signal } from "@preact/signals-core";
2
+ interface ShowProps<T = boolean> {
3
+ when: Signal<T> | ReadonlySignal<T>;
4
+ fallback?: JSX.Element;
5
+ children: JSX.Element | ((value: T) => JSX.Element);
6
+ }
7
+ export declare function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null;
8
+ interface ForProps<T> {
9
+ each: Signal<Array<T>> | ReadonlySignal<Array<T>> | (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);
10
+ fallback?: JSX.Element;
11
+ children: (value: T, index: number) => JSX.Element;
12
+ }
13
+ export declare function For<T>(props: ForProps<T>): JSX.Element | null;
14
+ export declare function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>): Signal<Signal<T> | ReadonlySignal<T>>;
15
+ export declare function useSignalRef<T>(value: T): Signal<T> & {
16
+ current: T;
17
+ };
18
+ export {};
@@ -0,0 +1 @@
1
+ var r=require("@preact/signals-react"),n=require("@preact/signals-react/runtime"),t=require("react"),e={configurable:!0,get:function(){return this.value},set:function(r){this.value=r}};exports.For=function(r){n.useSignals();var e=t.useMemo(function(){return new Map},[]),u=("function"==typeof r.each?r.each():r.each).value;if(!u.length)return r.fallback||null;var i=u.map(function(n,t){if(!e.has(n))e.set(n,r.children(n,t));return e.get(n)});return t.createElement(t.Fragment,{children:i})};exports.Show=function(r){n.useSignals();var t=r.when.value;if(!t)return r.fallback||null;else return"function"==typeof r.children?r.children(t):r.children};exports.useLiveSignal=function(n){var t=r.useSignal(n);if(t.peek()!==n)t.value=n;return t};exports.useSignalRef=function(n){var t=r.useSignal(n);if(!("current"in t))Object.defineProperty(t,"current",e);return t};//# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sources":["../src/index.ts"],"sourcesContent":["import { ReadonlySignal, Signal } from \"@preact/signals-core\";\nimport { useSignal } from \"@preact/signals-react\";\nimport { useSignals } from \"@preact/signals-react/runtime\";\nimport { Fragment, createElement, useMemo } from \"react\";\n\ninterface ShowProps<T = boolean> {\n\twhen: Signal<T> | ReadonlySignal<T>;\n\tfallback?: JSX.Element;\n\tchildren: JSX.Element | ((value: T) => JSX.Element);\n}\n\nexport function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst value = props.when.value;\n\tif (!value) return props.fallback || null;\n\treturn typeof props.children === \"function\"\n\t\t? props.children(value)\n\t\t: props.children;\n}\n\ninterface ForProps<T> {\n\teach:\n\t\t| Signal<Array<T>>\n\t\t| ReadonlySignal<Array<T>>\n\t\t| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);\n\tfallback?: JSX.Element;\n\tchildren: (value: T, index: number) => JSX.Element;\n}\n\nexport function For<T>(props: ForProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst cache = useMemo(() => new Map(), []);\n\tlet list = (\n\t\t(typeof props.each === \"function\" ? props.each() : props.each) as Signal<\n\t\t\tArray<T>\n\t\t>\n\t).value;\n\n\tif (!list.length) return props.fallback || null;\n\n\tconst items = list.map((value, key) => {\n\t\tif (!cache.has(value)) {\n\t\t\tcache.set(value, props.children(value, key));\n\t\t}\n\t\treturn cache.get(value);\n\t});\n\treturn createElement(Fragment, { children: items });\n}\n\nexport function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {\n\tconst s = useSignal(value);\n\tif (s.peek() !== value) s.value = value;\n\treturn s;\n}\n\nexport function useSignalRef<T>(value: T) {\n\tconst ref = useSignal(value) as Signal<T> & { current: T };\n\tif (!(\"current\" in ref))\n\t\tObject.defineProperty(ref, \"current\", refSignalProto);\n\treturn ref;\n}\nconst refSignalProto = {\n\tconfigurable: true,\n\tget(this: Signal) {\n\t\treturn this.value;\n\t},\n\tset(this: Signal, v: any) {\n\t\tthis.value = v;\n\t},\n};\n"],"names":["refSignalProto","configurable","get","this","value","set","v","exports","For","props","useSignals","cache","useMemo","Map","list","each","length","fallback","items","map","key","has","children","createElement","Fragment","Show","when","useLiveSignal","s","useSignal","peek","useSignalRef","ref","Object","defineProperty"],"mappings":"qGA6DMA,EAAiB,CACtBC,cAAc,EACdC,IAAG,WACF,OAAOC,KAAKC,KACb,EACAC,aAAkBC,GACjBH,KAAKC,MAAQE,CACd,GACAC,QAAAC,aAxCsBC,GACtBC,EAAAA,aACA,IAAMC,EAAQC,EAAAA,QAAQ,WAAM,OAAA,IAAIC,GAAK,EAAE,IACnCC,GACoB,mBAAfL,EAAMM,KAAsBN,EAAMM,OAASN,EAAMM,MAGxDX,MAEF,IAAKU,EAAKE,OAAQ,OAAOP,EAAMQ,UAAY,KAE3C,IAAMC,EAAQJ,EAAKK,IAAI,SAACf,EAAOgB,GAC9B,IAAKT,EAAMU,IAAIjB,GACdO,EAAMN,IAAID,EAAOK,EAAMa,SAASlB,EAAOgB,IAExC,OAAOT,EAAMT,IAAIE,EAClB,GACA,OAAOmB,EAAaA,cAACC,EAAQA,SAAE,CAAEF,SAAUJ,GAC5C,EAsBCX,QAAAkB,cA1DiChB,GACjCC,EAAAA,aACA,IAAMN,EAAQK,EAAMiB,KAAKtB,MACzB,IAAKA,EAAO,OAAOK,EAAMQ,UAAY,UACrC,MAAiC,mBAAnBR,EAAMa,SACjBb,EAAMa,SAASlB,GACfK,EAAMa,QACV,EAmDCf,QAAAoB,cApBe,SAAiBvB,GAChC,IAAMwB,EAAIC,EAAAA,UAAUzB,GACpB,GAAIwB,EAAEE,SAAW1B,EAAOwB,EAAExB,MAAQA,EAClC,OAAOwB,CACR,EAgBCrB,QAAAwB,sBAd+B3B,GAC/B,IAAM4B,EAAMH,EAASA,UAACzB,GACtB,KAAM,YAAa4B,GAClBC,OAAOC,eAAeF,EAAK,UAAWhC,GACvC,OAAOgC,CACR"}
@@ -0,0 +1 @@
1
+ !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("@preact/signals-react"),require("@preact/signals-react/runtime"),require("react")):"function"==typeof define&&define.amd?define(["exports","@preact/signals-react","@preact/signals-react/runtime","react"],n):n((e||self).reactSignalsutils={},e.signalsReact,e.reactSignalsRuntime,e.react)}(this,function(e,n,t,r){var i={configurable:!0,get:function(){return this.value},set:function(e){this.value=e}};e.For=function(e){t.useSignals();var n=r.useMemo(function(){return new Map},[]),i=("function"==typeof e.each?e.each():e.each).value;if(!i.length)return e.fallback||null;var u=i.map(function(t,r){if(!n.has(t))n.set(t,e.children(t,r));return n.get(t)});return r.createElement(r.Fragment,{children:u})};e.Show=function(e){t.useSignals();var n=e.when.value;if(!n)return e.fallback||null;else return"function"==typeof e.children?e.children(n):e.children};e.useLiveSignal=function(e){var t=n.useSignal(e);if(t.peek()!==e)t.value=e;return t};e.useSignalRef=function(e){var t=n.useSignal(e);if(!("current"in t))Object.defineProperty(t,"current",i);return t}});//# sourceMappingURL=utils.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.min.js","sources":["../src/index.ts"],"sourcesContent":["import { ReadonlySignal, Signal } from \"@preact/signals-core\";\nimport { useSignal } from \"@preact/signals-react\";\nimport { useSignals } from \"@preact/signals-react/runtime\";\nimport { Fragment, createElement, useMemo } from \"react\";\n\ninterface ShowProps<T = boolean> {\n\twhen: Signal<T> | ReadonlySignal<T>;\n\tfallback?: JSX.Element;\n\tchildren: JSX.Element | ((value: T) => JSX.Element);\n}\n\nexport function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst value = props.when.value;\n\tif (!value) return props.fallback || null;\n\treturn typeof props.children === \"function\"\n\t\t? props.children(value)\n\t\t: props.children;\n}\n\ninterface ForProps<T> {\n\teach:\n\t\t| Signal<Array<T>>\n\t\t| ReadonlySignal<Array<T>>\n\t\t| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);\n\tfallback?: JSX.Element;\n\tchildren: (value: T, index: number) => JSX.Element;\n}\n\nexport function For<T>(props: ForProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst cache = useMemo(() => new Map(), []);\n\tlet list = (\n\t\t(typeof props.each === \"function\" ? props.each() : props.each) as Signal<\n\t\t\tArray<T>\n\t\t>\n\t).value;\n\n\tif (!list.length) return props.fallback || null;\n\n\tconst items = list.map((value, key) => {\n\t\tif (!cache.has(value)) {\n\t\t\tcache.set(value, props.children(value, key));\n\t\t}\n\t\treturn cache.get(value);\n\t});\n\treturn createElement(Fragment, { children: items });\n}\n\nexport function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {\n\tconst s = useSignal(value);\n\tif (s.peek() !== value) s.value = value;\n\treturn s;\n}\n\nexport function useSignalRef<T>(value: T) {\n\tconst ref = useSignal(value) as Signal<T> & { current: T };\n\tif (!(\"current\" in ref))\n\t\tObject.defineProperty(ref, \"current\", refSignalProto);\n\treturn ref;\n}\nconst refSignalProto = {\n\tconfigurable: true,\n\tget(this: Signal) {\n\t\treturn this.value;\n\t},\n\tset(this: Signal, v: any) {\n\t\tthis.value = v;\n\t},\n};\n"],"names":["refSignalProto","configurable","get","this","value","set","v","exports","For","props","useSignals","cache","useMemo","Map","list","each","length","fallback","items","map","key","has","children","createElement","Fragment","Show","when","useLiveSignal","s","useSignal","peek","useSignalRef","ref","Object","defineProperty"],"mappings":"ybA6DA,IAAMA,EAAiB,CACtBC,cAAc,EACdC,IAAG,WACF,OAAOC,KAAKC,KACb,EACAC,aAAkBC,GACjBH,KAAKC,MAAQE,CACd,GACAC,EAAAC,aAxCsBC,GACtBC,EAAAA,aACA,IAAMC,EAAQC,EAAAA,QAAQ,WAAM,OAAA,IAAIC,GAAK,EAAE,IACnCC,GACoB,mBAAfL,EAAMM,KAAsBN,EAAMM,OAASN,EAAMM,MAGxDX,MAEF,IAAKU,EAAKE,OAAQ,OAAOP,EAAMQ,UAAY,KAE3C,IAAMC,EAAQJ,EAAKK,IAAI,SAACf,EAAOgB,GAC9B,IAAKT,EAAMU,IAAIjB,GACdO,EAAMN,IAAID,EAAOK,EAAMa,SAASlB,EAAOgB,IAExC,OAAOT,EAAMT,IAAIE,EAClB,GACA,OAAOmB,EAAaA,cAACC,EAAQA,SAAE,CAAEF,SAAUJ,GAC5C,EAsBCX,EAAAkB,cA1DiChB,GACjCC,EAAAA,aACA,IAAMN,EAAQK,EAAMiB,KAAKtB,MACzB,IAAKA,EAAO,OAAOK,EAAMQ,UAAY,UACrC,MAAiC,mBAAnBR,EAAMa,SACjBb,EAAMa,SAASlB,GACfK,EAAMa,QACV,EAmDCf,EAAAoB,cApBe,SAAiBvB,GAChC,IAAMwB,EAAIC,EAAAA,UAAUzB,GACpB,GAAIwB,EAAEE,SAAW1B,EAAOwB,EAAExB,MAAQA,EAClC,OAAOwB,CACR,EAgBCrB,EAAAwB,sBAd+B3B,GAC/B,IAAM4B,EAAMH,EAASA,UAACzB,GACtB,KAAM,YAAa4B,GAClBC,OAAOC,eAAeF,EAAK,UAAWhC,GACvC,OAAOgC,CACR,CASC"}
@@ -0,0 +1 @@
1
+ import{useSignal}from"@preact/signals-react";import{useSignals as t}from"@preact/signals-react/runtime";import{useMemo as n,createElement as r,Fragment as e}from"react";function c(n){t();const r=n.when.value;if(!r)return n.fallback||null;else return"function"==typeof n.children?n.children(r):n.children}function i(c){t();const i=n(()=>new Map,[]);let o=("function"==typeof c.each?c.each():c.each).value;if(!o.length)return c.fallback||null;const u=o.map((t,n)=>{if(!i.has(t))i.set(t,c.children(t,n));return i.get(t)});return r(e,{children:u})}function o(t){const n=useSignal(t);if(n.peek()!==t)n.value=t;return n}function u(t){const n=useSignal(t);if(!("current"in n))Object.defineProperty(n,"current",f);return n}const f={configurable:!0,get(){return this.value},set(t){this.value=t}};export{i as For,c as Show,o as useLiveSignal,u as useSignalRef};//# sourceMappingURL=utils.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.mjs","sources":["../src/index.ts"],"sourcesContent":["import { ReadonlySignal, Signal } from \"@preact/signals-core\";\nimport { useSignal } from \"@preact/signals-react\";\nimport { useSignals } from \"@preact/signals-react/runtime\";\nimport { Fragment, createElement, useMemo } from \"react\";\n\ninterface ShowProps<T = boolean> {\n\twhen: Signal<T> | ReadonlySignal<T>;\n\tfallback?: JSX.Element;\n\tchildren: JSX.Element | ((value: T) => JSX.Element);\n}\n\nexport function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst value = props.when.value;\n\tif (!value) return props.fallback || null;\n\treturn typeof props.children === \"function\"\n\t\t? props.children(value)\n\t\t: props.children;\n}\n\ninterface ForProps<T> {\n\teach:\n\t\t| Signal<Array<T>>\n\t\t| ReadonlySignal<Array<T>>\n\t\t| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);\n\tfallback?: JSX.Element;\n\tchildren: (value: T, index: number) => JSX.Element;\n}\n\nexport function For<T>(props: ForProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst cache = useMemo(() => new Map(), []);\n\tlet list = (\n\t\t(typeof props.each === \"function\" ? props.each() : props.each) as Signal<\n\t\t\tArray<T>\n\t\t>\n\t).value;\n\n\tif (!list.length) return props.fallback || null;\n\n\tconst items = list.map((value, key) => {\n\t\tif (!cache.has(value)) {\n\t\t\tcache.set(value, props.children(value, key));\n\t\t}\n\t\treturn cache.get(value);\n\t});\n\treturn createElement(Fragment, { children: items });\n}\n\nexport function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {\n\tconst s = useSignal(value);\n\tif (s.peek() !== value) s.value = value;\n\treturn s;\n}\n\nexport function useSignalRef<T>(value: T) {\n\tconst ref = useSignal(value) as Signal<T> & { current: T };\n\tif (!(\"current\" in ref))\n\t\tObject.defineProperty(ref, \"current\", refSignalProto);\n\treturn ref;\n}\nconst refSignalProto = {\n\tconfigurable: true,\n\tget(this: Signal) {\n\t\treturn this.value;\n\t},\n\tset(this: Signal, v: any) {\n\t\tthis.value = v;\n\t},\n};\n"],"names":["useSignal","useSignals","useMemo","createElement","Fragment","Show","props","value","when","fallback","children","For","cache","Map","list","each","length","items","map","key","has","set","get","useLiveSignal","s","peek","useSignalRef","ref","Object","defineProperty","refSignalProto","configurable","v","this"],"mappings":"OAWgBA,cAAA,6CAAAC,MAAA,kDAAAC,mBAAAC,cAAAC,MAAA,QAAA,SAAAC,EAAkBC,GACjCL,IACA,MAAMM,EAAQD,EAAME,KAAKD,MACzB,IAAKA,EAAO,OAAOD,EAAMG,UAAY,UACrC,MAAiC,mBAAnBH,EAAMI,SACjBJ,EAAMI,SAASH,GACfD,EAAMI,QACV,CAWgB,SAAAC,EAAOL,GACtBL,IACA,MAAMW,EAAQV,EAAQ,IAAM,IAAIW,IAAO,IACvC,IAAIC,GACoB,mBAAfR,EAAMS,KAAsBT,EAAMS,OAAST,EAAMS,MAGxDR,MAEF,IAAKO,EAAKE,OAAQ,OAAOV,EAAMG,UAAY,KAE3C,MAAMQ,EAAQH,EAAKI,IAAI,CAACX,EAAOY,KAC9B,IAAKP,EAAMQ,IAAIb,GACdK,EAAMS,IAAId,EAAOD,EAAMI,SAASH,EAAOY,IAExC,OAAOP,EAAMU,IAAIf,EAAK,GAEvB,OAAOJ,EAAcC,EAAU,CAAEM,SAAUO,GAC5C,CAEM,SAAUM,EAAiBhB,GAChC,MAAMiB,EAAIxB,UAAUO,GACpB,GAAIiB,EAAEC,SAAWlB,EAAOiB,EAAEjB,MAAQA,EAClC,OAAOiB,CACR,CAEgB,SAAAE,EAAgBnB,GAC/B,MAAMoB,EAAM3B,UAAUO,GACtB,KAAM,YAAaoB,GAClBC,OAAOC,eAAeF,EAAK,UAAWG,GACvC,OAAOH,CACR,CACA,MAAMG,EAAiB,CACtBC,cAAc,EACdT,MACC,YAAYf,KACb,EACAc,IAAkBW,GACjBC,KAAK1B,MAAQyB,CACd,UACArB,SAAAN,UAAAkB,mBAAAG"}
@@ -0,0 +1 @@
1
+ import{useSignal}from"@preact/signals-react";import{useSignals as r}from"@preact/signals-react/runtime";import{useMemo as n,createElement as t,Fragment as e}from"react";function i(n){r();var t=n.when.value;if(!t)return n.fallback||null;else return"function"==typeof n.children?n.children(t):n.children}function u(i){r();var u=n(function(){return new Map},[]),f=("function"==typeof i.each?i.each():i.each).value;if(!f.length)return i.fallback||null;var c=f.map(function(r,n){if(!u.has(r))u.set(r,i.children(r,n));return u.get(r)});return t(e,{children:c})}function f(r){var n=useSignal(r);if(n.peek()!==r)n.value=r;return n}function c(r){var n=useSignal(r);if(!("current"in n))Object.defineProperty(n,"current",o);return n}var o={configurable:!0,get:function(){return this.value},set:function(r){this.value=r}};export{u as For,i as Show,f as useLiveSignal,c as useSignalRef};//# sourceMappingURL=utils.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.module.js","sources":["../src/index.ts"],"sourcesContent":["import { ReadonlySignal, Signal } from \"@preact/signals-core\";\nimport { useSignal } from \"@preact/signals-react\";\nimport { useSignals } from \"@preact/signals-react/runtime\";\nimport { Fragment, createElement, useMemo } from \"react\";\n\ninterface ShowProps<T = boolean> {\n\twhen: Signal<T> | ReadonlySignal<T>;\n\tfallback?: JSX.Element;\n\tchildren: JSX.Element | ((value: T) => JSX.Element);\n}\n\nexport function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst value = props.when.value;\n\tif (!value) return props.fallback || null;\n\treturn typeof props.children === \"function\"\n\t\t? props.children(value)\n\t\t: props.children;\n}\n\ninterface ForProps<T> {\n\teach:\n\t\t| Signal<Array<T>>\n\t\t| ReadonlySignal<Array<T>>\n\t\t| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);\n\tfallback?: JSX.Element;\n\tchildren: (value: T, index: number) => JSX.Element;\n}\n\nexport function For<T>(props: ForProps<T>): JSX.Element | null {\n\tuseSignals();\n\tconst cache = useMemo(() => new Map(), []);\n\tlet list = (\n\t\t(typeof props.each === \"function\" ? props.each() : props.each) as Signal<\n\t\t\tArray<T>\n\t\t>\n\t).value;\n\n\tif (!list.length) return props.fallback || null;\n\n\tconst items = list.map((value, key) => {\n\t\tif (!cache.has(value)) {\n\t\t\tcache.set(value, props.children(value, key));\n\t\t}\n\t\treturn cache.get(value);\n\t});\n\treturn createElement(Fragment, { children: items });\n}\n\nexport function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {\n\tconst s = useSignal(value);\n\tif (s.peek() !== value) s.value = value;\n\treturn s;\n}\n\nexport function useSignalRef<T>(value: T) {\n\tconst ref = useSignal(value) as Signal<T> & { current: T };\n\tif (!(\"current\" in ref))\n\t\tObject.defineProperty(ref, \"current\", refSignalProto);\n\treturn ref;\n}\nconst refSignalProto = {\n\tconfigurable: true,\n\tget(this: Signal) {\n\t\treturn this.value;\n\t},\n\tset(this: Signal, v: any) {\n\t\tthis.value = v;\n\t},\n};\n"],"names":["Show","props","useSignals","value","when","fallback","children","For","cache","useMemo","Map","list","each","length","items","map","key","has","set","get","createElement","Fragment","useLiveSignal","s","useSignal","peek","useSignalRef","ref","Object","defineProperty","refSignalProto","configurable","this","v"],"mappings":"kLAWgBA,EAAkBC,GACjCC,IACA,IAAMC,EAAQF,EAAMG,KAAKD,MACzB,IAAKA,EAAO,OAAOF,EAAMI,UAAY,UACrC,MAAiC,mBAAnBJ,EAAMK,SACjBL,EAAMK,SAASH,GACfF,EAAMK,QACV,UAWgBC,EAAON,GACtBC,IACA,IAAMM,EAAQC,EAAQ,WAAM,OAAA,IAAIC,GAAK,EAAE,IACnCC,GACoB,mBAAfV,EAAMW,KAAsBX,EAAMW,OAASX,EAAMW,MAGxDT,MAEF,IAAKQ,EAAKE,OAAQ,OAAOZ,EAAMI,UAAY,KAE3C,IAAMS,EAAQH,EAAKI,IAAI,SAACZ,EAAOa,GAC9B,IAAKR,EAAMS,IAAId,GACdK,EAAMU,IAAIf,EAAOF,EAAMK,SAASH,EAAOa,IAExC,OAAOR,EAAMW,IAAIhB,EAClB,GACA,OAAOiB,EAAcC,EAAU,CAAEf,SAAUQ,GAC5C,CAEgB,SAAAQ,EAAiBnB,GAChC,IAAMoB,EAAIC,UAAUrB,GACpB,GAAIoB,EAAEE,SAAWtB,EAAOoB,EAAEpB,MAAQA,EAClC,OAAOoB,CACR,UAEgBG,EAAgBvB,GAC/B,IAAMwB,EAAMH,UAAUrB,GACtB,KAAM,YAAawB,GAClBC,OAAOC,eAAeF,EAAK,UAAWG,GACvC,OAAOH,CACR,CACA,IAAMG,EAAiB,CACtBC,cAAc,EACdZ,IAAG,WACF,OAAOa,KAAK7B,KACb,EACAe,aAAkBe,GACjBD,KAAK7B,MAAQ8B,CACd,UACA1B,SAAAP,UAAAsB,mBAAAI"}
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@preact/signals-react-utils",
3
+ "description": "Sub package for @preact/signals-react that contains some useful utilities",
4
+ "private": true,
5
+ "amdName": "reactSignalsutils",
6
+ "main": "dist/utils.js",
7
+ "module": "dist/utils.module.js",
8
+ "unpkg": "dist/utils.min.js",
9
+ "types": "dist/index.d.ts",
10
+ "source": "src/index.ts",
11
+ "mangle": "../../../mangle.json",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "browser": "./dist/utils.module.js",
16
+ "import": "./dist/utils.mjs",
17
+ "require": "./dist/utils.js"
18
+ }
19
+ },
20
+ "dependencies": {
21
+ "@preact/signals-core": "workspace:^1.3.0"
22
+ },
23
+ "peerDependencies": {
24
+ "@preact/signals-react": "workspace:*",
25
+ "react": "^16.14.0 || 17.x || 18.x || 19.x"
26
+ }
27
+ }
@@ -0,0 +1,70 @@
1
+ import { ReadonlySignal, Signal } from "@preact/signals-core";
2
+ import { useSignal } from "@preact/signals-react";
3
+ import { useSignals } from "@preact/signals-react/runtime";
4
+ import { Fragment, createElement, useMemo } from "react";
5
+
6
+ interface ShowProps<T = boolean> {
7
+ when: Signal<T> | ReadonlySignal<T>;
8
+ fallback?: JSX.Element;
9
+ children: JSX.Element | ((value: T) => JSX.Element);
10
+ }
11
+
12
+ export function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {
13
+ useSignals();
14
+ const value = props.when.value;
15
+ if (!value) return props.fallback || null;
16
+ return typeof props.children === "function"
17
+ ? props.children(value)
18
+ : props.children;
19
+ }
20
+
21
+ interface ForProps<T> {
22
+ each:
23
+ | Signal<Array<T>>
24
+ | ReadonlySignal<Array<T>>
25
+ | (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);
26
+ fallback?: JSX.Element;
27
+ children: (value: T, index: number) => JSX.Element;
28
+ }
29
+
30
+ export function For<T>(props: ForProps<T>): JSX.Element | null {
31
+ useSignals();
32
+ const cache = useMemo(() => new Map(), []);
33
+ let list = (
34
+ (typeof props.each === "function" ? props.each() : props.each) as Signal<
35
+ Array<T>
36
+ >
37
+ ).value;
38
+
39
+ if (!list.length) return props.fallback || null;
40
+
41
+ const items = list.map((value, key) => {
42
+ if (!cache.has(value)) {
43
+ cache.set(value, props.children(value, key));
44
+ }
45
+ return cache.get(value);
46
+ });
47
+ return createElement(Fragment, { children: items });
48
+ }
49
+
50
+ export function useLiveSignal<T>(value: Signal<T> | ReadonlySignal<T>) {
51
+ const s = useSignal(value);
52
+ if (s.peek() !== value) s.value = value;
53
+ return s;
54
+ }
55
+
56
+ export function useSignalRef<T>(value: T) {
57
+ const ref = useSignal(value) as Signal<T> & { current: T };
58
+ if (!("current" in ref))
59
+ Object.defineProperty(ref, "current", refSignalProto);
60
+ return ref;
61
+ }
62
+ const refSignalProto = {
63
+ configurable: true,
64
+ get(this: Signal) {
65
+ return this.value;
66
+ },
67
+ set(this: Signal, v: any) {
68
+ this.value = v;
69
+ },
70
+ };