solid-state-tools 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,12 +31,15 @@ const count: Atom<Signal<number>> = atom(createSignal(0));
31
31
 
32
32
  console.log(count()); // 0
33
33
 
34
+ // Sets count to 100.
34
35
  count(100);
35
36
  console.log(count()); // 100
36
37
 
38
+ // Sets count to its current value plus one.
37
39
  count(count() + 1);
38
40
  console.log(count()); // 101
39
41
 
42
+ // Sets count to its current value plus one (alternative syntax).
40
43
  count((c) => c + 1);
41
44
  console.log(count()); // 102
42
45
  ```
@@ -58,7 +61,7 @@ const count: Asig<number> = asig(0);
58
61
  const count: Atom<Signal<number>> = atom(createSignal(0));
59
62
  ```
60
63
 
61
- The second parameter (optional) is the config object, which is simply forwarded to the `createSignal` call.
64
+ The second parameter (optional) is the config object, which is simply forwarded to [createSignal's options](https://docs.solidjs.com/reference/basic-reactivity/create-signal#options).
62
65
 
63
66
  ```ts
64
67
  const list = asig([], { equals: false });
@@ -81,8 +84,8 @@ Why?
81
84
  ```ts
82
85
  const [ _count, setCount ] = createSignal(0);
83
86
 
84
- console.log(setCount(10)); // Prints: 10
85
- console.log(setCount(x => x + 5)); // Prints: 15
87
+ console.log(setCount(10)); // 10
88
+ console.log(setCount(x => x + 5)); // 15
86
89
  ```
87
90
 
88
91
  All of this is to say that creating custom signal pairs can be tedious.
@@ -114,22 +117,23 @@ With that, the following statements work (as is expected of a setter):
114
117
  ```ts
115
118
  setDouble(10); // double: 10, count: 5
116
119
  setDouble(x => x + 1); // double: 11, count: 5.5
117
- console.log(setDouble(20)); // Prints: 20
120
+ console.log(setDouble(20)); // 20
118
121
  ```
119
122
 
120
123
  But, the crusty boilerplate to get it working is annoying as heck.
121
124
 
122
125
  **Enter the `createCouple` utility.**
123
126
 
124
- It accepts a getter and a co-setter and returns a signal.
125
- A co-setter is similar to a setter, except that it doesn't take a function nor does it return a value.
126
- Basically, it's the previous example without the boilerplate.
127
+ It accepts a getter and a writer and returns a signal.
128
+ A writer is similar to a setter, except that it doesn't accept a function as input nor does it return a value.
129
+ Basically, it's the setter of the previous example without all the boilerplate.
127
130
  See it in action:
128
131
 
129
132
  ```ts
130
133
  const [ count, setCount ] = createSignal(0);
131
134
 
132
135
  const [ double, setDouble ] = createCouple(
136
+ // The provided getter is automatically memoized.
133
137
  () => count() * 2,
134
138
 
135
139
  (newValue) => {
@@ -140,7 +144,7 @@ const [ double, setDouble ] = createCouple(
140
144
  },
141
145
  );
142
146
 
143
- // Yet, we can still pass a function in.
147
+ // Yet, we can still inject a function.
144
148
  setDouble(x => x + 2);
145
149
  console.log(double(), count()); // 2 1
146
150
 
@@ -148,16 +152,25 @@ console.log(double(), count()); // 2 1
148
152
  console.log(setDouble(10), count()); // 10 5
149
153
  ```
150
154
 
155
+ It can be succinctly rewritten into this:
156
+
157
+ ```ts
158
+ const [ double, setDouble ] = createCouple(() => count() * 2, (x) => setCount(x / 2));
159
+ ```
160
+
151
161
  Much better, right?
152
162
 
153
163
  > [!NOTE]
154
- > The getter passed to `createCouple` is always [memoized](https://docs.solidjs.com/concepts/derived-values/memos).
155
- > This immediately invokes the getter, so keep that in mind.
164
+ > The getter passed to `createCouple` is [memoized](https://docs.solidjs.com/concepts/derived-values/memos) unless otherwise set in the `options`.
165
+ > Memoization immediately invokes the getter, so keep that in mind because it can cause undesirable side-effects.
156
166
 
157
- By the way! A `createCouple` call, like any expression that evaluates to a signal, can be converted into an atom so that the getter and setter are merged into one.
167
+ By the way! The `createCouple` output, like any signal, can be converted into an atom so that the getter and setter are merged together. See [atom](#atoms-atom) for details.
158
168
 
159
169
  ```ts
160
- const double = atom(createCouple(/* ... */));
170
+ const double = atom(createCouple(() => count() * 2, (x) => setCount(x / 2)));
171
+
172
+ double() // read
173
+ double(10) // write
161
174
  ```
162
175
 
163
176
  ## Atomic couples (`apair`)
@@ -173,6 +186,6 @@ const double = atom(createCouple(() => count() * 2, (double) => count(double / 2
173
186
  # Conclusion
174
187
 
175
188
  Perhaps you can see the power of the above primitives.
176
- Not only in what they do, but also in how they combine.
189
+ Not just what they do individually, but how they work together.
177
190
 
178
- More utilities for this library are in the works and will be coming soon.
191
+ More utilities for this library are in the works and are coming soon.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solid-state-tools",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "A collection of Solid JS state utilities",
5
5
  "author": "Reed Syllas <reedsyllas@gmail.com>",
6
6
  "license": "ISC",
package/dist/atom.d.ts DELETED
@@ -1,95 +0,0 @@
1
- import { type Accessor, type Signal, type SignalOptions } from "solid-js";
2
- /**
3
- * Any tuple of two functions where the first accepts no arguments and the second accepts any amount.
4
- */
5
- export type SignalLike = readonly [() => any, (...args: any) => any];
6
- /**
7
- * An atom is a polymorphic function that calls one of two
8
- * functions depending on the number of arguments it has.
9
- *
10
- * If called with zero arguments, the first function is called.
11
- * Otherwise, the second function is called and all of the arguments are forwarded to it.
12
- */
13
- export type Atom<T extends SignalLike = SignalLike> = T[0] & T[1];
14
- /**
15
- * Combine a getter and setter function pair into one.
16
- *
17
- * Accepts a tuple of two functions.
18
- * The first is the getter, the second is the setter.
19
- * A new function is returned that, when called with zero arguments, calls the getter.
20
- * Otherwise, it calls the setter and forwards all of the arguments.
21
- *
22
- * ### Example
23
- * ```
24
- * const count = atom(createSignal(0));
25
- *
26
- * // Read
27
- * count();
28
- *
29
- * // Write
30
- * count(100);
31
- * count(x => x + 1);
32
- * count(count() + 1);
33
- * ```
34
- */
35
- export declare function atom<const T extends SignalLike>(signal: T): Atom<T>;
36
- /**
37
- * Similar to a signal setter, except it doesn't accept a mapping function nor return a result.
38
- */
39
- export type Cosetter<T> = (value: T) => void;
40
- /**
41
- * Create a signal from a cosignal.
42
- *
43
- * ### Example
44
- * ```
45
- * const [ count, setCount ] = createSignal(0);
46
- * const [ double, setDouble ] = createSignalPair([
47
- * () => count() * 2,
48
- * (x) => void setCount(x / 2),
49
- * ]);
50
- *
51
- * double(x => x + 2);
52
- * console.log(double(), count()); // 2 1
53
- * ```
54
- */
55
- export declare function createCouple<T>(getter: Accessor<T>, setter: Cosetter<T>): Signal<T>;
56
- /**
57
- * An atomic signal.
58
- * A signal where the getter and setter are combined into one function.
59
- */
60
- export type Asig<T> = Atom<Signal<T>>;
61
- /**
62
- * Create an atomic signal.
63
- * Short for `atom(createSignal(...))`.
64
- *
65
- * ### Example
66
- * ```
67
- * const count = asig(0);
68
- *
69
- * count(10);
70
- * console.log(count()); // 10
71
- *
72
- * count(x => x + 10);
73
- * console.log(count()); // 20
74
- * ```
75
- */
76
- export declare function asig<T>(): Asig<T | undefined>;
77
- export declare function asig<T>(value: T, options?: SignalOptions<T>): Asig<T>;
78
- /**
79
- * Create an atomic cosignal pair.
80
- * Short for `atom(createCouple(...))`.
81
- *
82
- * ### Example
83
- * ```
84
- * const count = asig(0);
85
- * const double = apair(() => count() * 2, (double) => void count(double / 2));
86
- *
87
- * count(10);
88
- * console.log(count(), double()); // 10 20
89
- *
90
- * double(100);
91
- * console.log(count(), double()); // 50 100
92
- * ```
93
- */
94
- export declare function apair<T>(getter: Accessor<T>, setter: Cosetter<T>): Asig<T>;
95
- //# sourceMappingURL=atom.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"atom.d.ts","sourceRoot":"","sources":["../src/atom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,QAAQ,EAAe,KAAK,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAK1H;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,CAAE,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,CAAE,CAAC;AAEvE;;;;;;GAMG;AACH,MAAM,MAAM,IAAI,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,UAAU,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAiBnE;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;AAE7C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAmBnF;AAID;;;GAGG;AACH,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AAC/C,wBAAgB,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAKvE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAE1E"}
package/dist/atom.js DELETED
@@ -1,97 +0,0 @@
1
- import { createMemo, createSignal, untrack } from "solid-js";
2
- import { isDev } from "solid-js/web";
3
- /**
4
- * Combine a getter and setter function pair into one.
5
- *
6
- * Accepts a tuple of two functions.
7
- * The first is the getter, the second is the setter.
8
- * A new function is returned that, when called with zero arguments, calls the getter.
9
- * Otherwise, it calls the setter and forwards all of the arguments.
10
- *
11
- * ### Example
12
- * ```
13
- * const count = atom(createSignal(0));
14
- *
15
- * // Read
16
- * count();
17
- *
18
- * // Write
19
- * count(100);
20
- * count(x => x + 1);
21
- * count(count() + 1);
22
- * ```
23
- */
24
- export function atom(signal) {
25
- if (isDev) {
26
- // Assert that the input is valid.
27
- // For production, these checks are skipped for performance.
28
- if (!Array.isArray(signal)) {
29
- throw new Error(`expected a getter setter pair as an array, but got ${typeof signal}`);
30
- }
31
- if (typeof signal[0] !== "function") {
32
- throw new Error(`expected a getter function, but got ${typeof signal[0]}`);
33
- }
34
- if (typeof signal[1] !== "function") {
35
- throw new Error(`expected a setter function, but got ${typeof signal[1]}`);
36
- }
37
- }
38
- const [getter, setter] = signal;
39
- return (...args) => (args.length === 0) ? getter() : setter(...args);
40
- }
41
- /**
42
- * Create a signal from a cosignal.
43
- *
44
- * ### Example
45
- * ```
46
- * const [ count, setCount ] = createSignal(0);
47
- * const [ double, setDouble ] = createSignalPair([
48
- * () => count() * 2,
49
- * (x) => void setCount(x / 2),
50
- * ]);
51
- *
52
- * double(x => x + 2);
53
- * console.log(double(), count()); // 2 1
54
- * ```
55
- */
56
- export function createCouple(getter, setter) {
57
- if (isDev) {
58
- // Assert that the input is valid.
59
- // For production, these checks are skipped for performance.
60
- if (typeof getter !== "function") {
61
- throw new Error(`expected getter to be a function, but got ${typeof getter}`);
62
- }
63
- if (typeof setter !== "function") {
64
- throw new Error(`expected setter to be a function, but got ${typeof setter}`);
65
- }
66
- }
67
- const get = createMemo(getter);
68
- const set = ((source) => {
69
- const value = (typeof source === "function") ? source(untrack(get)) : source;
70
- setter(value);
71
- return value;
72
- });
73
- return [get, set];
74
- }
75
- export function asig(value, options) {
76
- return atom(createSignal(value, options));
77
- }
78
- /**
79
- * Create an atomic cosignal pair.
80
- * Short for `atom(createCouple(...))`.
81
- *
82
- * ### Example
83
- * ```
84
- * const count = asig(0);
85
- * const double = apair(() => count() * 2, (double) => void count(double / 2));
86
- *
87
- * count(10);
88
- * console.log(count(), double()); // 10 20
89
- *
90
- * double(100);
91
- * console.log(count(), double()); // 50 100
92
- * ```
93
- */
94
- export function apair(getter, setter) {
95
- return atom(createCouple(getter, setter));
96
- }
97
- //# sourceMappingURL=atom.js.map
package/dist/atom.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"atom.js","sourceRoot":"","sources":["../src/atom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAA+D,MAAM,UAAU,CAAC;AAC1H,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAkBrC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,IAAI,CAA6B,MAAS;IACzD,IAAI,KAAK,EAAE,CAAC;QACX,kCAAkC;QAClC,4DAA4D;QAE5D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,sDAAsD,OAAO,MAAM,EAAE,CAAC,CAAC;QACxF,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC;IACF,CAAC;IACD,MAAM,CAAE,MAAM,EAAE,MAAM,CAAE,GAAG,MAAM,CAAC;IAClC,OAAO,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;AACjF,CAAC;AAOD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,YAAY,CAAI,MAAmB,EAAE,MAAmB;IACvE,IAAI,KAAK,EAAE,CAAC;QACX,kCAAkC;QAClC,4DAA4D;QAE5D,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,6CAA6C,OAAO,MAAM,EAAE,CAAC,CAAC;QAC/E,CAAC;QACD,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,6CAA6C,OAAO,MAAM,EAAE,CAAC,CAAC;QAC/E,CAAC;IACF,CAAC;IACD,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACvB,MAAM,KAAK,GAAG,CAAC,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAAE,MAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3F,MAAM,CAAC,KAAK,CAAC,CAAC;QACd,OAAO,KAAK,CAAC;IACd,CAAC,CAAc,CAAC;IAChB,OAAO,CAAE,GAAG,EAAE,GAAG,CAAW,CAAC;AAC9B,CAAC;AA2BD,MAAM,UAAU,IAAI,CAAI,KAAqB,EAAE,OAAsC;IACpF,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,KAAK,CAAI,MAAmB,EAAE,MAAmB;IAChE,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAC3C,CAAC"}
package/dist/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from "./atom.js";
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
package/dist/index.js DELETED
@@ -1,2 +0,0 @@
1
- export * from "./atom.js";
2
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}