solid-state-tools 1.3.0 → 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 +40 -16
- package/package.json +1 -1
- package/dist/atom.d.ts +0 -95
- package/dist/atom.d.ts.map +0 -1
- package/dist/atom.js +0 -75
- package/dist/atom.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Solid State Tools
|
|
2
2
|
|
|
3
|
+
Links: [GitHub Repository](https://github.com/ReedSyllas/solid-state-tools), [NPM Package](https://www.npmjs.com/package/solid-state-tools).
|
|
4
|
+
|
|
3
5
|
Solid State Tools is a collection of simple utilities for managing [Solid JS](https://docs.solidjs.com/) state.
|
|
4
6
|
|
|
5
7
|
All features are intended to compliment Solid JS's existing state system, building upon the existing foundation.
|
|
@@ -29,12 +31,15 @@ const count: Atom<Signal<number>> = atom(createSignal(0));
|
|
|
29
31
|
|
|
30
32
|
console.log(count()); // 0
|
|
31
33
|
|
|
34
|
+
// Sets count to 100.
|
|
32
35
|
count(100);
|
|
33
36
|
console.log(count()); // 100
|
|
34
37
|
|
|
38
|
+
// Sets count to its current value plus one.
|
|
35
39
|
count(count() + 1);
|
|
36
40
|
console.log(count()); // 101
|
|
37
41
|
|
|
42
|
+
// Sets count to its current value plus one (alternative syntax).
|
|
38
43
|
count((c) => c + 1);
|
|
39
44
|
console.log(count()); // 102
|
|
40
45
|
```
|
|
@@ -56,6 +61,14 @@ const count: Asig<number> = asig(0);
|
|
|
56
61
|
const count: Atom<Signal<number>> = atom(createSignal(0));
|
|
57
62
|
```
|
|
58
63
|
|
|
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).
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const list = asig([], { equals: false });
|
|
68
|
+
// is short for
|
|
69
|
+
const list = atom(createSignal([], { equals: false }));
|
|
70
|
+
```
|
|
71
|
+
|
|
59
72
|
## Couples (`createCouple`)
|
|
60
73
|
|
|
61
74
|
A signal can be summarized as a getter setter pair.
|
|
@@ -71,8 +84,8 @@ Why?
|
|
|
71
84
|
```ts
|
|
72
85
|
const [ _count, setCount ] = createSignal(0);
|
|
73
86
|
|
|
74
|
-
console.log(setCount(10)); //
|
|
75
|
-
console.log(setCount(x => x + 5)); //
|
|
87
|
+
console.log(setCount(10)); // 10
|
|
88
|
+
console.log(setCount(x => x + 5)); // 15
|
|
76
89
|
```
|
|
77
90
|
|
|
78
91
|
All of this is to say that creating custom signal pairs can be tedious.
|
|
@@ -99,26 +112,28 @@ const [ double, setDouble ] = [
|
|
|
99
112
|
];
|
|
100
113
|
```
|
|
101
114
|
|
|
102
|
-
With that,
|
|
115
|
+
With that, the following statements work (as is expected of a setter):
|
|
103
116
|
|
|
104
117
|
```ts
|
|
105
118
|
setDouble(10); // double: 10, count: 5
|
|
106
119
|
setDouble(x => x + 1); // double: 11, count: 5.5
|
|
107
|
-
console.log(setDouble(20)); //
|
|
120
|
+
console.log(setDouble(20)); // 20
|
|
108
121
|
```
|
|
109
122
|
|
|
110
|
-
But,
|
|
123
|
+
But, the crusty boilerplate to get it working is annoying as heck.
|
|
111
124
|
|
|
112
|
-
**Enter the `createCouple` utility
|
|
125
|
+
**Enter the `createCouple` utility.**
|
|
113
126
|
|
|
114
|
-
It accepts a getter and a
|
|
115
|
-
A
|
|
116
|
-
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.
|
|
130
|
+
See it in action:
|
|
117
131
|
|
|
118
132
|
```ts
|
|
119
133
|
const [ count, setCount ] = createSignal(0);
|
|
120
134
|
|
|
121
135
|
const [ double, setDouble ] = createCouple(
|
|
136
|
+
// The provided getter is automatically memoized.
|
|
122
137
|
() => count() * 2,
|
|
123
138
|
|
|
124
139
|
(newValue) => {
|
|
@@ -129,7 +144,7 @@ const [ double, setDouble ] = createCouple(
|
|
|
129
144
|
},
|
|
130
145
|
);
|
|
131
146
|
|
|
132
|
-
// Yet, we can still
|
|
147
|
+
// Yet, we can still inject a function.
|
|
133
148
|
setDouble(x => x + 2);
|
|
134
149
|
console.log(double(), count()); // 2 1
|
|
135
150
|
|
|
@@ -137,16 +152,25 @@ console.log(double(), count()); // 2 1
|
|
|
137
152
|
console.log(setDouble(10), count()); // 10 5
|
|
138
153
|
```
|
|
139
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
|
+
|
|
140
161
|
Much better, right?
|
|
141
162
|
|
|
142
163
|
> [!NOTE]
|
|
143
|
-
> The getter passed to `createCouple` is
|
|
144
|
-
>
|
|
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.
|
|
145
166
|
|
|
146
|
-
By the way!
|
|
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.
|
|
147
168
|
|
|
148
169
|
```ts
|
|
149
|
-
const double = atom(createCouple(
|
|
170
|
+
const double = atom(createCouple(() => count() * 2, (x) => setCount(x / 2)));
|
|
171
|
+
|
|
172
|
+
double() // read
|
|
173
|
+
double(10) // write
|
|
150
174
|
```
|
|
151
175
|
|
|
152
176
|
## Atomic couples (`apair`)
|
|
@@ -162,6 +186,6 @@ const double = atom(createCouple(() => count() * 2, (double) => count(double / 2
|
|
|
162
186
|
# Conclusion
|
|
163
187
|
|
|
164
188
|
Perhaps you can see the power of the above primitives.
|
|
165
|
-
Not
|
|
189
|
+
Not just what they do individually, but how they work together.
|
|
166
190
|
|
|
167
|
-
More utilities for this library are in the works and
|
|
191
|
+
More utilities for this library are in the works and are coming soon.
|
package/package.json
CHANGED
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>(value: 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
|
package/dist/atom.d.ts.map
DELETED
|
@@ -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,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAmBpE;;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,75 +0,0 @@
|
|
|
1
|
-
import { createMemo, createSignal, untrack } from "solid-js";
|
|
2
|
-
import { isDev } from "solid-js/web";
|
|
3
|
-
export function atom(value) {
|
|
4
|
-
if (isDev) {
|
|
5
|
-
// Assert that the input is valid.
|
|
6
|
-
// For production, these checks are skipped for performance.
|
|
7
|
-
if (!Array.isArray(value)) {
|
|
8
|
-
throw new Error(`expected a getter setter pair as an array, but got ${typeof value}`);
|
|
9
|
-
}
|
|
10
|
-
if (typeof value[0] !== "function") {
|
|
11
|
-
throw new Error(`expected a getter function, but got ${typeof value[0]}`);
|
|
12
|
-
}
|
|
13
|
-
if (typeof value[1] !== "function") {
|
|
14
|
-
throw new Error(`expected a setter function, but got ${typeof value[1]}`);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
return (...args) => (args.length === 0) ? value[0]() : value[1](...args);
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Create a signal from a cosignal.
|
|
21
|
-
*
|
|
22
|
-
* ### Example
|
|
23
|
-
* ```
|
|
24
|
-
* const [ count, setCount ] = createSignal(0);
|
|
25
|
-
* const [ double, setDouble ] = createSignalPair([
|
|
26
|
-
* () => count() * 2,
|
|
27
|
-
* (x) => void setCount(x / 2),
|
|
28
|
-
* ]);
|
|
29
|
-
*
|
|
30
|
-
* double(x => x + 2);
|
|
31
|
-
* console.log(double(), count()); // 2 1
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
export function createCouple(getter, setter) {
|
|
35
|
-
if (isDev) {
|
|
36
|
-
// Assert that the input is valid.
|
|
37
|
-
// For production, these checks are skipped for performance.
|
|
38
|
-
if (typeof getter !== "function") {
|
|
39
|
-
throw new Error(`expected getter to be a function, but got ${typeof getter}`);
|
|
40
|
-
}
|
|
41
|
-
if (typeof setter !== "function") {
|
|
42
|
-
throw new Error(`expected setter to be a function, but got ${typeof setter}`);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const get = createMemo(getter);
|
|
46
|
-
const set = ((source) => {
|
|
47
|
-
const value = (typeof source === "function") ? source(untrack(get)) : source;
|
|
48
|
-
setter(value);
|
|
49
|
-
return value;
|
|
50
|
-
});
|
|
51
|
-
return [get, set];
|
|
52
|
-
}
|
|
53
|
-
export function asig(value, options) {
|
|
54
|
-
return atom(createSignal(value, options));
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Create an atomic cosignal pair.
|
|
58
|
-
* Short for `atom(createCouple(...))`.
|
|
59
|
-
*
|
|
60
|
-
* ### Example
|
|
61
|
-
* ```
|
|
62
|
-
* const count = asig(0);
|
|
63
|
-
* const double = apair(() => count() * 2, (double) => void count(double / 2));
|
|
64
|
-
*
|
|
65
|
-
* count(10);
|
|
66
|
-
* console.log(count(), double()); // 10 20
|
|
67
|
-
*
|
|
68
|
-
* double(100);
|
|
69
|
-
* console.log(count(), double()); // 50 100
|
|
70
|
-
* ```
|
|
71
|
-
*/
|
|
72
|
-
export function apair(getter, setter) {
|
|
73
|
-
return atom(createCouple(getter, setter));
|
|
74
|
-
}
|
|
75
|
-
//# 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;AAwCrC,MAAM,UAAU,IAAI,CAAC,KAAc;IAClC,IAAI,KAAK,EAAE,CAAC;QACX,kCAAkC;QAClC,4DAA4D;QAE5D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,sDAAsD,OAAO,KAAK,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3E,CAAC;IACF,CAAC;IACD,OAAO,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAE,KAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE,KAAoB,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AACrH,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
package/dist/index.d.ts.map
DELETED
|
@@ -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
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"}
|