solid-ctrl-flow 1.0.57 → 1.0.59

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/dist/index.d.ts CHANGED
@@ -4,39 +4,50 @@ import { JSX } from 'solid-js';
4
4
  import { MemoOptions } from 'solid-js';
5
5
  import { Owner } from 'solid-js';
6
6
  import { ParentProps } from 'solid-js';
7
- import { Setter } from 'solid-js';
8
7
  import { Signal } from 'solid-js';
9
8
 
9
+ /** Reactive atomic value without the inconveniences of {@link Signal} */
10
+ export declare class Atom<T> {
11
+ get: Accessor<T>;
12
+ set: (x: T) => void;
13
+ get value(): T;
14
+ set value(v: T);
15
+ constructor(get: Accessor<T>, set: (x: T) => void);
16
+ /**
17
+ * Allows you to set the current {@link Atom} based on its current value.
18
+ * The current value gets read through {@link untrack} to mimic the {@link Setter} behaviour
19
+ * @param f Function that creates a new value based on the current one
20
+ */
21
+ update<V extends T>(f: (prev: T) => V): V;
22
+ /**
23
+ * Creates a new {@link Atom} that applies a conversion to the current one
24
+ * @param to Conversion function from {@link S} to {@link D}
25
+ * @param from Conversion function from {@link D} to {@link S}
26
+ */
27
+ convert<R>(to: (x: T) => R, from: (x: R) => T): Atom<R>;
28
+ /**
29
+ * Creates an {@link Atom} that forwards an {@link Accessor} to another {@link Atom}
30
+ * @param f The reactive {@link Accessor} to the {@link Atom} to forward
31
+ */
32
+ static unwrap<T>(f: Accessor<Atom<T>>): Atom<T>;
33
+ /**
34
+ * Creates an {@link Atom} based on a {@link Signal}
35
+ * @param param0 The {@link Signal} to forward
36
+ */
37
+ static from<T>([get, set]: Signal<T>): Atom<T>;
38
+ /**
39
+ * Creates a bindable data source.
40
+ * If {@link bind} returns an {@link Atom} it gets wrapped, otherwise it creates a {@link Signal} using {@link f} and uses it to store the value until {@link bind}'s value changes
41
+ * @param bind The bound {@link Atom}
42
+ * @param f The function that will create the actual {@link Signal} that will store the {@link Atom}'s data in case that {@link bind} doesn't return anything
43
+ */
44
+ static source<T>(bind: Accessor<Atom<T> | undefined>): Atom<T | undefined>;
45
+ static source<T>(bind: Accessor<Atom<T> | undefined>, f: Accessor<Signal<T>>): Atom<T>;
46
+ }
47
+
10
48
  /** Type hack for making {@link ReactiveContext} implement {@link Accessor} */
11
49
  declare const BASE_CTOR: new <T>() => Accessor<T>;
12
50
 
13
- /**
14
- * Creates a one-way binding between two {@link Signal}s.
15
- * The function uses {@link createComputed}, which means that:
16
- * - As soon as the function is done executing the two {@link Signal}s will have the same value
17
- * - If {@link source} changes, {@link dest} will be instantly updated
18
- * @param source The getter of the source of the binding
19
- * @param dest The setter of the destination of the binding
20
- * @param to Conversion function from {@link S} to {@link D}
21
- * @param skip If it is `true`, {@link dest} won't be executed until the next change
22
- * @returns A function that disposes the binding
23
- */
24
- export declare function bind<S>(source: Accessor<S>, dest: Setter<S>, to?: undefined, skip?: boolean): () => void;
25
-
26
- export declare function bind<S, D>(source: Accessor<S>, dest: Setter<D>, to: Convert<S, D>, skip?: boolean): () => void;
27
-
28
- /**
29
- * Creates a two-way binding between two {@link Signal}s calling {@link bind} two times
30
- * @param source The source of the binding
31
- * @param dest The destination of the binding
32
- * @param to Conversion function from {@link S} to {@link D}
33
- * @param from Conversion function from {@link D} to {@link S}
34
- * @returns A function that disposes the binding
35
- */
36
- export declare function bindTwoWay<S>(source: Signal<S>, dest: Signal<S>): () => void;
37
-
38
- export declare function bindTwoWay<S, D>(source: Signal<S>, dest: Signal<D>, to: Convert<S, D>, from: Convert<D, S>): () => void;
39
-
40
51
  /** Like a {@link Match} but gets the value from the closest {@link On} ancestor */
41
52
  export declare function Case(props: ParentProps<{
42
53
  value: unknown;
@@ -58,9 +69,6 @@ export declare function Case<T>(props: {
58
69
  children(x: NonNullable<T>): JSX.Element;
59
70
  }): JSX.Element;
60
71
 
61
- /** Conversion function for bindings */
62
- export declare type Convert<S, D> = (x: S, prev: D) => D;
63
-
64
72
  /**
65
73
  * Creates a slot that allows you to show a component outside of its parent.
66
74
  * It works with arbitrary nesting.
@@ -123,13 +131,6 @@ export declare function Enfold<T>(props: Unkeyed<T>): JSX.Element;
123
131
  /** Handy type alias */
124
132
  declare type Equals = MemoOptions<unknown>["equals"];
125
133
 
126
- /**
127
- * Creates a {@link Signal} that behaves like the input one, with the only difference that each call to the setter will trigger the effects even if the value didn't change.
128
- * Can give reactivity to a fake {@link Signal}
129
- * @param param0 The {@link Signal} to force
130
- */
131
- export declare function forceSignal<T>([get, set]: Signal<T>): Signal<T>;
132
-
133
134
  /** Parameters to pass to a keyed {@link Enfold} */
134
135
  declare type Keyed<T> = Standard<T> & {
135
136
  keyed: true;
@@ -197,7 +198,7 @@ export declare abstract class ReactiveContext<T> extends BASE_CTOR<T> {
197
198
  /**
198
199
  * Component that sets the value of the current {@link Context} for its children.
199
200
  * If no value is provided then it will use the default value for {@link ctx}.
200
- * The function is binded for the way solid compiles components inside other objects.
201
+ * The function is bound for the way solid compiles components inside other objects.
201
202
  * (The value is memoized)
202
203
  */
203
204
  get Provider(): (props: ParentProps<{
@@ -283,20 +284,6 @@ declare type Standard<T> = ParentProps<{
283
284
  /** Type of an element wrapping call-back which accepts an additional parameter */
284
285
  declare type Template<T> = (c: Accessor<JSX.Element>, x: T) => JSX.Element;
285
286
 
286
- /**
287
- * Creates a full-fledged solid {@link Setter} from a normal one
288
- * @param get The getter of the {@link Signal}; It's needed when a function gets passed to the new setter
289
- * @param set The simple setter to which to add functionalities
290
- */
291
- export declare function toSetter<T>(get: Accessor<T>, set: (x: T) => void): Setter<T>;
292
-
293
- /**
294
- * Creates a {@link Signal} from a property access
295
- * @param obj The {@link Accessor} to the object from which to get the property
296
- * @param k The {@link Accessor} to the key of the property
297
- */
298
- export declare function toSignal<T, K extends keyof T>(obj: Accessor<T>, k: Accessor<K>): Signal<T[K]>;
299
-
300
287
  /** Parameters to pass to an unkeyed {@link Enfold} */
301
288
  declare type Unkeyed<T> = Standard<T> & {
302
289
  keyed?: false;
@@ -321,18 +308,4 @@ export declare function untrackCall<F extends (...args: any[]) => unknown>(this:
321
308
  */
322
309
  export declare const unwrap: <T extends object>(f: Accessor<T>) => T;
323
310
 
324
- /**
325
- * Calls {@link f} maintaining its reactivity at 2 levels.
326
- * Unlike the normal {@link unwrap}, this maintains reactivity on the elements of the array too, which means that it can be destructured
327
- * ```ts
328
- * const first = unwrap(f); // The value of `first` is reactive but CANNOT be destructured
329
- * const [ getFirst ] = first; // The value of `getFirst()` is NOT reactive, it's the first element of the CURRENT signal returned by `f()`
330
- *
331
- * const second = unwrapSignal(f); // The value of `second` is reactive and CAN be destructured
332
- * const [ getSecond ] = second; // The value of `getSecond()` IS reactive, it's a function that calls `f()`, gets the first element and calls that too
333
- * ```
334
- * @param f An {@link Accessor} to a {@link Signal}
335
- */
336
- export declare function unwrapSignal<T>(f: Accessor<Signal<T>>): Signal<T>;
337
-
338
311
  export { }
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { useContext, createMemo, createComponent, createContext, createRoot, getOwner, untrack, splitProps, Show, onCleanup, For, Match, mergeProps, createComputed, on, createSignal } from "solid-js";
1
+ import { useContext, createMemo, createComponent, createContext, createRoot, getOwner, untrack, splitProps, Show, onCleanup, For, Match, mergeProps, on, createSignal } from "solid-js";
2
2
  import { createMutable } from "solid-js/store";
3
3
  const BASE_CTOR = Function;
4
4
  class ReactiveContext extends BASE_CTOR {
@@ -13,7 +13,7 @@ class ReactiveContext extends BASE_CTOR {
13
13
  /**
14
14
  * Component that sets the value of the current {@link Context} for its children.
15
15
  * If no value is provided then it will use the default value for {@link ctx}.
16
- * The function is binded for the way solid compiles components inside other objects.
16
+ * The function is bound for the way solid compiles components inside other objects.
17
17
  * (The value is memoized)
18
18
  */
19
19
  get Provider() {
@@ -224,38 +224,50 @@ function Case(props) {
224
224
  }
225
225
  }, other));
226
226
  }
227
- const IDENTITY = (x) => x;
228
- function bind(source, dest, to = IDENTITY, skip = false) {
229
- const d = createRoot((d2) => (createComputed(on(source, (x) => skip ? skip = false : dest((prev) => to(x, prev)))), d2));
230
- return onCleanup(d), d;
231
- }
232
- function bindTwoWay(source, dest, to, from) {
233
- const a = bind(source[0], dest[1], to);
234
- const b = bind(dest[0], source[1], from, true);
235
- return () => (a(), b());
236
- }
237
- function toSetter(get, set) {
238
- return (x) => {
239
- const out = typeof x === "function" ? x(untrack(get)) : x;
240
- return set(out), out;
241
- };
242
- }
243
- function toSignal(obj, k) {
244
- const get = () => obj()[k()];
245
- return [get, toSetter(get, (v) => obj()[k()] = v)];
246
- }
247
- function unwrapSignal(f) {
248
- return [() => f()[0](), (x) => f()[1](x)];
249
- }
250
- function forceSignal([get, set]) {
251
- const [track, update] = createSignal(void 0, { equals: false });
252
- return [
253
- () => (track(), get()),
254
- (x) => {
255
- const out = set(x);
256
- return update(), out;
257
- }
258
- ];
227
+ class Atom {
228
+ constructor(get, set) {
229
+ this.get = get;
230
+ this.set = set;
231
+ }
232
+ get value() {
233
+ return this.get();
234
+ }
235
+ set value(v) {
236
+ this.set(v);
237
+ }
238
+ /**
239
+ * Allows you to set the current {@link Atom} based on its current value.
240
+ * The current value gets read through {@link untrack} to mimic the {@link Setter} behaviour
241
+ * @param f Function that creates a new value based on the current one
242
+ */
243
+ update(f) {
244
+ return this.value = f(untrack(this.get));
245
+ }
246
+ /**
247
+ * Creates a new {@link Atom} that applies a conversion to the current one
248
+ * @param to Conversion function from {@link S} to {@link D}
249
+ * @param from Conversion function from {@link D} to {@link S}
250
+ */
251
+ convert(to, from) {
252
+ return new Atom(() => to(this.value), (x) => this.value = from(x));
253
+ }
254
+ /**
255
+ * Creates an {@link Atom} that forwards an {@link Accessor} to another {@link Atom}
256
+ * @param f The reactive {@link Accessor} to the {@link Atom} to forward
257
+ */
258
+ static unwrap(f) {
259
+ return new this(() => f().value, (x) => f().value = x);
260
+ }
261
+ /**
262
+ * Creates an {@link Atom} based on a {@link Signal}
263
+ * @param param0 The {@link Signal} to forward
264
+ */
265
+ static from([get, set]) {
266
+ return new this(get, (v) => set(() => v));
267
+ }
268
+ static source(bind, f = createSignal) {
269
+ return this.unwrap(createMemo(on(bind, (x) => x ?? Atom.from(f()))));
270
+ }
259
271
  }
260
272
  const debug = ReactiveContext.create(false, "debug-scope");
261
273
  function SameContext(props) {
@@ -265,23 +277,18 @@ function SameContext(props) {
265
277
  });
266
278
  }
267
279
  export {
280
+ Atom,
268
281
  Case,
269
282
  Enfold,
270
283
  On,
271
284
  ReactiveContext,
272
285
  SameContext,
273
286
  Slot,
274
- bind,
275
- bindTwoWay,
276
287
  createExtractor,
277
288
  debug,
278
- forceSignal,
279
289
  memoProps,
280
290
  runWithContext,
281
291
  splitAndMemoProps,
282
- toSetter,
283
- toSignal,
284
292
  untrackCall,
285
- unwrap,
286
- unwrapSignal
293
+ unwrap
287
294
  };
package/dist/index.umd.js CHANGED
@@ -15,7 +15,7 @@
15
15
  /**
16
16
  * Component that sets the value of the current {@link Context} for its children.
17
17
  * If no value is provided then it will use the default value for {@link ctx}.
18
- * The function is binded for the way solid compiles components inside other objects.
18
+ * The function is bound for the way solid compiles components inside other objects.
19
19
  * (The value is memoized)
20
20
  */
21
21
  get Provider() {
@@ -226,38 +226,50 @@
226
226
  }
227
227
  }, other));
228
228
  }
229
- const IDENTITY = (x) => x;
230
- function bind(source, dest, to = IDENTITY, skip = false) {
231
- const d = solidJs.createRoot((d2) => (solidJs.createComputed(solidJs.on(source, (x) => skip ? skip = false : dest((prev) => to(x, prev)))), d2));
232
- return solidJs.onCleanup(d), d;
233
- }
234
- function bindTwoWay(source, dest, to, from) {
235
- const a = bind(source[0], dest[1], to);
236
- const b = bind(dest[0], source[1], from, true);
237
- return () => (a(), b());
238
- }
239
- function toSetter(get, set) {
240
- return (x) => {
241
- const out = typeof x === "function" ? x(solidJs.untrack(get)) : x;
242
- return set(out), out;
243
- };
244
- }
245
- function toSignal(obj, k) {
246
- const get = () => obj()[k()];
247
- return [get, toSetter(get, (v) => obj()[k()] = v)];
248
- }
249
- function unwrapSignal(f) {
250
- return [() => f()[0](), (x) => f()[1](x)];
251
- }
252
- function forceSignal([get, set]) {
253
- const [track, update] = solidJs.createSignal(void 0, { equals: false });
254
- return [
255
- () => (track(), get()),
256
- (x) => {
257
- const out = set(x);
258
- return update(), out;
259
- }
260
- ];
229
+ class Atom {
230
+ constructor(get, set) {
231
+ this.get = get;
232
+ this.set = set;
233
+ }
234
+ get value() {
235
+ return this.get();
236
+ }
237
+ set value(v) {
238
+ this.set(v);
239
+ }
240
+ /**
241
+ * Allows you to set the current {@link Atom} based on its current value.
242
+ * The current value gets read through {@link untrack} to mimic the {@link Setter} behaviour
243
+ * @param f Function that creates a new value based on the current one
244
+ */
245
+ update(f) {
246
+ return this.value = f(solidJs.untrack(this.get));
247
+ }
248
+ /**
249
+ * Creates a new {@link Atom} that applies a conversion to the current one
250
+ * @param to Conversion function from {@link S} to {@link D}
251
+ * @param from Conversion function from {@link D} to {@link S}
252
+ */
253
+ convert(to, from) {
254
+ return new Atom(() => to(this.value), (x) => this.value = from(x));
255
+ }
256
+ /**
257
+ * Creates an {@link Atom} that forwards an {@link Accessor} to another {@link Atom}
258
+ * @param f The reactive {@link Accessor} to the {@link Atom} to forward
259
+ */
260
+ static unwrap(f) {
261
+ return new this(() => f().value, (x) => f().value = x);
262
+ }
263
+ /**
264
+ * Creates an {@link Atom} based on a {@link Signal}
265
+ * @param param0 The {@link Signal} to forward
266
+ */
267
+ static from([get, set]) {
268
+ return new this(get, (v) => set(() => v));
269
+ }
270
+ static source(bind, f = solidJs.createSignal) {
271
+ return this.unwrap(solidJs.createMemo(solidJs.on(bind, (x) => x ?? Atom.from(f()))));
272
+ }
261
273
  }
262
274
  const debug = ReactiveContext.create(false, "debug-scope");
263
275
  function SameContext(props) {
@@ -266,23 +278,18 @@
266
278
  return props.children;
267
279
  });
268
280
  }
281
+ exports2.Atom = Atom;
269
282
  exports2.Case = Case;
270
283
  exports2.Enfold = Enfold;
271
284
  exports2.On = On;
272
285
  exports2.ReactiveContext = ReactiveContext;
273
286
  exports2.SameContext = SameContext;
274
- exports2.bind = bind;
275
- exports2.bindTwoWay = bindTwoWay;
276
287
  exports2.createExtractor = createExtractor;
277
288
  exports2.debug = debug;
278
- exports2.forceSignal = forceSignal;
279
289
  exports2.memoProps = memoProps;
280
290
  exports2.runWithContext = runWithContext;
281
291
  exports2.splitAndMemoProps = splitAndMemoProps;
282
- exports2.toSetter = toSetter;
283
- exports2.toSignal = toSignal;
284
292
  exports2.untrackCall = untrackCall;
285
293
  exports2.unwrap = unwrap;
286
- exports2.unwrapSignal = unwrapSignal;
287
294
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
288
295
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solid-ctrl-flow",
3
- "version": "1.0.57",
3
+ "version": "1.0.59",
4
4
  "description": "Control flow components for solid-js",
5
5
  "author": "AFatNiBBa",
6
6
  "license": "ISC",
package/readMe.md CHANGED
@@ -162,26 +162,26 @@ return <>
162
162
 
163
163
  ## Utility
164
164
 
165
- ### Bindings
166
- Functions that create bindings between `Signal`s
165
+ ### `Atom`s
166
+ Customizable and simplified wrappers for reactive states
167
167
 
168
- > #### `bind()`
169
- > Creates a one-way binding between two `Signal`s
168
+ > #### `new Atom()`
169
+ > Creates an `Atom` with custom getter and setter
170
170
  >
171
- > #### `bindTwoWay()`
172
- > Creates a two-way binding between two `Signal`s
171
+ > #### `Atom.update()`
172
+ > Like the `Setter` overload of a `Signal` that takes a function with the previous value
173
173
  >
174
- > #### `toSetter()`
175
- > Creates a full-fledged solid `Setter` from a normal one
174
+ > #### `Atom.convert()`
175
+ > Creates a new `Atom` that applies a conversion to the current one
176
176
  >
177
- > #### `toSignal()`
178
- > Creates a `Signal` from a property of an object
177
+ > #### `Atom.unwrap()`
178
+ > An `Atom`-specific (optimized) version of `unwrap()` that allows the destructuring of its result
179
179
  >
180
- > #### `unwrapSignal()`
181
- > A `Signal`-specific version of `unwrap()` that allows the destructuring of its result
180
+ > #### `Atom.from()`
181
+ > Creates an `Atom` from a `Signal`
182
182
  >
183
- > #### `forceSignal()`
184
- > Creates a `Signal` that behaves like the input one, with the only difference that each call to the setter will trigger the effects even if the value didn't change
183
+ > #### `Atom.source()`
184
+ > Similiar to `Atom.unwrap()`, but if the `Accessor` doesn't return anything it automatically creates an internal `Signal` in which to store the value
185
185
 
186
186
  ### `ReactiveContext.create()`
187
187
  Method that creates a reactive version of a solid `Context` with some additional built-in functionalities
@@ -0,0 +1,22 @@
1
+
2
+ import dtsPlugin from "vite-plugin-dts";
3
+ import solidPlugin from "vite-plugin-solid";
4
+ import { defineConfig } from "vite";
5
+ import { join } from "path";
6
+
7
+ export default defineConfig({
8
+ plugins: [ dtsPlugin({ rollupTypes: true }), solidPlugin() ],
9
+ build: {
10
+ minify: false,
11
+ target: "ESNext",
12
+ lib: {
13
+ entry: join(__dirname, "src/index.ts"),
14
+ fileName: "index",
15
+ name: "solidCtrlFlow"
16
+ },
17
+ rollupOptions: {
18
+ output: { globals: x => x.replace(/\W(\w)/g, (_, x) => x.toUpperCase()) },
19
+ external: [ "solid-js", "solid-js/store" ]
20
+ }
21
+ }
22
+ });