solid-state-tools 1.5.0 → 1.6.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
@@ -6,16 +6,17 @@ Solid State Tools is a collection of simple utilities for managing [Solid JS](ht
6
6
 
7
7
  All features are intended to compliment Solid JS's existing state system, building upon the existing foundation.
8
8
 
9
- The package is small and only has a peer dependency of Solid JS.
9
+ The package is small and the only production dependency is Solid JS.
10
10
 
11
11
  # Usage
12
12
 
13
- | Utility | Summary |
14
- | ------------------------------- | ------------------------------------------------ |
15
- | [atom](#atoms-atom) | Combines a getter setter pair into one function. |
16
- | [createPair](#pairs-createpair) | Creates a signal from a getter setter pair. |
17
- | [asig](#atomic-signals-asig) | Shorthand for `atom(createSignal(...))` |
18
- | [apair](#atomic-pairs-apair) | Shorthand for `atom(createCouple(...))` |
13
+ | Utility | Summary |
14
+ | ---------------------------------------- | ------------------------------------------------- |
15
+ | [atom](#atoms-atom) | Combines a getter setter pair into one function. |
16
+ | [createPair](#pairs-createpair) | Creates a signal from a getter setter pair. |
17
+ | [asig](#atomic-signals-asig) | Shorthand for `atom(createSignal(...))` |
18
+ | [apair](#atomic-pairs-apair) | Shorthand for `atom(createCouple(...))` |
19
+ | [createBlinker](#blinkers-createblinker) | Creates a reactive boolean for flashing elements. |
19
20
 
20
21
  Read the sections below for a breakdown of each utility.
21
22
 
@@ -180,9 +181,25 @@ const double = apair(() => count() * 2, (double) => count(double / 2));
180
181
  const double = atom(createPair(() => count() * 2, (double) => count(double / 2)));
181
182
  ```
182
183
 
184
+ ## Blinkers (`createBlinker`)
185
+
186
+ A blinker is a reactive boolean that tracks some state. When the state updates, the blinker temporarily flips to true.
187
+
188
+ This is primarily useful for flashing an element on the page when a signal changes to draw the user's attention to it.
189
+
190
+ ```tsx
191
+ const [ count, setCount ] = createSignal(0);
192
+ const countBlinked = createBlinker(count, 200);
193
+
194
+ // Flashes orange for 200ms when count changes.
195
+ <span style={ { "color": countBlinked() ? "orange" : undefined } }>
196
+ { count() }
197
+ </span>
198
+ ```
199
+
183
200
  # Conclusion
184
201
 
185
202
  Perhaps you can see the power of the above primitives.
186
- Not just what they do individually, but how they work together.
203
+ Specifically, how they work together to reduce boilerplate.
187
204
 
188
205
  More utilities for this library are in the works and are coming soon.
package/dist/index.js CHANGED
@@ -1,107 +1,147 @@
1
- import { createMemo, createSignal, untrack } from "solid-js";
2
- import { isDev } from "solid-js/web";
3
- /**
4
- * @description
5
- * Combine a getter and setter function pair into one.
6
- * [See documentation.](https://github.com/ReedSyllas/solid-state-tools#atoms-atom)
7
- *
8
- * Accepts a tuple of two functions.
9
- * The first is the getter, the second is the setter.
10
- * A new function is returned that, when called with zero arguments, calls the getter.
11
- * Otherwise, it calls the setter and forwards all of the arguments.
12
- *
13
- * @see {@link SignalLike} (input), {@link Atom} (output)
14
- *
15
- * @example
16
- * ```
17
- * const count: Atom<Signal<T>> = atom(createSignal(0));
18
- *
19
- * // Read
20
- * count();
21
- *
22
- * // Write
23
- * count(100);
24
- * count(x => x + 1);
25
- * count(count() + 1);
26
- * ```
27
- */
28
- export function atom(signal) {
29
- if (isDev) {
30
- // Assert that the input is valid.
31
- // For production, these checks are skipped for performance.
32
- if (!Array.isArray(signal)) {
33
- throw new Error(`expected a getter setter pair as an array, but got ${typeof signal}`);
34
- }
35
- if (typeof signal[0] !== "function") {
36
- throw new Error(`expected a getter function, but got ${typeof signal[0]}`);
37
- }
38
- if (typeof signal[1] !== "function") {
39
- throw new Error(`expected a setter function, but got ${typeof signal[1]}`);
40
- }
41
- }
42
- const [getter, setter] = signal;
43
- return (...args) => (args.length === 0) ? getter() : setter(...args);
1
+ import { createMemo as E, createSignal as s, createComputed as w, on as $, getOwner as L, createSelector as O, onCleanup as x, batch as m, getListener as k, untrack as a, runWithOwner as C, createRoot as F } from "solid-js";
2
+ import { isDev as g } from "solid-js/web";
3
+ function h(t) {
4
+ if (g) {
5
+ if (!Array.isArray(t))
6
+ throw new Error(`expected signal to be an array, but got ${typeof t}`);
7
+ if (typeof t[0] != "function")
8
+ throw new Error(`expected getter to be a function, but got ${typeof t[0]}`);
9
+ if (typeof t[1] != "function")
10
+ throw new Error(`expected setter to be a function, but got ${typeof t[1]}`);
11
+ }
12
+ const [e, r] = t;
13
+ return Object.assign(
14
+ (...o) => o.length === 0 ? e() : r(...o),
15
+ e,
16
+ r
17
+ );
44
18
  }
45
- /**
46
- * @description
47
- * Create a signal from a getter setter pair.
48
- * [See documentation.](https://github.com/ReedSyllas/solid-state-tools#pairs-createpair)
49
- *
50
- * **The getter is immediately invoked for memoization.**
51
- *
52
- * @see {@link Accessor} (input), {@link Writer} (input), {@link PairOptions} (input), {@link Signal} (output)
53
- *
54
- * @example
55
- * ```
56
- * const [ count, setCount ] = createSignal(0);
57
- * const [ double, setDouble ] = createPair(() => count() * 2, (x) => setCount(x / 2));
58
- *
59
- * setDouble(x => x + 2);
60
- * console.log(double(), count()); // 2 1
61
- * ```
62
- */
63
- export function createPair(getter, setter, options) {
64
- if (isDev) {
65
- // Assert that the input is valid.
66
- // For production, these checks are skipped for performance.
67
- if (typeof getter !== "function") {
68
- throw new Error(`expected getter to be a function, but got ${typeof getter}`);
69
- }
70
- if (typeof setter !== "function") {
71
- throw new Error(`expected setter to be a function, but got ${typeof setter}`);
72
- }
73
- }
74
- const get = options?.memoized === false ? getter : createMemo(getter);
75
- const set = ((source) => {
76
- const value = (typeof source === "function") ? source(untrack(get)) : source;
77
- setter(value);
78
- return value;
19
+ function j(t, e, r) {
20
+ if (g) {
21
+ if (typeof t != "function")
22
+ throw new Error(`expected getter to be a function, but got ${typeof t}`);
23
+ if (typeof e != "function")
24
+ throw new Error(`expected setter to be a function, but got ${typeof e}`);
25
+ }
26
+ const o = r?.memoized === !1 ? t : E(t);
27
+ return [o, ((c) => {
28
+ const u = typeof c == "function" ? c(a(o)) : c;
29
+ return e(u), u;
30
+ })];
31
+ }
32
+ function R(t, e = 500) {
33
+ if (g) {
34
+ if (typeof t != "function")
35
+ throw new Error(`expected subject to be a function, but got ${typeof t}`);
36
+ if (typeof e != "number")
37
+ throw new Error(`expected duration to be a number, but got ${typeof e}`);
38
+ }
39
+ const [r, o] = s(!1);
40
+ let n;
41
+ return w($(t, () => {
42
+ n !== void 0 ? clearTimeout(n) : o(!0), n = setTimeout(() => {
43
+ o(!1), n = void 0;
44
+ }, e);
45
+ }, { defer: !0 })), r;
46
+ }
47
+ function q(t, e) {
48
+ const [r, o] = s(e?.initial), n = () => t((c) => o(() => c), r);
49
+ if (e?.late) {
50
+ const c = L();
51
+ let u = () => {
52
+ u = void 0, C(c, n);
53
+ };
54
+ return () => (u?.(), r());
55
+ }
56
+ return n(), r;
57
+ }
58
+ function T(t, e) {
59
+ const [r, o] = s(), [n, c] = s(e?.initial), [u, l] = s("unresolved"), p = O(u);
60
+ let d = !1;
61
+ const b = q((y, v) => {
62
+ w(() => {
63
+ let i = !1;
64
+ x(() => {
65
+ i = !0, y(void 0);
66
+ }), l(d ? "refreshing" : "pending");
67
+ try {
68
+ t((f) => {
69
+ i || m(() => {
70
+ l("ready"), c(() => f), d = !0, y(f);
71
+ });
72
+ }, v);
73
+ } catch (f) {
74
+ m(() => {
75
+ l("errored"), o(f);
76
+ });
77
+ }
79
78
  });
80
- return [get, set];
79
+ }, e);
80
+ return Object.assign(b, {
81
+ error: r,
82
+ latest: n,
83
+ state: u,
84
+ is: p
85
+ });
86
+ }
87
+ function S(t, e) {
88
+ let r = 0, o;
89
+ const n = () => {
90
+ r === 0 && (o = a(e)), r++;
91
+ }, c = () => queueMicrotask(() => {
92
+ r--, r === 0 && (o?.(), o = void 0);
93
+ });
94
+ return () => (k() && (n(), x(c)), t());
95
+ }
96
+ function z(t, e) {
97
+ const [r, o] = s(a(t), e);
98
+ return S(r, () => F((n) => (w(() => {
99
+ o(t);
100
+ }), n)));
101
+ }
102
+ function B(t, e) {
103
+ const [r, o] = s(e?.initial);
104
+ let n = !!e?.initial;
105
+ const [c, u] = s(), [l, p] = s(!1), d = E(() => r() !== c()), b = (i) => m(() => {
106
+ const f = t.reconcile ? t.reconcile(i, a(r), a(c)) : i;
107
+ return n = !0, o(() => f), u(() => f), f;
108
+ }), y = h([
109
+ S(r, () => {
110
+ const i = t.sub(b);
111
+ return p(!0), () => {
112
+ p(!1), i();
113
+ };
114
+ }),
115
+ (...i) => (n = !0, o(...i))
116
+ ]);
117
+ return Object.assign(y, {
118
+ async pull() {
119
+ const i = await a(t.get);
120
+ return b(i);
121
+ },
122
+ async push() {
123
+ n && await t.set(a(r));
124
+ },
125
+ cache: c,
126
+ subscribed: l,
127
+ detached: d
128
+ });
81
129
  }
82
- export function asig(value, options) {
83
- return atom(createSignal(value, options));
130
+ function D(t, e) {
131
+ return h(s(t, e));
84
132
  }
85
- /**
86
- * @description
87
- * Create an atomic getter setter pair. Short for `atom(createPair(...))`.
88
- * [See documentation.](https://github.com/ReedSyllas/solid-state-tools#atomic-pairs-apair)
89
- *
90
- * @see {@link Accessor} (input), {@link Writer} (input), {@link PairOptions} (input), {@link Asig} (output)
91
- *
92
- * @example
93
- * ```
94
- * const count = asig(0);
95
- * const double = apair(() => count() * 2, (x) => count(x / 2));
96
- *
97
- * count(10);
98
- * console.log(count(), double()); // 10 20
99
- *
100
- * double(100);
101
- * console.log(count(), double()); // 50 100
102
- * ```
103
- */
104
- export function apair(getter, setter, options) {
105
- return atom(createPair(getter, setter, options));
133
+ function P(t, e, r) {
134
+ return h(j(t, e, r));
106
135
  }
107
- //# sourceMappingURL=index.js.map
136
+ export {
137
+ P as apair,
138
+ D as asig,
139
+ h as atom,
140
+ R as createBlinker,
141
+ T as createFetched,
142
+ j as createPair,
143
+ q as createSpool,
144
+ B as createSubscription,
145
+ z as derive,
146
+ S as quantum
147
+ };
@@ -0,0 +1,347 @@
1
+ import { Accessor, Setter, Signal, SignalOptions } from 'solid-js';
2
+ /**
3
+ * A function that updates a state to the given value.
4
+ *
5
+ * @see {@link Setter} (related type)
6
+ */
7
+ export type Update<T> = (value: T) => void;
8
+ /**
9
+ * Any tuple of two functions where the first accepts no arguments and the second accepts any amount.
10
+ *
11
+ * Used as the source of an {@link Atom}.
12
+ *
13
+ * @see {@link Atom}, {@link atom}
14
+ */
15
+ export type SignalLike = readonly [
16
+ getter: () => any,
17
+ setter: (...args: any) => any
18
+ ];
19
+ /**
20
+ * An {@link Atom} is a polymorphic function that calls one of two
21
+ * functions depending on the number of arguments it has.
22
+ *
23
+ * If called with zero arguments, the first function is called.
24
+ * Otherwise, the second function is called with all arguments forwarded to it.
25
+ *
26
+ * @see {@link SignalLike}, {@link atom} (constructor)
27
+ */
28
+ export type Atom<T extends SignalLike = SignalLike> = T[0] & T[1];
29
+ /**
30
+ * Combine a getter and setter function pair into one.
31
+ * [See documentation.](https://github.com/ReedSyllas/solid-state-tools#atoms-atom)
32
+ *
33
+ * Accepts a tuple of two functions.
34
+ * The first is the getter, the second is the setter.
35
+ * A new function is returned that, when called with zero arguments, calls the getter.
36
+ * Otherwise, it calls the setter and forwards all of the arguments.
37
+ *
38
+ * @see {@link SignalLike} (input), {@link Atom} (output)
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * const count: Atom<Signal<T>> = atom(createSignal(0));
43
+ *
44
+ * // Read
45
+ * count();
46
+ *
47
+ * // Write
48
+ * count(100);
49
+ * count(x => x + 1);
50
+ * count(count() + 1);
51
+ * ```
52
+ */
53
+ export declare function atom<const T extends SignalLike>(signal: T): Atom<T>;
54
+ export interface PairOptions {
55
+ /**
56
+ * @default true
57
+ */
58
+ memoized: boolean;
59
+ }
60
+ /**
61
+ * Create a signal from a getter setter pair.
62
+ * [See documentation.](https://github.com/ReedSyllas/solid-state-tools#pairs-createpair)
63
+ *
64
+ * **The getter is immediately invoked for memoization.**
65
+ *
66
+ * @see {@link Accessor} (input), {@link Update} (input), {@link PairOptions} (input), {@link Signal} (output)
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * const [ count, setCount ] = createSignal(0);
71
+ * const [ double, setDouble ] = createPair(() => count() * 2, (x) => setCount(x / 2));
72
+ *
73
+ * setDouble(x => x + 2);
74
+ * console.log(double(), count()); // 2 1
75
+ * ```
76
+ */
77
+ export declare function createPair<T>(getter: Accessor<T>, setter: Update<T>, options?: PairOptions): Signal<T>;
78
+ /**
79
+ * Create a reactive boolean that temporarily flips to true when the subject changes value.
80
+ *
81
+ * Useful for flashing an element when a signal changes value.
82
+ * Perhaps to draw the user's attention to it.
83
+ *
84
+ * @param subject The subject to track for changes.
85
+ * @param duration The duration in milliseconds to "blink" before resetting to false. Default: 500.
86
+ *
87
+ * @see {@link Accessor}
88
+ *
89
+ * @example
90
+ * ```tsx
91
+ * const [ count, setCount ] = createSignal(0);
92
+ * const countBlinked = createBlinker(count, 200);
93
+ *
94
+ * <span style={ { "color": countBlinked() ? "orange" : undefined } }>
95
+ * { count() }
96
+ * </span>
97
+ * ```
98
+ */
99
+ export declare function createBlinker(subject: Accessor<unknown>, duration?: number): Accessor<boolean>;
100
+ /**
101
+ * A function that will periodically call the given update function as needed.
102
+ * The current value (stateful) is also available to the consumer for incremental changes.
103
+ *
104
+ * @see {@link Update}, {@link Accessor}
105
+ */
106
+ export type Winch<T, Initial extends T | undefined> = (update: Update<T>, value: Accessor<Initial>) => void;
107
+ /**
108
+ * Options for creation of a spool signal.
109
+ *
110
+ * @see {@link createSpool}
111
+ */
112
+ export interface SpoolOptions<T> {
113
+ /**
114
+ * The initial value of the spool signal.
115
+ * @default undefined
116
+ */
117
+ initial?: T;
118
+ /**
119
+ * If set to true, the winch will not be invoked until the spool signal is read for the first time.
120
+ * @default false
121
+ */
122
+ late?: boolean;
123
+ }
124
+ /**
125
+ * Create a signal from a winch.
126
+ *
127
+ * This is essentially an alternative way of writing a signal declaration.
128
+ *
129
+ * Note that the winch is not tracked and therefore does not automatically rerun when state changes.
130
+ * This behavior can be implemented in the winch function itself, if desired.
131
+ * Use {@link createFetched} for a reactive version.
132
+ *
133
+ * @see {@link Winch} (input), {@link SpoolOptions} (input), {@link Accessor} (output)
134
+ *
135
+ * @example
136
+ * ```tsx
137
+ * // A timer that updates each second.
138
+ * const time: Accessor<number> = createSpool((setTime, curr) => {
139
+ * // Start timer.
140
+ * const interval = setInterval(() => void setTime(curr() + 1), 1000);
141
+ *
142
+ * // Dispose of timer when signal is destroyed.
143
+ * onCleanup(() => void clearInterval(interval));
144
+ * }, {
145
+ * initial: 0,
146
+ * });
147
+ *
148
+ * <div>
149
+ * { time() }
150
+ * </div>
151
+ * ```
152
+ */
153
+ export declare function createSpool<T>(winch: Winch<T, T>, options: SpoolOptions<T> & {
154
+ initial: T;
155
+ }): Accessor<T>;
156
+ export declare function createSpool<T>(winch: Winch<T, T | undefined>, options?: SpoolOptions<T>): Accessor<T | undefined>;
157
+ /**
158
+ * A synchronous reactive state driven by a winch.
159
+ *
160
+ * @see {@link Accessor}, {@link Winch}, {@link createFetched} (constructor)
161
+ */
162
+ export type Fetched<T> = Accessor<T> & FetchedMembers<T>;
163
+ export interface FetchedMembers<T> {
164
+ error: Accessor<unknown>;
165
+ latest: Accessor<T>;
166
+ state: Accessor<FetchedState>;
167
+ is: (key: FetchedState) => boolean;
168
+ }
169
+ /**
170
+ * Represents the current state of a fetched signal.
171
+ *
172
+ * Its identical to {@link Resource.state} in meaning.
173
+ * See the [table of definitions](https://docs.solidjs.com/reference/basic-reactivity/create-resource#resource) for that.
174
+ *
175
+ * @see {@link Fetched.state}
176
+ */
177
+ export type FetchedState = "unresolved" | "pending" | "ready" | "refreshing" | "errored";
178
+ /**
179
+ * Create a signal that's driven by a tracked winch.
180
+ *
181
+ * The winch is tracked and therefore is rerun when its state changes.
182
+ *
183
+ * If the winch is rerun, the old winch can no longer mutate the state.
184
+ * This prevents race conditions where the old winch attempts to write _after_ the new winch resolved.
185
+ *
186
+ * @see {@link Winch} (input), {@link SpoolOptions} (input), {@link Fetched} (output)
187
+ */
188
+ export declare function createFetched<T>(winch: Winch<T, T>, options: SpoolOptions<T> & {
189
+ initial: T;
190
+ }): Fetched<T>;
191
+ export declare function createFetched<T>(winch: Winch<T, T | undefined>, options?: SpoolOptions<T>): Fetched<T | undefined>;
192
+ export type QuantumAccessor<T> = Accessor<T>;
193
+ /**
194
+ * Create a quantum accessor.
195
+ *
196
+ * A quantum accessor counts its listeners and executes `track` if it is used at least once.
197
+ * When it is no longer used, `track`'s disposal function is invoked.
198
+ *
199
+ * Quantum accessors have standalone utility, but their primary purpose was to create and destroy subscriptions on the fly.
200
+ * Thus, {@link createSubscription} and {@link derive} replace most situations where {@link quantum} would be invoked directly.
201
+ *
202
+ * Note that quantum accessors count listeners ambiguously.
203
+ * Thus, some primitives must be substituted with a quantum-compatible one to preserve the 'quantum' behavior.
204
+ * Using a quantum accessor in these primitives (e.g. {@link createMemo}) is not _wrong_, but it may have unintended side-effects.
205
+ * Use {@link derive} in place of {@link createMemo} for quantum accessors.
206
+ *
207
+ * Technically, {@link QuantumAccessor} is just an alias of {@link Accessor} and can be used anywhere {@link Accessor} is allowed.
208
+ * However, it is useful to mark it this way due to the special handling (mentioned above) that's sometimes needed.
209
+ *
210
+ * @example
211
+ * ```ts
212
+ * const [ source ] = createSignal(0);
213
+ * const count = quantum(source, () => {
214
+ * console.log("count is now observed");
215
+ * return () => {
216
+ * console.log("count is no longer observed");
217
+ * };
218
+ * });
219
+ *
220
+ * createRoot((dispose) => {
221
+ * count(); // nothing happens because `createRoot` doesn't track signals
222
+ *
223
+ * createComputed(() => {
224
+ * count(); // prints "count is now observed" because `createComputed` started tracking `count`
225
+ * count(); // nothing happens because count is already tracked at least once
226
+ * });
227
+ *
228
+ * dispose(); // prints "count is no longer observed" because the `createComputed` is destroyed and `count` isn't tracked by anything else
229
+ * });
230
+ * ```
231
+ */
232
+ export declare function quantum<T>(source: Accessor<T>, track: () => () => void): QuantumAccessor<T>;
233
+ /**
234
+ * Derive a new quantum accessor from an existing one while preserving the quantum behavior.
235
+ *
236
+ * Essentially, this is a quantum-compatible version of {@link createMemo}.
237
+ *
238
+ * This provides no advantage over {@link createMemo} for traditional accessors.
239
+ *
240
+ * @see {@link quantum}, {@link QuantumAccessor}
241
+ *
242
+ * @example
243
+ * ```ts
244
+ * const count: QuantumAccessor<number> = ...;
245
+ * const double = derive(() => count() * 2);
246
+ * ```
247
+ */
248
+ export declare function derive<T>(source: QuantumAccessor<T>, options?: SignalOptions<T>): QuantumAccessor<T>;
249
+ /**
250
+ * Handler for a subscription.
251
+ *
252
+ * @see {@link Subscription}, {@link createSubscription}
253
+ */
254
+ export type Subscribable<T, Initial extends T | undefined> = {
255
+ get: () => Promise<T>;
256
+ set: (value: T) => Promise<void>;
257
+ sub: (update: Update<T>) => () => void;
258
+ reconcile?: (remote: T, local: Initial, cache: T | undefined) => T;
259
+ };
260
+ /**
261
+ * A state driven by a remote subscription.
262
+ *
263
+ * @see {@link createSubscription} (constructor), {@link QuantumAccessor} (component type)
264
+ */
265
+ export type Subscription<T> = QuantumAccessor<T> & Setter<T> & SubscriptionMembers<T>;
266
+ export type SubscriptionMembers<T> = {
267
+ /**
268
+ * The last known remote value.
269
+ *
270
+ * It changes when a new remote value is pushed or pulled to this subscribable.
271
+ */
272
+ cache: Accessor<T | undefined>;
273
+ /**
274
+ * Fetch the remote value and reconcile it with the current value (local) and cache.
275
+ */
276
+ pull: () => Promise<T>;
277
+ /**
278
+ * Push local to the remote.
279
+ */
280
+ push: () => Promise<void>;
281
+ /**
282
+ * True if subscribed to the remote.
283
+ */
284
+ subscribed: Accessor<boolean>;
285
+ /**
286
+ * True if the current value (local) is different from the last known remote value (cache).
287
+ */
288
+ detached: Accessor<boolean>;
289
+ };
290
+ /**
291
+ * Options for creation of a subscription.
292
+ *
293
+ * @see {@link createSubscription}, {@link Subscription}
294
+ */
295
+ export interface SubscriptionOptions<T> {
296
+ initial?: T;
297
+ }
298
+ /**
299
+ * Create a new subscription from a subscribable (handler).
300
+ *
301
+ * Quantum signals are used for dynamic subscription through observation.
302
+ */
303
+ export declare function createSubscription<T>(handler: Subscribable<T, T | undefined>, options?: SubscriptionOptions<T>): Subscription<T | undefined>;
304
+ /**
305
+ * An atomic signal. A signal where the getter and setter are combined into one function.
306
+ *
307
+ * @see {@link Atom}, {@link asig} (constructor)
308
+ */
309
+ export type Asig<T> = Atom<Signal<T>>;
310
+ /**
311
+ * Create an atomic signal. Short for `atom(createSignal(...))`.
312
+ * [See documentation.](https://github.com/ReedSyllas/solid-state-tools#atomic-signals-asig)
313
+ *
314
+ * @see {@link Asig} (output), {@link Atom}, {@link atom}
315
+ *
316
+ * @example
317
+ * ```ts
318
+ * const count = asig(0);
319
+ *
320
+ * count(10);
321
+ * console.log(count()); // 10
322
+ *
323
+ * count(x => x + 10);
324
+ * console.log(count()); // 20
325
+ * ```
326
+ */
327
+ export declare function asig<T>(value: T, options?: SignalOptions<T>): Asig<T>;
328
+ export declare function asig<T>(): Asig<T | undefined>;
329
+ /**
330
+ * Create an atomic getter setter pair. Short for `atom(createPair(...))`.
331
+ * [See documentation.](https://github.com/ReedSyllas/solid-state-tools#atomic-pairs-apair)
332
+ *
333
+ * @see {@link Accessor} (input), {@link Update} (input), {@link PairOptions} (input), {@link Asig} (output)
334
+ *
335
+ * @example
336
+ * ```ts
337
+ * const count = asig(0);
338
+ * const double = apair(() => count() * 2, (x) => count(x / 2));
339
+ *
340
+ * count(10);
341
+ * console.log(count(), double()); // 10 20
342
+ *
343
+ * double(100);
344
+ * console.log(count(), double()); // 50 100
345
+ * ```
346
+ */
347
+ export declare function apair<T>(getter: Accessor<T>, setter: Update<T>, options?: PairOptions): Asig<T>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solid-state-tools",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "A collection of Solid JS state utilities",
5
5
  "author": "Reed Syllas <reedsyllas@gmail.com>",
6
6
  "license": "ISC",
@@ -17,24 +17,28 @@
17
17
  ],
18
18
  "exports": {
19
19
  "import": {
20
- "types": "./dist/index.d.ts",
21
- "default": "./dist/index.js"
20
+ "import": "./dist/index.js",
21
+ "types": "./dist/types/index.d.ts"
22
22
  }
23
23
  },
24
24
  "type": "module",
25
- "main": "./dist/index.js",
26
- "types": "./dist/index.d.ts",
25
+ "module": "./dist/index.js",
26
+ "types": "./dist/types/index.d.ts",
27
27
  "files": [
28
28
  "dist"
29
29
  ],
30
30
  "devDependencies": {
31
31
  "@types/node": "^24.10.0",
32
- "typescript": "^5.9.3"
32
+ "typescript": "^5.9.3",
33
+ "vite": "^7.3.1",
34
+ "vite-plugin-dts": "^4.5.4",
35
+ "vite-plugin-solid": "^2.11.10"
33
36
  },
34
37
  "peerDependencies": {
35
38
  "solid-js": "^1.9.10"
36
39
  },
37
40
  "scripts": {
38
- "build": "tsc"
41
+ "dev": "vite dev",
42
+ "build": "vite build"
39
43
  }
40
44
  }
package/dist/index.d.ts DELETED
@@ -1,127 +0,0 @@
1
- import { type Accessor, type Signal, type SignalOptions } from "solid-js";
2
- /**
3
- * @description
4
- * Any tuple of two functions where the first accepts no arguments and the second accepts any amount.
5
- *
6
- * Used as the source of an {@link Atom}.
7
- *
8
- * @see {@link Atom}, {@link atom}
9
- */
10
- export type SignalLike = readonly [() => any, (...args: any) => any];
11
- /**
12
- * @description
13
- * An {@link Atom} is a polymorphic function that calls one of two
14
- * functions depending on the number of arguments it has.
15
- *
16
- * If called with zero arguments, the first function is called.
17
- * Otherwise, the second function is called with all arguments forwarded to it.
18
- *
19
- * @see {@link SignalLike}, {@link atom} (constructor)
20
- */
21
- export type Atom<T extends SignalLike = SignalLike> = T[0] & T[1];
22
- /**
23
- * @description
24
- * Combine a getter and setter function pair into one.
25
- * [See documentation.](https://github.com/ReedSyllas/solid-state-tools#atoms-atom)
26
- *
27
- * Accepts a tuple of two functions.
28
- * The first is the getter, the second is the setter.
29
- * A new function is returned that, when called with zero arguments, calls the getter.
30
- * Otherwise, it calls the setter and forwards all of the arguments.
31
- *
32
- * @see {@link SignalLike} (input), {@link Atom} (output)
33
- *
34
- * @example
35
- * ```
36
- * const count: Atom<Signal<T>> = atom(createSignal(0));
37
- *
38
- * // Read
39
- * count();
40
- *
41
- * // Write
42
- * count(100);
43
- * count(x => x + 1);
44
- * count(count() + 1);
45
- * ```
46
- */
47
- export declare function atom<const T extends SignalLike>(signal: T): Atom<T>;
48
- /**
49
- * @description
50
- * Similar to a signal setter, except it doesn't accept a mapping function nor return a result.
51
- *
52
- * @see {@link createPair} (for example usage)
53
- */
54
- export type Writer<T> = (value: T) => void;
55
- export interface PairOptions {
56
- /**
57
- * @default true
58
- */
59
- memoized: boolean;
60
- }
61
- /**
62
- * @description
63
- * Create a signal from a getter setter pair.
64
- * [See documentation.](https://github.com/ReedSyllas/solid-state-tools#pairs-createpair)
65
- *
66
- * **The getter is immediately invoked for memoization.**
67
- *
68
- * @see {@link Accessor} (input), {@link Writer} (input), {@link PairOptions} (input), {@link Signal} (output)
69
- *
70
- * @example
71
- * ```
72
- * const [ count, setCount ] = createSignal(0);
73
- * const [ double, setDouble ] = createPair(() => count() * 2, (x) => setCount(x / 2));
74
- *
75
- * setDouble(x => x + 2);
76
- * console.log(double(), count()); // 2 1
77
- * ```
78
- */
79
- export declare function createPair<T>(getter: Accessor<T>, setter: Writer<T>, options?: PairOptions): Signal<T>;
80
- /**
81
- * @description
82
- * An atomic signal. A signal where the getter and setter are combined into one function.
83
- *
84
- * @see {@link Atom}, {@link asig} (constructor)
85
- */
86
- export type Asig<T> = Atom<Signal<T>>;
87
- /**
88
- * @description
89
- * Create an atomic signal. Short for `atom(createSignal(...))`.
90
- * [See documentation.](https://github.com/ReedSyllas/solid-state-tools#atomic-signals-asig)
91
- *
92
- * @see {@link Asig} (output), {@link Atom}, {@link atom}
93
- *
94
- * @example
95
- * ```
96
- * const count = asig(0);
97
- *
98
- * count(10);
99
- * console.log(count()); // 10
100
- *
101
- * count(x => x + 10);
102
- * console.log(count()); // 20
103
- * ```
104
- */
105
- export declare function asig<T>(value: T, options?: SignalOptions<T>): Asig<T>;
106
- export declare function asig<T>(): Asig<T | undefined>;
107
- /**
108
- * @description
109
- * Create an atomic getter setter pair. Short for `atom(createPair(...))`.
110
- * [See documentation.](https://github.com/ReedSyllas/solid-state-tools#atomic-pairs-apair)
111
- *
112
- * @see {@link Accessor} (input), {@link Writer} (input), {@link PairOptions} (input), {@link Asig} (output)
113
- *
114
- * @example
115
- * ```
116
- * const count = asig(0);
117
- * const double = apair(() => count() * 2, (x) => count(x / 2));
118
- *
119
- * count(10);
120
- * console.log(count(), double()); // 10 20
121
- *
122
- * double(100);
123
- * console.log(count(), double()); // 50 100
124
- * ```
125
- */
126
- export declare function apair<T>(getter: Accessor<T>, setter: Writer<T>, options?: PairOptions): Asig<T>;
127
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,QAAQ,EAAe,KAAK,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAK1H;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,CAAE,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,CAAE,CAAC;AAEvE;;;;;;;;;GASG;AACH,MAAM,MAAM,IAAI,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,UAAU,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAiBnE;AAED;;;;;GAKG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;AAE3C,MAAM,WAAW,WAAW;IAC3B;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,CAmBtG;AAID;;;;;GAKG;AACH,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AACvE,wBAAgB,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AAK/C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAE/F"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAA+D,MAAM,UAAU,CAAC;AAC1H,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AA0BrC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;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;AAiBD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,UAAU,CAAI,MAAmB,EAAE,MAAiB,EAAE,OAAqB;IAC1F,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,OAAO,EAAE,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACtE,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;AAgCD,MAAM,UAAU,IAAI,CAAI,KAAqB,EAAE,OAAsC;IACpF,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,KAAK,CAAI,MAAmB,EAAE,MAAiB,EAAE,OAAqB;IACrF,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAClD,CAAC"}