solid-ctrl-flow 1.0.39 → 1.0.40

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
@@ -3,7 +3,6 @@ import { Context } from 'solid-js';
3
3
  import { EffectFunction } from 'solid-js';
4
4
  import { JSX } from 'solid-js';
5
5
  import { MemoOptions } from 'solid-js';
6
- import { Ref } from 'solid-js';
7
6
  import { Resource } from 'solid-js';
8
7
  import { Setter } from 'solid-js';
9
8
  import { Signal } from 'solid-js';
@@ -133,6 +132,18 @@ export declare function createReactiveResource<R>(f: EffectFunction<R | undefine
133
132
  /** Built-in {@link ReactiveContext} which allows you to display different things in debug mode */
134
133
  export declare const debug: ReactiveContext<boolean>;
135
134
 
135
+ /**
136
+ * Eventually wraps its content into a template if a certain condition is met.
137
+ * The content is memoized in the beginning and will be recycled even if the wrapper changes.
138
+ * You can avoid the memoization trought {@link Standard.unrecycled}, this is needed if you want to use a context provider on your template.
139
+ * If {@link Keyed.keyed} is active, the template will be executed each time the content of {@link Standard.when} changes.
140
+ * If {@link Standard.unrecycled} is active, the content will be executed each time it is mounted (Each time {@link Standard.when} goes from a falsish value to a truish one and vice versa).
141
+ * If both {@link Keyed.keyed} and {@link Standard.unrecycled} are active, the content will be executed each time {@link Standard.when} changes
142
+ */
143
+ export declare function Enfold<T>(props: Keyed<T>): JSX.Element;
144
+
145
+ export declare function Enfold<T>(props: Unkeyed<T>): JSX.Element;
146
+
136
147
  /** Handy type alias */
137
148
  declare type Equals = MemoOptions<unknown>["equals"];
138
149
 
@@ -143,6 +154,12 @@ declare type Info = {
143
154
  children: JSX.Element;
144
155
  };
145
156
 
157
+ /** Parameters to pass to a keyed {@link Enfold} */
158
+ declare type Keyed<T> = Standard<T> & {
159
+ keyed: true;
160
+ template: Template<NonNullable<T>>;
161
+ };
162
+
146
163
  /**
147
164
  * Memoizes some of the properties of {@link obj}.
148
165
  * If {@link keys} is not provided, memoizes everything that get returned by {@link Object.keys} when provided with {@link obj}.
@@ -158,11 +175,11 @@ export declare function memoProps<T, K extends readonly (keyof T)[]>(obj: T, key
158
175
  /**
159
176
  * Like a {@link For}, but instead of putting an element after another it nests them.
160
177
  * The component will try to recycle the layers when the source array changes (Once again, like the {@link For}).
161
- * Due to the recyling, the layers will be created indipendently, thus their {@link Owner}s won't be nested in their parents' ones.
178
+ * Due to the recyling, the layers will be created indipendently, thus their {@link Owner}s won't be nested in their parents' ones, this makes the component unsuitable to wrap the content with context providers.
162
179
  * Example:
163
180
  * ```tsx
164
181
  * return <>
165
- * <Nest each={[ 1, 2, 3 ]} template={(x, y) => <>({x}, {y()}, -{x})</>}>
182
+ * <Nest each={[ 1, 2, 3 ]} template={(c, x) => <>({x}, {c()}, -{x})</>}>
166
183
  * content
167
184
  * </Nest>
168
185
  * </>
@@ -170,8 +187,8 @@ export declare function memoProps<T, K extends readonly (keyof T)[]>(obj: T, key
170
187
  * Will output "(1, (2, (3, content, -3), -2), -1)"
171
188
  */
172
189
  export declare function Nest<T>(props: {
173
- each: T[];
174
- template: (x: T, c: Accessor<JSX.Element>, i: Accessor<number>) => JSX.Element;
190
+ each: readonly T[] | undefined;
191
+ template: (c: Accessor<JSX.Element>, x: T, i: Accessor<number>) => JSX.Element;
175
192
  children: JSX.Element;
176
193
  }): JSX.Element;
177
194
 
@@ -214,15 +231,6 @@ export declare abstract class ReactiveContext<T> extends BASE_CTOR<T> {
214
231
  static create<T>(defaultValue: T, name?: string): ReactiveContext<T>;
215
232
  }
216
233
 
217
- /**
218
- * Executes a {@link Ref}.
219
- * Throws a {@link ReferenceError} if {@link ref} its not a function at runtime (Which should never be the case thanks to the solid compiler)
220
- * @param ref The function to execute
221
- * @param value The value to pass to the function
222
- * @returns The same value of {@link value}
223
- */
224
- export declare function refCall<T, U extends T = T>(ref: Ref<T> | undefined, value: U): U;
225
-
226
234
  /**
227
235
  * Executes {@link f} with the provided value for the specified {@link Context}.
228
236
  * You can pass `undefined` to {@link value} in order to get back the default value for {@link ctx}.
@@ -244,6 +252,16 @@ export declare function runWithContext<T, R>(ctx: Context<T>, value: T | undefin
244
252
  */
245
253
  export declare function splitAndMemoProps<T extends Record<any, any>, K extends readonly (keyof T)[]>(obj: T, keys: K, equals?: Equals): [Pick<T, Extract<K, readonly (keyof T)[]>[number]>, Omit<T, K[number]>];
246
254
 
255
+ /** Standard parameters to pass to an {@link Enfold} */
256
+ declare type Standard<T> = {
257
+ when: T;
258
+ children: JSX.Element;
259
+ unrecycled?: boolean;
260
+ };
261
+
262
+ /** Type of an element wrapping call-back which accepts an additional parameter */
263
+ declare type Template<T> = (c: Accessor<JSX.Element>, x: T) => JSX.Element;
264
+
247
265
  /**
248
266
  * Creates a full-fledged solid {@link Setter} from a normal one
249
267
  * @param get The getter of the {@link Signal}; It's needed when a function gets passed to the new setter
@@ -258,6 +276,12 @@ export declare function toSetter<T>(get: Accessor<T>, set: (x: T) => void): Sett
258
276
  */
259
277
  export declare function toSignal<T, K extends keyof T>(obj: Accessor<T>, k: Accessor<K>): Signal<T[K]>;
260
278
 
279
+ /** Parameters to pass to an unkeyed {@link Enfold} */
280
+ declare type Unkeyed<T> = Standard<T> & {
281
+ keyed?: false;
282
+ template: Template<Accessor<NonNullable<T>>>;
283
+ };
284
+
261
285
  /**
262
286
  * Executes {@link f} untracking it.
263
287
  * Due to the fact that the function is passed as input, it does not untrack its changes (It's intentional)
@@ -269,11 +293,25 @@ export declare function toSignal<T, K extends keyof T>(obj: Accessor<T>, k: Acce
269
293
  export declare function untrackCall<F extends (...args: any[]) => unknown>(this: ThisParameterType<F>, f: F, ...args: Parameters<F>): ReturnType<F>;
270
294
 
271
295
  /**
272
- * Calls an {@link Accessor} maintaining its reactivity
296
+ * Calls an {@link Accessor} maintaining its reactivity at 1 level
273
297
  * @param f The {@link Accessor} to the value to emulate
274
298
  * @returns A {@link Proxy} that copies the functionalities of the result of {@link f} calling it for each interaction, thus maintaining reactivity
275
299
  */
276
- export declare const unwrap: <T>(f: Accessor<T>) => T;
300
+ export declare const unwrap: <T extends object>(f: Accessor<T>) => T;
301
+
302
+ /**
303
+ * Calls {@link f} maintaining its reactivity at 2 levels.
304
+ * Unlike the normal {@link unwrap}, this maintains reactivity on the elements of the array too, which means that it can be destructured
305
+ * ```ts
306
+ * const first = unwrap(f); // The value of "first" is reactive but CANNOT be destructured
307
+ * const [ getFirst ] = first; // The value of "getFirst" is NOT reactive, it's the first element of the CURRENT signal returned by "f"
308
+ *
309
+ * const second = unwrapSignal(f); // The value of "second" is reactive and CAN be destructured
310
+ * const [ getSecond ] = second; // The value of "getSecond" IS reactive, it's a function that calls "f", gets the first element and calls that too
311
+ * ```
312
+ * @param f An {@link Accessor} to a {@link Signal}
313
+ */
314
+ export declare function unwrapSignal<T>(f: Accessor<Signal<T>>): Signal<T>;
277
315
 
278
316
  /** Like a {@link Match} but gets the value from the closest {@link Case} ancestor */
279
317
  export declare function When(props: {
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { useContext, createMemo, createComponent, createContext, createRoot, getOwner, Match, mergeProps, onCleanup, For, Show, untrack, splitProps, createEffect, on, createResource, mapArray, createSignal, onMount, createRenderEffect } from "solid-js";
1
+ import { useContext, createMemo, createComponent, createContext, createRoot, getOwner, Match, mergeProps, splitProps, createEffect, on, createResource, untrack, Show, onCleanup, For, mapArray, createSignal, onMount, createRenderEffect } from "solid-js";
2
2
  import { createMutable } from "solid-js/store";
3
3
  const BASE_CTOR = Function;
4
4
  class ReactiveContext extends BASE_CTOR {
@@ -78,6 +78,58 @@ function When(props) {
78
78
  }
79
79
  }, other));
80
80
  }
81
+ function memoProps(obj, keys = Object.keys(obj), equals = false) {
82
+ const out = {};
83
+ for (const elm of keys)
84
+ Object.defineProperty(out, elm, {
85
+ enumerable: true,
86
+ get: createMemo(() => obj[elm], void 0, {
87
+ equals
88
+ })
89
+ });
90
+ return out;
91
+ }
92
+ function splitAndMemoProps(obj, keys, equals) {
93
+ const out = splitProps(obj, keys);
94
+ out[0] = memoProps(out[0], keys, equals);
95
+ return out;
96
+ }
97
+ function createReactiveResource(f) {
98
+ var refetch;
99
+ const memo = createMemo(f);
100
+ createEffect(on(memo, () => refetch?.()));
101
+ const [get] = [, {
102
+ refetch
103
+ }] = createResource(memo);
104
+ return get;
105
+ }
106
+ function untrackCall(f, ...args) {
107
+ return untrack(() => f.apply(this, args));
108
+ }
109
+ const unwrap = (f) => new Proxy(f, HANDLER);
110
+ const HANDLER = new Proxy({}, {
111
+ get(cache, k) {
112
+ return cache[k] ??= (t, ...args) => {
113
+ return Reflect[k](t(), ...args);
114
+ };
115
+ }
116
+ });
117
+ function Enfold(props) {
118
+ const f = () => props.children;
119
+ const children = unwrap(createMemo(() => props.unrecycled ? f : createMemo(f)));
120
+ return createComponent(Show, {
121
+ get keyed() {
122
+ return props.keyed;
123
+ },
124
+ get when() {
125
+ return props.when;
126
+ },
127
+ get fallback() {
128
+ return children();
129
+ },
130
+ children: (x) => createMemo(() => untrackCall(props.template, children, x))
131
+ });
132
+ }
81
133
  function createExtractor(name = "extractor") {
82
134
  const ctx2 = createContext(void 0, {
83
135
  name
@@ -151,47 +203,11 @@ function Joint(props) {
151
203
  }
152
204
  });
153
205
  }
154
- function untrackCall(f, ...args) {
155
- return untrack(() => f.apply(this, args));
156
- }
157
- function refCall(ref, value) {
158
- if (!ref)
159
- return value;
160
- if (typeof ref !== "function")
161
- throw new ReferenceError('Il parametro "ref" deve essere stato compilato in una funzione a runtime');
162
- ref(value);
163
- return value;
164
- }
165
- function memoProps(obj, keys = Object.keys(obj), equals = false) {
166
- const out = {};
167
- for (const elm of keys)
168
- Object.defineProperty(out, elm, {
169
- enumerable: true,
170
- get: createMemo(() => obj[elm], void 0, {
171
- equals
172
- })
173
- });
174
- return out;
175
- }
176
- function splitAndMemoProps(obj, keys, equals) {
177
- const out = splitProps(obj, keys);
178
- out[0] = memoProps(out[0], keys, equals);
179
- return out;
180
- }
181
- function createReactiveResource(f) {
182
- var refetch;
183
- const memo = createMemo(f);
184
- createEffect(on(memo, () => refetch?.()));
185
- const [get] = [, {
186
- refetch
187
- }] = createResource(memo);
188
- return get;
189
- }
190
206
  function Nest(props) {
191
207
  const memo = memoProps(props, ["template", "children"]);
192
208
  const content = mapArray(() => props.each, (x, i) => {
193
209
  const [get, set] = createSignal();
194
- const out = memo.template(x, get, i);
210
+ const out = createMemo(() => untrackCall(memo.template, get, x, i));
195
211
  return (x2) => {
196
212
  onMount(() => set(() => x2));
197
213
  onCleanup(() => set(void 0));
@@ -223,17 +239,13 @@ function toSignal(obj, k) {
223
239
  function coalesceSignal([get, set], f) {
224
240
  return [() => get() ?? set(f), set];
225
241
  }
226
- const unwrap = (f) => new Proxy(f, HANDLER);
227
- const HANDLER = new Proxy({}, {
228
- get(cache, k) {
229
- return cache[k] ??= (t, ...args) => {
230
- return Reflect[k](t(), ...args);
231
- };
232
- }
233
- });
242
+ function unwrapSignal(f) {
243
+ return [() => f()[0](), (x) => f()[1](x)];
244
+ }
234
245
  const debug = ReactiveContext.create(false, "debug-scope");
235
246
  export {
236
247
  Case,
248
+ Enfold,
237
249
  Nest,
238
250
  ReactiveContext,
239
251
  When,
@@ -244,11 +256,11 @@ export {
244
256
  createReactiveResource,
245
257
  debug,
246
258
  memoProps,
247
- refCall,
248
259
  runWithContext,
249
260
  splitAndMemoProps,
250
261
  toSetter,
251
262
  toSignal,
252
263
  untrackCall,
253
- unwrap
264
+ unwrap,
265
+ unwrapSignal
254
266
  };
package/dist/index.umd.js CHANGED
@@ -80,6 +80,58 @@
80
80
  }
81
81
  }, other));
82
82
  }
83
+ function memoProps(obj, keys = Object.keys(obj), equals = false) {
84
+ const out = {};
85
+ for (const elm of keys)
86
+ Object.defineProperty(out, elm, {
87
+ enumerable: true,
88
+ get: solidJs.createMemo(() => obj[elm], void 0, {
89
+ equals
90
+ })
91
+ });
92
+ return out;
93
+ }
94
+ function splitAndMemoProps(obj, keys, equals) {
95
+ const out = solidJs.splitProps(obj, keys);
96
+ out[0] = memoProps(out[0], keys, equals);
97
+ return out;
98
+ }
99
+ function createReactiveResource(f) {
100
+ var refetch;
101
+ const memo = solidJs.createMemo(f);
102
+ solidJs.createEffect(solidJs.on(memo, () => refetch?.()));
103
+ const [get] = [, {
104
+ refetch
105
+ }] = solidJs.createResource(memo);
106
+ return get;
107
+ }
108
+ function untrackCall(f, ...args) {
109
+ return solidJs.untrack(() => f.apply(this, args));
110
+ }
111
+ const unwrap = (f) => new Proxy(f, HANDLER);
112
+ const HANDLER = new Proxy({}, {
113
+ get(cache, k) {
114
+ return cache[k] ??= (t, ...args) => {
115
+ return Reflect[k](t(), ...args);
116
+ };
117
+ }
118
+ });
119
+ function Enfold(props) {
120
+ const f = () => props.children;
121
+ const children = unwrap(solidJs.createMemo(() => props.unrecycled ? f : solidJs.createMemo(f)));
122
+ return solidJs.createComponent(solidJs.Show, {
123
+ get keyed() {
124
+ return props.keyed;
125
+ },
126
+ get when() {
127
+ return props.when;
128
+ },
129
+ get fallback() {
130
+ return children();
131
+ },
132
+ children: (x) => solidJs.createMemo(() => untrackCall(props.template, children, x))
133
+ });
134
+ }
83
135
  function createExtractor(name = "extractor") {
84
136
  const ctx2 = solidJs.createContext(void 0, {
85
137
  name
@@ -153,47 +205,11 @@
153
205
  }
154
206
  });
155
207
  }
156
- function untrackCall(f, ...args) {
157
- return solidJs.untrack(() => f.apply(this, args));
158
- }
159
- function refCall(ref, value) {
160
- if (!ref)
161
- return value;
162
- if (typeof ref !== "function")
163
- throw new ReferenceError('Il parametro "ref" deve essere stato compilato in una funzione a runtime');
164
- ref(value);
165
- return value;
166
- }
167
- function memoProps(obj, keys = Object.keys(obj), equals = false) {
168
- const out = {};
169
- for (const elm of keys)
170
- Object.defineProperty(out, elm, {
171
- enumerable: true,
172
- get: solidJs.createMemo(() => obj[elm], void 0, {
173
- equals
174
- })
175
- });
176
- return out;
177
- }
178
- function splitAndMemoProps(obj, keys, equals) {
179
- const out = solidJs.splitProps(obj, keys);
180
- out[0] = memoProps(out[0], keys, equals);
181
- return out;
182
- }
183
- function createReactiveResource(f) {
184
- var refetch;
185
- const memo = solidJs.createMemo(f);
186
- solidJs.createEffect(solidJs.on(memo, () => refetch?.()));
187
- const [get] = [, {
188
- refetch
189
- }] = solidJs.createResource(memo);
190
- return get;
191
- }
192
208
  function Nest(props) {
193
209
  const memo = memoProps(props, ["template", "children"]);
194
210
  const content = solidJs.mapArray(() => props.each, (x, i) => {
195
211
  const [get, set] = solidJs.createSignal();
196
- const out = memo.template(x, get, i);
212
+ const out = solidJs.createMemo(() => untrackCall(memo.template, get, x, i));
197
213
  return (x2) => {
198
214
  solidJs.onMount(() => set(() => x2));
199
215
  solidJs.onCleanup(() => set(void 0));
@@ -225,16 +241,12 @@
225
241
  function coalesceSignal([get, set], f) {
226
242
  return [() => get() ?? set(f), set];
227
243
  }
228
- const unwrap = (f) => new Proxy(f, HANDLER);
229
- const HANDLER = new Proxy({}, {
230
- get(cache, k) {
231
- return cache[k] ??= (t, ...args) => {
232
- return Reflect[k](t(), ...args);
233
- };
234
- }
235
- });
244
+ function unwrapSignal(f) {
245
+ return [() => f()[0](), (x) => f()[1](x)];
246
+ }
236
247
  const debug = ReactiveContext.create(false, "debug-scope");
237
248
  exports2.Case = Case;
249
+ exports2.Enfold = Enfold;
238
250
  exports2.Nest = Nest;
239
251
  exports2.ReactiveContext = ReactiveContext;
240
252
  exports2.When = When;
@@ -245,12 +257,12 @@
245
257
  exports2.createReactiveResource = createReactiveResource;
246
258
  exports2.debug = debug;
247
259
  exports2.memoProps = memoProps;
248
- exports2.refCall = refCall;
249
260
  exports2.runWithContext = runWithContext;
250
261
  exports2.splitAndMemoProps = splitAndMemoProps;
251
262
  exports2.toSetter = toSetter;
252
263
  exports2.toSignal = toSignal;
253
264
  exports2.untrackCall = untrackCall;
254
265
  exports2.unwrap = unwrap;
266
+ exports2.unwrapSignal = unwrapSignal;
255
267
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
256
268
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solid-ctrl-flow",
3
- "version": "1.0.39",
3
+ "version": "1.0.40",
4
4
  "description": "Control flow components for solid-js",
5
5
  "author": "AFatNiBBa",
6
6
  "license": "ISC",
package/readMe.md CHANGED
@@ -34,12 +34,44 @@ return <>
34
34
  </>
35
35
  ```
36
36
 
37
+ ### `Enfold`
38
+ Eventually wraps its content into a template if a certain condition is met.
39
+ The following code
40
+ ```tsx
41
+ const value = true;
42
+ return <>
43
+ <Enfold when={value} template={c => <div style={{ background: "red" }}>{c()}</div>}>
44
+ content
45
+ </Enfold>
46
+ </>
47
+ ```
48
+ Is equivalent to this
49
+ ```tsx
50
+ return <>
51
+ <div style={{ background: "red" }}>
52
+ content
53
+ </div>
54
+ </>
55
+ ```
56
+ And if `value` was falsish, it would have been equivalent to this
57
+ ```tsx
58
+ return <>content</>
59
+ ```
60
+ If you are wrapping the content with a context provider you need to set the `unrecycled` attribute to `true` to run again the whole content, otherwise the `Owner` of the content won't be child of the template one
61
+ ```tsx
62
+ return <>
63
+ <Enfold unrecycled when={value} template={c => <ctx.Provider value={2} children={c()} />}>
64
+ {useContext(ctx)}
65
+ </Enfold>
66
+ </>
67
+ ```
68
+
37
69
  ### `Nest`
38
70
  Like a `For`, but instead of putting an element after another it nests them.
39
71
  The following code
40
72
  ```tsx
41
73
  return <>
42
- <Nest each={[ "red", "green", "blue" ]} template={(x, y) => <div style={{ background: x, padding: "1ch" }}>{y()}</div>}>
74
+ <Nest each={[ "red", "green", "blue" ]} template={(c, x) => <div style={{ background: x, padding: "1ch" }}>{c()}</div>}>
43
75
  content
44
76
  </Nest>
45
77
  </>
@@ -150,6 +182,9 @@ Functions that create bindings between `Signal`s
150
182
  >
151
183
  > #### `coalesceSignal()`
152
184
  > Creates a non nullable `Signal` from a nullable one
185
+ >
186
+ > #### `unwrapSignal()`
187
+ > A `Signal`-specific version of `unwrap()` that allows the destructuring of its result
153
188
 
154
189
  ### `ReactiveContext.create()`
155
190
  Method that creates a reactive version of a solid `Context` with some additional built-in functionalities
@@ -164,7 +199,7 @@ const value = ctx();
164
199
  Creates a context scope that persists for the duration of a function
165
200
 
166
201
  ### `unwrap()`
167
- Calls an `Accessor` maintaining its reactivity
202
+ Calls an `Accessor` maintaining its reactivity at 1 level
168
203
 
169
204
  ### `debug()`
170
205
  Allows you to define ui section that are only visible in debug or NOT in debug
@@ -180,12 +215,6 @@ return <>
180
215
  </>
181
216
  ```
182
217
 
183
- ### `untrackCall()`
184
- Calls a function untracking what happens inside of it but not what gets passed as its argument
185
-
186
- ### `refCall()`
187
- Executes a `Ref`
188
-
189
218
  ### `memoProps()`
190
219
  Creates a partial version of an object with memoized remaining properties
191
220
 
@@ -193,4 +222,7 @@ Creates a partial version of an object with memoized remaining properties
193
222
  Like `splitProps()` but memoizes the whole local part
194
223
 
195
224
  ### `createReactiveResource()`
196
- Like `createResource()` but the provided function will be reactive
225
+ Like `createResource()` but the provided function will be reactive
226
+
227
+ ### `untrackCall()`
228
+ Calls a function untracking what happens inside of it but not what gets passed as its argument