solid-ctrl-flow 1.0.57 → 1.0.58

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,51 @@ 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 an {@link Atom} that forwards an {@link Accessor} to another {@link Atom}
24
+ * @param f The reactive {@link Accessor} to the {@link Atom} to forward
25
+ */
26
+ static unwrap<T>(f: Accessor<Atom<T>>): Atom<T>;
27
+ /**
28
+ * Creates an {@link Atom} based on a {@link Signal}
29
+ * @param param0 The {@link Signal} to forward
30
+ */
31
+ static from<T>([get, set]: Signal<T>): Atom<T>;
32
+ /**
33
+ * Creates a new {@link Atom} that applies a conversion to another {@link Atom}
34
+ * @param atom The {@link Atom} to which to apply the conversion
35
+ * @param to Conversion function from {@link S} to {@link D}
36
+ * @param from Conversion function from {@link D} to {@link S}
37
+ */
38
+ static convert<S, D>(atom: Atom<S>, to: (x: S) => D, from: (x: D) => S): Atom<D>;
39
+ /**
40
+ * Creates a bindable data source.
41
+ * 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
42
+ * @param bind The bound {@link Atom}
43
+ * @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
44
+ */
45
+ static source<T>(bind: Accessor<Atom<T> | undefined>): Atom<T | undefined>;
46
+ static source<T>(bind: Accessor<Atom<T> | undefined>, f: Accessor<Signal<T>>): Atom<T>;
47
+ }
48
+
10
49
  /** Type hack for making {@link ReactiveContext} implement {@link Accessor} */
11
50
  declare const BASE_CTOR: new <T>() => Accessor<T>;
12
51
 
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
52
  /** Like a {@link Match} but gets the value from the closest {@link On} ancestor */
41
53
  export declare function Case(props: ParentProps<{
42
54
  value: unknown;
@@ -58,9 +70,6 @@ export declare function Case<T>(props: {
58
70
  children(x: NonNullable<T>): JSX.Element;
59
71
  }): JSX.Element;
60
72
 
61
- /** Conversion function for bindings */
62
- export declare type Convert<S, D> = (x: S, prev: D) => D;
63
-
64
73
  /**
65
74
  * Creates a slot that allows you to show a component outside of its parent.
66
75
  * It works with arbitrary nesting.
@@ -123,13 +132,6 @@ export declare function Enfold<T>(props: Unkeyed<T>): JSX.Element;
123
132
  /** Handy type alias */
124
133
  declare type Equals = MemoOptions<unknown>["equals"];
125
134
 
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
135
  /** Parameters to pass to a keyed {@link Enfold} */
134
136
  declare type Keyed<T> = Standard<T> & {
135
137
  keyed: true;
@@ -197,7 +199,7 @@ export declare abstract class ReactiveContext<T> extends BASE_CTOR<T> {
197
199
  /**
198
200
  * Component that sets the value of the current {@link Context} for its children.
199
201
  * 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.
202
+ * The function is bound for the way solid compiles components inside other objects.
201
203
  * (The value is memoized)
202
204
  */
203
205
  get Provider(): (props: ParentProps<{
@@ -283,20 +285,6 @@ declare type Standard<T> = ParentProps<{
283
285
  /** Type of an element wrapping call-back which accepts an additional parameter */
284
286
  declare type Template<T> = (c: Accessor<JSX.Element>, x: T) => JSX.Element;
285
287
 
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
288
  /** Parameters to pass to an unkeyed {@link Enfold} */
301
289
  declare type Unkeyed<T> = Standard<T> & {
302
290
  keyed?: false;
@@ -321,18 +309,4 @@ export declare function untrackCall<F extends (...args: any[]) => unknown>(this:
321
309
  */
322
310
  export declare const unwrap: <T extends object>(f: Accessor<T>) => T;
323
311
 
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
312
  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,51 @@ 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 an {@link Atom} that forwards an {@link Accessor} to another {@link Atom}
248
+ * @param f The reactive {@link Accessor} to the {@link Atom} to forward
249
+ */
250
+ static unwrap(f) {
251
+ return new this(() => f().value, (x) => f().value = x);
252
+ }
253
+ /**
254
+ * Creates an {@link Atom} based on a {@link Signal}
255
+ * @param param0 The {@link Signal} to forward
256
+ */
257
+ static from([get, set]) {
258
+ return new this(get, (v) => set(() => v));
259
+ }
260
+ /**
261
+ * Creates a new {@link Atom} that applies a conversion to another {@link Atom}
262
+ * @param atom The {@link Atom} to which to apply the conversion
263
+ * @param to Conversion function from {@link S} to {@link D}
264
+ * @param from Conversion function from {@link D} to {@link S}
265
+ */
266
+ static convert(atom, to, from) {
267
+ return new this(() => to(atom.value), (x) => atom.value = from(x));
268
+ }
269
+ static source(bind, f = createSignal) {
270
+ return this.unwrap(createMemo(on(bind, (x) => x ?? Atom.from(f()))));
271
+ }
259
272
  }
260
273
  const debug = ReactiveContext.create(false, "debug-scope");
261
274
  function SameContext(props) {
@@ -265,23 +278,18 @@ function SameContext(props) {
265
278
  });
266
279
  }
267
280
  export {
281
+ Atom,
268
282
  Case,
269
283
  Enfold,
270
284
  On,
271
285
  ReactiveContext,
272
286
  SameContext,
273
287
  Slot,
274
- bind,
275
- bindTwoWay,
276
288
  createExtractor,
277
289
  debug,
278
- forceSignal,
279
290
  memoProps,
280
291
  runWithContext,
281
292
  splitAndMemoProps,
282
- toSetter,
283
- toSignal,
284
293
  untrackCall,
285
- unwrap,
286
- unwrapSignal
294
+ unwrap
287
295
  };
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,51 @@
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 an {@link Atom} that forwards an {@link Accessor} to another {@link Atom}
250
+ * @param f The reactive {@link Accessor} to the {@link Atom} to forward
251
+ */
252
+ static unwrap(f) {
253
+ return new this(() => f().value, (x) => f().value = x);
254
+ }
255
+ /**
256
+ * Creates an {@link Atom} based on a {@link Signal}
257
+ * @param param0 The {@link Signal} to forward
258
+ */
259
+ static from([get, set]) {
260
+ return new this(get, (v) => set(() => v));
261
+ }
262
+ /**
263
+ * Creates a new {@link Atom} that applies a conversion to another {@link Atom}
264
+ * @param atom The {@link Atom} to which to apply the conversion
265
+ * @param to Conversion function from {@link S} to {@link D}
266
+ * @param from Conversion function from {@link D} to {@link S}
267
+ */
268
+ static convert(atom, to, from) {
269
+ return new this(() => to(atom.value), (x) => atom.value = from(x));
270
+ }
271
+ static source(bind, f = solidJs.createSignal) {
272
+ return this.unwrap(solidJs.createMemo(solidJs.on(bind, (x) => x ?? Atom.from(f()))));
273
+ }
261
274
  }
262
275
  const debug = ReactiveContext.create(false, "debug-scope");
263
276
  function SameContext(props) {
@@ -266,23 +279,18 @@
266
279
  return props.children;
267
280
  });
268
281
  }
282
+ exports2.Atom = Atom;
269
283
  exports2.Case = Case;
270
284
  exports2.Enfold = Enfold;
271
285
  exports2.On = On;
272
286
  exports2.ReactiveContext = ReactiveContext;
273
287
  exports2.SameContext = SameContext;
274
- exports2.bind = bind;
275
- exports2.bindTwoWay = bindTwoWay;
276
288
  exports2.createExtractor = createExtractor;
277
289
  exports2.debug = debug;
278
- exports2.forceSignal = forceSignal;
279
290
  exports2.memoProps = memoProps;
280
291
  exports2.runWithContext = runWithContext;
281
292
  exports2.splitAndMemoProps = splitAndMemoProps;
282
- exports2.toSetter = toSetter;
283
- exports2.toSignal = toSignal;
284
293
  exports2.untrackCall = untrackCall;
285
294
  exports2.unwrap = unwrap;
286
- exports2.unwrapSignal = unwrapSignal;
287
295
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
288
296
  });
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.58",
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.unwrap()`
175
+ > An `Atom`-specific (optimized) version of `unwrap()` that allows the destructuring of its result
176
176
  >
177
- > #### `toSignal()`
178
- > Creates a `Signal` from a property of an object
177
+ > #### `Atom.from()`
178
+ > Creates an `Atom` from a `Signal`
179
179
  >
180
- > #### `unwrapSignal()`
181
- > A `Signal`-specific version of `unwrap()` that allows the destructuring of its result
180
+ > #### `Atom.convert()`
181
+ > Creates a new `Atom` that applies a conversion to another `Atom`
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
+ });