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 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
- * Creates an atomic signal. Alias of `atom(createSignal(...))`.
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
- export type Cosig<T> = [
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
- * Creates a signal from a getter/setter pair.
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 cosig<T>(cosig: Cosig<T>): Signal<T>;
76
+ export declare function createCosignal<T>(cosignal: Cosignal<T>): Signal<T>;
19
77
  //# sourceMappingURL=atom.d.ts.map
@@ -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;AAElF,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAE,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,CAAE,CAAC;AAErE,MAAM,MAAM,IAAI,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9D,wBAAgB,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,QAAQ,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAUlE,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtC;;GAEG;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,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI;IACtB,MAAM,CAAC;IACP,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAMnD"}
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 (Array.isArray(value)) {
4
- if (typeof value[0] === "function" && typeof value[0] === "function") {
5
- return (...args) => (args.length === 0) ? value[0]() : value[1](...args);
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
- throw new Error("cannot create an atom from this value");
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
- * Creates a signal from a getter/setter pair.
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 cosig(cosig) {
17
- const [get, set] = cosig;
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;AAOlF,MAAM,UAAU,IAAI,CAAC,KAAc;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;YACtE,OAAO,CAAC,GAAG,IAAS,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC/E,CAAC;IACF,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;AAC1D,CAAC;AASD,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;AAOD;;GAEG;AACH,MAAM,UAAU,KAAK,CAAI,KAAe;IACvC,MAAM,CAAE,GAAG,EAAE,GAAG,CAAE,GAAG,KAAK,CAAC;IAC3B,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"}
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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solid-state-tools",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "A collection of Solid JS state utilities",
5
5
  "author": "Reed Syllas <reedsyllas@gmail.com>",
6
6
  "license": "ISC",