solid-state-tools 1.0.1 → 1.0.3
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 +78 -0
- package/dist/atom.d.ts +62 -4
- package/dist/atom.d.ts.map +1 -1
- package/dist/atom.js +41 -7
- package/dist/atom.js.map +1 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Solid JS State Tools
|
|
2
|
+
|
|
3
|
+
This package is a collection of utilities for managing [Solid JS](https://docs.solidjs.com/) state.
|
|
4
|
+
|
|
5
|
+
## Atoms (`atom`)
|
|
6
|
+
|
|
7
|
+
Atoms combine the getter and setter of a [signal](https://docs.solidjs.com/concepts/signals) into one function.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
const count = atom(createSignal(0));
|
|
11
|
+
|
|
12
|
+
console.log(count()); // 0
|
|
13
|
+
|
|
14
|
+
count(100);
|
|
15
|
+
console.log(count()); // 100
|
|
16
|
+
|
|
17
|
+
count(count() + 1);
|
|
18
|
+
console.log(count()); // 101
|
|
19
|
+
|
|
20
|
+
count((c) => c + 1);
|
|
21
|
+
console.log(count()); // 102
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
When called with no arguments, the atom acts like the signal's getter. If an argument is passed, it is forwarded to the signal's setter. Note that `undefined` _is_ considered an argument and is forwarded to the setter, as desired.
|
|
25
|
+
|
|
26
|
+
Atoms simplify the boilerplate that comes with managing getters and setters separately. However, signals are still preferred for granular control of the getter and setter. Additionally, atoms incur a tiny performance cost. Thus, atoms do not replace signals. They coexist.
|
|
27
|
+
|
|
28
|
+
## Atomic signals (`asig`)
|
|
29
|
+
|
|
30
|
+
Because creating and wrapping a signal with `atom` is so common, a shorthand utility was created called `asig` (atomic signal).
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
const count = asig(0);
|
|
34
|
+
// is a shorthand for
|
|
35
|
+
const count = atom(createSignal(0));
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Co-signals (`createCosignal`)
|
|
39
|
+
|
|
40
|
+
A signal can be summarized as a getter setter pair. However, Solid JS's setters are more complex than just a function that accepts a new value for the signal. They can also accept a function which acts like a map predicate from the old value to the new one.
|
|
41
|
+
|
|
42
|
+
All this is to say that creating signals manually can be tedious since the setter has to handle this edge case. Co-signals make defining the getter setter pair easy.
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const [ count, setCount ] = createSignal(0);
|
|
46
|
+
const [ double, setDouble ] = createCosignal([
|
|
47
|
+
() => count() * 2,
|
|
48
|
+
|
|
49
|
+
// Notice how we don't need to handle `x` being a function here.
|
|
50
|
+
(x) => void setCount(x / 2),
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
// Yet, we can still pass a mapping function here.
|
|
54
|
+
double(x => x + 2);
|
|
55
|
+
console.log(double(), count()); // 12 6
|
|
56
|
+
|
|
57
|
+
// Or simply use it traditionally.
|
|
58
|
+
double(10);
|
|
59
|
+
console.log(double(), count()); // 10 5
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
It's important to note that the getter is not automatically memoized and should be wrapped with `createMemo`, when appropriate.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
const [ double, setDouble ] = createCosignal([
|
|
66
|
+
// Memoize to reduce extra computation.
|
|
67
|
+
createMemo(() => count() * 2),
|
|
68
|
+
/* ... */
|
|
69
|
+
]);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Finally, co-signals can be wrapped with `atom`, of course.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
const double = atom(createCosignal(/* ... */));
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
To be clear, `createCosignal` and `createSignal` return the same kind of value and therefore should work in every situation native signals do.
|
package/dist/atom.d.ts
CHANGED
|
@@ -1,19 +1,77 @@
|
|
|
1
1
|
import { 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
|
+
*/
|
|
2
5
|
export type Atomical = 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
|
+
*/
|
|
3
13
|
export type Atom<T extends Atomical = Atomical> = 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
|
+
*/
|
|
4
35
|
export declare function atom<const T extends Atomical>(value: T): Atom<T>;
|
|
36
|
+
/**
|
|
37
|
+
* An atomic signal.
|
|
38
|
+
* A signal where the getter and setter are combined into one function.
|
|
39
|
+
*/
|
|
5
40
|
export type Asig<T> = Atom<Signal<T>>;
|
|
6
41
|
/**
|
|
7
|
-
*
|
|
42
|
+
* Create an atomic signal.
|
|
43
|
+
* Shorthand for `atom(createSignal(...))`.
|
|
44
|
+
*
|
|
45
|
+
* ### Example
|
|
46
|
+
* ```
|
|
47
|
+
* const count = asig(0);
|
|
48
|
+
* ```
|
|
8
49
|
*/
|
|
9
50
|
export declare function asig<T>(): Atom<Signal<T | undefined>>;
|
|
10
51
|
export declare function asig<T>(value: T, options?: SignalOptions<T>): Atom<Signal<T>>;
|
|
11
|
-
|
|
52
|
+
/**
|
|
53
|
+
* A getter setter pair.
|
|
54
|
+
* While similar to `Signal`, the setter of
|
|
55
|
+
* `Cosignal` does not accept a mapping function.
|
|
56
|
+
*/
|
|
57
|
+
export type Cosignal<T> = [
|
|
12
58
|
() => T,
|
|
13
59
|
(value: T) => T
|
|
14
60
|
];
|
|
15
61
|
/**
|
|
16
|
-
*
|
|
62
|
+
* Create signal from a getter/setter tuple.
|
|
63
|
+
*
|
|
64
|
+
* ### Example
|
|
65
|
+
* ```
|
|
66
|
+
* const [ count, setCount ] = createSignal(0);
|
|
67
|
+
* const [ double, setDouble ] = createCosignal([
|
|
68
|
+
* () => count() * 2,
|
|
69
|
+
* (x) => void setCount(x / 2),
|
|
70
|
+
* ]);
|
|
71
|
+
*
|
|
72
|
+
* double(x => x + 2);
|
|
73
|
+
* console.log(double(), count()); // 12 6
|
|
74
|
+
* ```
|
|
17
75
|
*/
|
|
18
|
-
export declare function
|
|
76
|
+
export declare function createCosignal<T>(cosignal: Cosignal<T>): Signal<T>;
|
|
19
77
|
//# sourceMappingURL=atom.d.ts.map
|
package/dist/atom.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atom.d.ts","sourceRoot":"","sources":["../src/atom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"atom.d.ts","sourceRoot":"","sources":["../src/atom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAGlF;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAE,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,CAAE,CAAC;AAErE;;;;;;GAMG;AACH,MAAM,MAAM,IAAI,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,QAAQ,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAmBlE;;;GAGG;AACH,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtC;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;AACvD,wBAAgB,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAK/E;;;;GAIG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;IACzB,MAAM,CAAC;IACP,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC;CACf,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAoBlE"}
|
package/dist/atom.js
CHANGED
|
@@ -1,20 +1,54 @@
|
|
|
1
1
|
import { createSignal, untrack } from "solid-js";
|
|
2
|
+
import { isDev } from "solid-js/web";
|
|
2
3
|
export function atom(value) {
|
|
3
|
-
if (
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
if (isDev) {
|
|
5
|
+
// Assert that the input is valid.
|
|
6
|
+
// For production, the 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]}`);
|
|
6
15
|
}
|
|
7
16
|
}
|
|
8
|
-
|
|
17
|
+
return (...args) => (args.length === 0) ? value[0]() : value[1](...args);
|
|
9
18
|
}
|
|
10
19
|
export function asig(...args) {
|
|
11
20
|
return atom(args.length === 0 ? createSignal() : createSignal(args[0], args[1]));
|
|
12
21
|
}
|
|
13
22
|
/**
|
|
14
|
-
*
|
|
23
|
+
* Create signal from a getter/setter tuple.
|
|
24
|
+
*
|
|
25
|
+
* ### Example
|
|
26
|
+
* ```
|
|
27
|
+
* const [ count, setCount ] = createSignal(0);
|
|
28
|
+
* const [ double, setDouble ] = createCosignal([
|
|
29
|
+
* () => count() * 2,
|
|
30
|
+
* (x) => void setCount(x / 2),
|
|
31
|
+
* ]);
|
|
32
|
+
*
|
|
33
|
+
* double(x => x + 2);
|
|
34
|
+
* console.log(double(), count()); // 12 6
|
|
35
|
+
* ```
|
|
15
36
|
*/
|
|
16
|
-
export function
|
|
17
|
-
|
|
37
|
+
export function createCosignal(cosignal) {
|
|
38
|
+
if (isDev) {
|
|
39
|
+
// Assert that the input is valid.
|
|
40
|
+
// For production, the checks are skipped for performance.
|
|
41
|
+
if (!Array.isArray(cosignal)) {
|
|
42
|
+
throw new Error(`expected a getter setter pair as an array, but got ${typeof cosignal}`);
|
|
43
|
+
}
|
|
44
|
+
if (typeof cosignal[0] !== "function") {
|
|
45
|
+
throw new Error(`expected a getter function, but got ${typeof cosignal[0]}`);
|
|
46
|
+
}
|
|
47
|
+
if (typeof cosignal[1] !== "function") {
|
|
48
|
+
throw new Error(`expected a setter function, but got ${typeof cosignal[1]}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const [get, set] = cosignal;
|
|
18
52
|
return [
|
|
19
53
|
get,
|
|
20
54
|
(value) => set((typeof value === "function") ? value(untrack(get)) : value),
|
package/dist/atom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atom.js","sourceRoot":"","sources":["../src/atom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAmC,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"atom.js","sourceRoot":"","sources":["../src/atom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAmC,MAAM,UAAU,CAAC;AAClF,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAsCrC,MAAM,UAAU,IAAI,CAAC,KAAc;IAClC,IAAI,KAAK,EAAE,CAAC;QACX,kCAAkC;QAClC,0DAA0D;QAE1D,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,IAAS,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAE,KAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE,KAAa,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AACjG,CAAC;AAmBD,MAAM,UAAU,IAAI,CAAI,GAAG,IAA+C;IACzE,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,EAAK,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1F,CAAC;AAYD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,cAAc,CAAI,QAAqB;IACtD,IAAI,KAAK,EAAE,CAAC;QACX,kCAAkC;QAClC,0DAA0D;QAE1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,sDAAsD,OAAO,QAAQ,EAAE,CAAC,CAAC;QAC1F,CAAC;QACD,IAAI,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,IAAI,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9E,CAAC;IACF,CAAC;IACD,MAAM,CAAE,GAAG,EAAE,GAAG,CAAE,GAAG,QAAQ,CAAC;IAC9B,OAAO;QACN,GAAG;QACH,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,CAAE,KAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;KACvE,CAAC;AAChB,CAAC"}
|