solid-ctrl-flow 1.0.56 → 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
@@ -1,44 +1,54 @@
1
1
  import { Accessor } from 'solid-js';
2
2
  import { Context } from 'solid-js';
3
- import { EffectFunction } from 'solid-js';
4
3
  import { JSX } from 'solid-js';
5
4
  import { MemoOptions } from 'solid-js';
6
5
  import { Owner } from 'solid-js';
7
6
  import { ParentProps } from 'solid-js';
8
- import { Resource } from 'solid-js';
9
- import { Setter } from 'solid-js';
10
7
  import { Signal } from 'solid-js';
11
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
+
12
49
  /** Type hack for making {@link ReactiveContext} implement {@link Accessor} */
13
50
  declare const BASE_CTOR: new <T>() => Accessor<T>;
14
51
 
15
- /**
16
- * Creates a one-way binding between two {@link Signal}s.
17
- * The function uses {@link createComputed}, which means that:
18
- * - As soon as the function is done executing the two {@link Signal}s will have the same value
19
- * - If {@link source} changes, {@link dest} will be instantly updated
20
- * @param source The getter of the source of the binding
21
- * @param dest The setter of the destination of the binding
22
- * @param to Conversion function from {@link S} to {@link D}
23
- * @param skip If it is `true`, {@link dest} won't be executed until the next change
24
- * @returns A function that disposes the binding
25
- */
26
- export declare function bind<S>(source: Accessor<S>, dest: Setter<S>, to?: undefined, skip?: boolean): () => void;
27
-
28
- export declare function bind<S, D>(source: Accessor<S>, dest: Setter<D>, to: Convert<S, D>, skip?: boolean): () => void;
29
-
30
- /**
31
- * Creates a two-way binding between two {@link Signal}s calling {@link bind} two times
32
- * @param source The source of the binding
33
- * @param dest The destination of the binding
34
- * @param to Conversion function from {@link S} to {@link D}
35
- * @param from Conversion function from {@link D} to {@link S}
36
- * @returns A function that disposes the binding
37
- */
38
- export declare function bindTwoWay<S>(source: Signal<S>, dest: Signal<S>): () => void;
39
-
40
- export declare function bindTwoWay<S, D>(source: Signal<S>, dest: Signal<D>, to: Convert<S, D>, from: Convert<D, S>): () => void;
41
-
42
52
  /** Like a {@link Match} but gets the value from the closest {@link On} ancestor */
43
53
  export declare function Case(props: ParentProps<{
44
54
  value: unknown;
@@ -60,9 +70,6 @@ export declare function Case<T>(props: {
60
70
  children(x: NonNullable<T>): JSX.Element;
61
71
  }): JSX.Element;
62
72
 
63
- /** Conversion function for bindings */
64
- export declare type Convert<S, D> = (x: S, prev: D) => D;
65
-
66
73
  /**
67
74
  * Creates a slot that allows you to show a component outside of its parent.
68
75
  * It works with arbitrary nesting.
@@ -107,14 +114,6 @@ export declare function createExtractor(name?: string): {
107
114
  readonly extracting: () => number | null;
108
115
  };
109
116
 
110
- /**
111
- * Creates a {@link Resource} from the function {@link f}.
112
- * The resource will be refetched each time one of the dependencies of {@link f} changes.
113
- * The only dependant signals that will be tracked are the ones before the first `await`
114
- * @param f A reactive resource fetcher
115
- */
116
- export declare function createReactiveResource<R>(f: EffectFunction<R | undefined, R>): Resource<Awaited<R>>;
117
-
118
117
  /** Built-in {@link ReactiveContext} which allows you to display different things in debug mode */
119
118
  export declare const debug: ReactiveContext<boolean>;
120
119
 
@@ -133,13 +132,6 @@ export declare function Enfold<T>(props: Unkeyed<T>): JSX.Element;
133
132
  /** Handy type alias */
134
133
  declare type Equals = MemoOptions<unknown>["equals"];
135
134
 
136
- /**
137
- * 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.
138
- * Can give reactivity to a fake {@link Signal}
139
- * @param param0 The {@link Signal} to force
140
- */
141
- export declare function forceSignal<T>([get, set]: Signal<T>): Signal<T>;
142
-
143
135
  /** Parameters to pass to a keyed {@link Enfold} */
144
136
  declare type Keyed<T> = Standard<T> & {
145
137
  keyed: true;
@@ -207,7 +199,7 @@ export declare abstract class ReactiveContext<T> extends BASE_CTOR<T> {
207
199
  /**
208
200
  * Component that sets the value of the current {@link Context} for its children.
209
201
  * If no value is provided then it will use the default value for {@link ctx}.
210
- * 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.
211
203
  * (The value is memoized)
212
204
  */
213
205
  get Provider(): (props: ParentProps<{
@@ -293,20 +285,6 @@ declare type Standard<T> = ParentProps<{
293
285
  /** Type of an element wrapping call-back which accepts an additional parameter */
294
286
  declare type Template<T> = (c: Accessor<JSX.Element>, x: T) => JSX.Element;
295
287
 
296
- /**
297
- * Creates a full-fledged solid {@link Setter} from a normal one
298
- * @param get The getter of the {@link Signal}; It's needed when a function gets passed to the new setter
299
- * @param set The simple setter to which to add functionalities
300
- */
301
- export declare function toSetter<T>(get: Accessor<T>, set: (x: T) => void): Setter<T>;
302
-
303
- /**
304
- * Creates a {@link Signal} from a property access
305
- * @param obj The {@link Accessor} to the object from which to get the property
306
- * @param k The {@link Accessor} to the key of the property
307
- */
308
- export declare function toSignal<T, K extends keyof T>(obj: Accessor<T>, k: Accessor<K>): Signal<T[K]>;
309
-
310
288
  /** Parameters to pass to an unkeyed {@link Enfold} */
311
289
  declare type Unkeyed<T> = Standard<T> & {
312
290
  keyed?: false;
@@ -331,18 +309,4 @@ export declare function untrackCall<F extends (...args: any[]) => unknown>(this:
331
309
  */
332
310
  export declare const unwrap: <T extends object>(f: Accessor<T>) => T;
333
311
 
334
- /**
335
- * Calls {@link f} maintaining its reactivity at 2 levels.
336
- * Unlike the normal {@link unwrap}, this maintains reactivity on the elements of the array too, which means that it can be destructured
337
- * ```ts
338
- * const first = unwrap(f); // The value of `first` is reactive but CANNOT be destructured
339
- * const [ getFirst ] = first; // The value of `getFirst()` is NOT reactive, it's the first element of the CURRENT signal returned by `f()`
340
- *
341
- * const second = unwrapSignal(f); // The value of `second` is reactive and CAN be destructured
342
- * const [ getSecond ] = second; // The value of `getSecond()` IS reactive, it's a function that calls `f()`, gets the first element and calls that too
343
- * ```
344
- * @param f An {@link Accessor} to a {@link Signal}
345
- */
346
- export declare function unwrapSignal<T>(f: Accessor<Signal<T>>): Signal<T>;
347
-
348
312
  export { }
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { useContext, createMemo, createComponent, createContext, createRoot, getOwner, untrack, createEffect, on, createResource, splitProps, Show, onCleanup, For, Match, mergeProps, createComputed, 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() {
@@ -67,13 +67,6 @@ function runWithContext(ctx2, value, f) {
67
67
  function untrackCall(f, ...args) {
68
68
  return untrack(() => f.apply(this, args));
69
69
  }
70
- function createReactiveResource(f) {
71
- var refetch;
72
- const memo = createMemo(f);
73
- createEffect(on(memo, () => refetch?.()));
74
- const [get] = [, { refetch }] = createResource(memo);
75
- return get;
76
- }
77
70
  function memoProps(obj, keys = Object.keys(obj), equals = false) {
78
71
  const out = {};
79
72
  for (const elm of keys)
@@ -231,38 +224,51 @@ function Case(props) {
231
224
  }
232
225
  }, other));
233
226
  }
234
- const IDENTITY = (x) => x;
235
- function bind(source, dest, to = IDENTITY, skip = false) {
236
- const d = createRoot((d2) => (createComputed(on(source, (x) => skip ? skip = false : dest((prev) => to(x, prev)))), d2));
237
- return onCleanup(d), d;
238
- }
239
- function bindTwoWay(source, dest, to, from) {
240
- const a = bind(source[0], dest[1], to);
241
- const b = bind(dest[0], source[1], from, true);
242
- return () => (a(), b());
243
- }
244
- function toSetter(get, set) {
245
- return (x) => {
246
- const out = typeof x === "function" ? x(untrack(get)) : x;
247
- return set(out), out;
248
- };
249
- }
250
- function toSignal(obj, k) {
251
- const get = () => obj()[k()];
252
- return [get, toSetter(get, (v) => obj()[k()] = v)];
253
- }
254
- function unwrapSignal(f) {
255
- return [() => f()[0](), (x) => f()[1](x)];
256
- }
257
- function forceSignal([get, set]) {
258
- const [track, update] = createSignal(void 0, { equals: false });
259
- return [
260
- () => (track(), get()),
261
- (x) => {
262
- const out = set(x);
263
- return update(), out;
264
- }
265
- ];
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
+ }
266
272
  }
267
273
  const debug = ReactiveContext.create(false, "debug-scope");
268
274
  function SameContext(props) {
@@ -272,24 +278,18 @@ function SameContext(props) {
272
278
  });
273
279
  }
274
280
  export {
281
+ Atom,
275
282
  Case,
276
283
  Enfold,
277
284
  On,
278
285
  ReactiveContext,
279
286
  SameContext,
280
287
  Slot,
281
- bind,
282
- bindTwoWay,
283
288
  createExtractor,
284
- createReactiveResource,
285
289
  debug,
286
- forceSignal,
287
290
  memoProps,
288
291
  runWithContext,
289
292
  splitAndMemoProps,
290
- toSetter,
291
- toSignal,
292
293
  untrackCall,
293
- unwrap,
294
- unwrapSignal
294
+ unwrap
295
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() {
@@ -69,13 +69,6 @@
69
69
  function untrackCall(f, ...args) {
70
70
  return solidJs.untrack(() => f.apply(this, args));
71
71
  }
72
- function createReactiveResource(f) {
73
- var refetch;
74
- const memo = solidJs.createMemo(f);
75
- solidJs.createEffect(solidJs.on(memo, () => refetch?.()));
76
- const [get] = [, { refetch }] = solidJs.createResource(memo);
77
- return get;
78
- }
79
72
  function memoProps(obj, keys = Object.keys(obj), equals = false) {
80
73
  const out = {};
81
74
  for (const elm of keys)
@@ -233,38 +226,51 @@
233
226
  }
234
227
  }, other));
235
228
  }
236
- const IDENTITY = (x) => x;
237
- function bind(source, dest, to = IDENTITY, skip = false) {
238
- const d = solidJs.createRoot((d2) => (solidJs.createComputed(solidJs.on(source, (x) => skip ? skip = false : dest((prev) => to(x, prev)))), d2));
239
- return solidJs.onCleanup(d), d;
240
- }
241
- function bindTwoWay(source, dest, to, from) {
242
- const a = bind(source[0], dest[1], to);
243
- const b = bind(dest[0], source[1], from, true);
244
- return () => (a(), b());
245
- }
246
- function toSetter(get, set) {
247
- return (x) => {
248
- const out = typeof x === "function" ? x(solidJs.untrack(get)) : x;
249
- return set(out), out;
250
- };
251
- }
252
- function toSignal(obj, k) {
253
- const get = () => obj()[k()];
254
- return [get, toSetter(get, (v) => obj()[k()] = v)];
255
- }
256
- function unwrapSignal(f) {
257
- return [() => f()[0](), (x) => f()[1](x)];
258
- }
259
- function forceSignal([get, set]) {
260
- const [track, update] = solidJs.createSignal(void 0, { equals: false });
261
- return [
262
- () => (track(), get()),
263
- (x) => {
264
- const out = set(x);
265
- return update(), out;
266
- }
267
- ];
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
+ }
268
274
  }
269
275
  const debug = ReactiveContext.create(false, "debug-scope");
270
276
  function SameContext(props) {
@@ -273,24 +279,18 @@
273
279
  return props.children;
274
280
  });
275
281
  }
282
+ exports2.Atom = Atom;
276
283
  exports2.Case = Case;
277
284
  exports2.Enfold = Enfold;
278
285
  exports2.On = On;
279
286
  exports2.ReactiveContext = ReactiveContext;
280
287
  exports2.SameContext = SameContext;
281
- exports2.bind = bind;
282
- exports2.bindTwoWay = bindTwoWay;
283
288
  exports2.createExtractor = createExtractor;
284
- exports2.createReactiveResource = createReactiveResource;
285
289
  exports2.debug = debug;
286
- exports2.forceSignal = forceSignal;
287
290
  exports2.memoProps = memoProps;
288
291
  exports2.runWithContext = runWithContext;
289
292
  exports2.splitAndMemoProps = splitAndMemoProps;
290
- exports2.toSetter = toSetter;
291
- exports2.toSignal = toSignal;
292
293
  exports2.untrackCall = untrackCall;
293
294
  exports2.unwrap = unwrap;
294
- exports2.unwrapSignal = unwrapSignal;
295
295
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
296
296
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solid-ctrl-flow",
3
- "version": "1.0.56",
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
@@ -215,9 +215,6 @@ return <>
215
215
  ### `untrackCall()`
216
216
  Calls a function untracking what happens inside of it but not what gets passed as its argument
217
217
 
218
- ### `createReactiveResource()`
219
- Like `createResource()` but the provided function will be reactive
220
-
221
218
  ### `memoProps()`
222
219
  Creates a partial version of an object with memoized remaining properties
223
220
 
@@ -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
+ });