solid-ctrl-flow 2.2.4 → 3.0.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/dist/index.d.ts CHANGED
@@ -57,11 +57,23 @@ export declare class Extractor {
57
57
  Joint: (props: {
58
58
  children?: JSX.Element;
59
59
  }) => JSX.Element;
60
- Fallback: () => JSX.Element;
61
60
  Dest: (props: {
62
- hidden?: boolean | undefined;
61
+ children?: JSX.Element;
62
+ }) => JSX.Element;
63
+ Source: (props: {
64
+ order?: number | undefined;
65
+ } & {
66
+ children?: JSX.Element;
67
+ } & {
68
+ fallback?: JSX.Element;
69
+ }) => JSX.Element;
70
+ SameContextSource: (props: {
71
+ order?: number | undefined;
72
+ } & {
73
+ children?: JSX.Element;
74
+ } & {
75
+ fallback?: JSX.Element;
63
76
  }) => JSX.Element;
64
- Source: (props: Info) => JSX.Element;
65
77
  /**
66
78
  * Returns the number of destinations available for the current {@link Extractor}.
67
79
  * It's a getter that returns a function that will be bound to the {@link Owner} in which the getter was called.
@@ -134,7 +146,8 @@ export declare class OrderedLinkedList<T> {
134
146
  /** Yields all the elements PAST the current */
135
147
  [Symbol.iterator](): Generator<T>;
136
148
  /**
137
- * Adds a node to the list in order
149
+ * Adds a node to the list in order.
150
+ * If two nodes have the same order, it would have been more efficient to put the latest one first, but this would not have been ok, since we also want to order by insertion time
138
151
  * @param node The node to add
139
152
  * @param comp The comparison function to use
140
153
  * @returns The same value as {@link node}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { createMemo, splitProps, untrack, createRoot, getOwner, createComponent, Show, createContext, useContext, createRenderEffect, on, onCleanup, For, createSignal, createSelector, equalFn, Match } from "solid-js";
1
+ import { createMemo, splitProps, untrack, createRoot, getOwner, createComponent, Show, createContext, useContext, onCleanup, For, createRenderEffect, on, mergeProps, createSignal, createSelector, equalFn, Match } from "solid-js";
2
2
  const NO_OP = () => {
3
3
  };
4
4
  function memoProps(obj, keys = Reflect.ownKeys(obj), equals = false) {
@@ -61,14 +61,15 @@ class OrderedLinkedList {
61
61
  yield* next;
62
62
  }
63
63
  /**
64
- * Adds a node to the list in order
65
- * @param node The node to add
66
- * @param comp The comparison function to use
67
- * @returns The same value as {@link node}
68
- */
64
+ * Adds a node to the list in order.
65
+ * If two nodes have the same order, it would have been more efficient to put the latest one first, but this would not have been ok, since we also want to order by insertion time
66
+ * @param node The node to add
67
+ * @param comp The comparison function to use
68
+ * @returns The same value as {@link node}
69
+ */
69
70
  add(node, comp) {
70
71
  const { next } = this;
71
- if (next && comp(node.value, next.value) > 0)
72
+ if (next && comp(node.value, next.value) >= 0)
72
73
  return next.add(node, comp);
73
74
  this.next = node;
74
75
  node.prev = this;
@@ -123,9 +124,9 @@ class Extractor {
123
124
  });
124
125
  }
125
126
  Joint = Joint.bind(this);
126
- Fallback = Fallback.bind(this);
127
127
  Dest = Dest.bind(this);
128
128
  Source = Source.bind(this);
129
+ SameContextSource = SameContextSource.bind(this);
129
130
  /**
130
131
  * Returns the number of destinations available for the current {@link Extractor}.
131
132
  * It's a getter that returns a function that will be bound to the {@link Owner} in which the getter was called.
@@ -145,41 +146,26 @@ function Joint(props) {
145
146
  }
146
147
  });
147
148
  }
148
- function Fallback() {
149
- const _self$ = this;
150
- const f = this.getDestCount;
151
- return createComponent(Show, {
152
- get when() {
153
- return !f?.();
154
- },
155
- get children() {
156
- return createComponent(_self$.Dest, {
157
- hidden: true
158
- });
159
- }
160
- });
161
- }
162
149
  function Dest(props) {
163
150
  const state = useContext(this.ctx);
164
151
  if (!state)
165
- throw new Error("An extractor's destination must be inside one of its joints");
166
- createRenderEffect(on(createMemo(() => props.hidden), (x) => {
167
- if (x)
168
- return;
169
- onCleanup(() => state.shift(-1));
170
- state.shift(1);
171
- }));
152
+ return createMemo(() => props.children);
153
+ onCleanup(() => state.shift(-1));
154
+ state.shift(1);
172
155
  return createComponent(For, {
173
156
  get each() {
174
157
  return [...state.sources];
175
158
  },
159
+ get fallback() {
160
+ return props.children;
161
+ },
176
162
  children: (x) => createMemo(() => x.children)
177
163
  });
178
164
  }
179
165
  function Source(props) {
180
166
  const state = useContext(this.ctx);
181
167
  if (!state)
182
- throw new Error("An extractor's source must be inside one of its joints");
168
+ return createMemo(() => props.fallback);
183
169
  const {
184
170
  sources
185
171
  } = state;
@@ -194,11 +180,36 @@ function Source(props) {
194
180
  };
195
181
  const node = new OrderedLinkedListNode(info);
196
182
  createRenderEffect(on(order, () => {
197
- onCleanup(() => node.remove());
183
+ onCleanup(() => {
184
+ node.remove();
185
+ state.force();
186
+ });
198
187
  sources.add(node, COMPARATOR);
199
188
  state.force();
200
189
  }));
201
- return [];
190
+ return createComponent(Show, {
191
+ get when() {
192
+ return !state.destCount;
193
+ },
194
+ get children() {
195
+ return props.fallback;
196
+ }
197
+ });
198
+ }
199
+ function SameContextSource(props) {
200
+ const _self$ = this;
201
+ const [mine, other] = splitProps(props, ["children"]);
202
+ const owner = getOwner();
203
+ return createComponent(_self$.Source, mergeProps(other, {
204
+ get children() {
205
+ return createComponent(SameContext, {
206
+ owner,
207
+ get children() {
208
+ return mine.children;
209
+ }
210
+ });
211
+ }
212
+ }));
202
213
  }
203
214
  const ctx = createContext(void 0, {
204
215
  name: "on-case"
package/dist/index.umd.js CHANGED
@@ -64,14 +64,15 @@
64
64
  yield* next;
65
65
  }
66
66
  /**
67
- * Adds a node to the list in order
68
- * @param node The node to add
69
- * @param comp The comparison function to use
70
- * @returns The same value as {@link node}
71
- */
67
+ * Adds a node to the list in order.
68
+ * If two nodes have the same order, it would have been more efficient to put the latest one first, but this would not have been ok, since we also want to order by insertion time
69
+ * @param node The node to add
70
+ * @param comp The comparison function to use
71
+ * @returns The same value as {@link node}
72
+ */
72
73
  add(node, comp) {
73
74
  const { next } = this;
74
- if (next && comp(node.value, next.value) > 0)
75
+ if (next && comp(node.value, next.value) >= 0)
75
76
  return next.add(node, comp);
76
77
  this.next = node;
77
78
  node.prev = this;
@@ -126,9 +127,9 @@
126
127
  });
127
128
  }
128
129
  Joint = Joint.bind(this);
129
- Fallback = Fallback.bind(this);
130
130
  Dest = Dest.bind(this);
131
131
  Source = Source.bind(this);
132
+ SameContextSource = SameContextSource.bind(this);
132
133
  /**
133
134
  * Returns the number of destinations available for the current {@link Extractor}.
134
135
  * It's a getter that returns a function that will be bound to the {@link Owner} in which the getter was called.
@@ -148,41 +149,26 @@
148
149
  }
149
150
  });
150
151
  }
151
- function Fallback() {
152
- const _self$ = this;
153
- const f = this.getDestCount;
154
- return solidJs.createComponent(solidJs.Show, {
155
- get when() {
156
- return !f?.();
157
- },
158
- get children() {
159
- return solidJs.createComponent(_self$.Dest, {
160
- hidden: true
161
- });
162
- }
163
- });
164
- }
165
152
  function Dest(props) {
166
153
  const state = solidJs.useContext(this.ctx);
167
154
  if (!state)
168
- throw new Error("An extractor's destination must be inside one of its joints");
169
- solidJs.createRenderEffect(solidJs.on(solidJs.createMemo(() => props.hidden), (x) => {
170
- if (x)
171
- return;
172
- solidJs.onCleanup(() => state.shift(-1));
173
- state.shift(1);
174
- }));
155
+ return solidJs.createMemo(() => props.children);
156
+ solidJs.onCleanup(() => state.shift(-1));
157
+ state.shift(1);
175
158
  return solidJs.createComponent(solidJs.For, {
176
159
  get each() {
177
160
  return [...state.sources];
178
161
  },
162
+ get fallback() {
163
+ return props.children;
164
+ },
179
165
  children: (x) => solidJs.createMemo(() => x.children)
180
166
  });
181
167
  }
182
168
  function Source(props) {
183
169
  const state = solidJs.useContext(this.ctx);
184
170
  if (!state)
185
- throw new Error("An extractor's source must be inside one of its joints");
171
+ return solidJs.createMemo(() => props.fallback);
186
172
  const {
187
173
  sources
188
174
  } = state;
@@ -197,11 +183,36 @@
197
183
  };
198
184
  const node = new OrderedLinkedListNode(info);
199
185
  solidJs.createRenderEffect(solidJs.on(order, () => {
200
- solidJs.onCleanup(() => node.remove());
186
+ solidJs.onCleanup(() => {
187
+ node.remove();
188
+ state.force();
189
+ });
201
190
  sources.add(node, COMPARATOR);
202
191
  state.force();
203
192
  }));
204
- return [];
193
+ return solidJs.createComponent(solidJs.Show, {
194
+ get when() {
195
+ return !state.destCount;
196
+ },
197
+ get children() {
198
+ return props.fallback;
199
+ }
200
+ });
201
+ }
202
+ function SameContextSource(props) {
203
+ const _self$ = this;
204
+ const [mine, other] = solidJs.splitProps(props, ["children"]);
205
+ const owner = solidJs.getOwner();
206
+ return solidJs.createComponent(_self$.Source, solidJs.mergeProps(other, {
207
+ get children() {
208
+ return solidJs.createComponent(SameContext, {
209
+ owner,
210
+ get children() {
211
+ return mine.children;
212
+ }
213
+ });
214
+ }
215
+ }));
205
216
  }
206
217
  const ctx = solidJs.createContext(void 0, {
207
218
  name: "on-case"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solid-ctrl-flow",
3
- "version": "2.2.4",
3
+ "version": "3.0.0",
4
4
  "description": "Control flow components for solid-js",
5
5
  "author": "AFatNiBBa",
6
6
  "license": "ISC",
package/readMe.md CHANGED
@@ -94,7 +94,9 @@ return <>
94
94
  </e.Joint>
95
95
  </>
96
96
  ```
97
- Both `Extractor.Source` and `Extractor.Dest` will throw if they're not inside a `Extractor.Joint`.
97
+ If a `Extractor.Dest` has no `Extractor.Source` to render (Or it isn't inside a `Extractor.Joint`), it will render whatever you pass inside the `children` attribute
98
+ <br />
99
+ If a `Extractor.Source` has no available `Extractor.Dest` (Or it isn't inside a `Extractor.Joint`), it will render whatever you pass inside the `fallback` attribute
98
100
  <br />
99
101
  Componets from different `Extractor`s don't "talk" to each other and there can be more than one source and destinations:
100
102
  ```tsx
@@ -117,7 +119,7 @@ return <>
117
119
  <a.Dest />
118
120
  <b.Joint>
119
121
  {/* No source */}
120
- <b.Dest />
122
+ <b.Dest>fb1</b.Dest>
121
123
  <c.Joint>
122
124
  3
123
125
  {/* Double destination */}
@@ -126,7 +128,7 @@ return <>
126
128
  <a.Source>
127
129
  5
128
130
  </a.Source>
129
- <c.Source>
131
+ <c.Source fallback="fb2">
130
132
  {/* No destination */}
131
133
  6
132
134
  </c.Source>
@@ -145,7 +147,7 @@ return <>
145
147
  </a.Joint>
146
148
  </>
147
149
  ```
148
- The output of this code is ***1***, ***5***, 3, ***1***, ***5***, 4, 0, 2, ***8***, 7, ***8***.
150
+ The output of this code is ***1***, ***5***, ~~fb1~~, 3, ***1***, ***5***, 4, ~~fb2~~, 0, 2, ***8***, 7, ***8***.
149
151
  <br />
150
152
  You can detect the number of destinations available for a given extractor through `Extractor.getDestCount()`
151
153
  ```tsx
@@ -196,26 +198,26 @@ return <>
196
198
  </e.Joint>
197
199
  </>
198
200
  ```
199
- You can NOT do this to create a fallback destination for when there aren't any other
200
- ```tsx
201
- return <>
202
- <Show when={!someExtractor.getDestCount!()}>
203
- <someExtractor.Dest />
204
- </Show>
205
- </>
206
- ```
207
- Because it would start a strange loop due to which the new destination would disable itself. To do that you must use the `hidden` attribute, which will made sure that the destination is not considered by `Extractor.getDestCount()` at all
208
- ```tsx
209
- return <>
210
- <Show when={!someExtractor.getDestCount!()}>
211
- <someExtractor.Dest hidden />
212
- </Show>
213
- </>
214
- ```
215
- Due to this pattern being fairly common, there's the `Extractor.Fallback` component that does that exact thing
201
+ You can use `Extractor.SameContextSource` to automate the process of using a `SameContext` inside a `Extractor.Source`. When in doubt, use `Extractor.SameContextSource` instead of `Extractor.Source`
216
202
  ```tsx
203
+ const e = new Extractor(), ctx = createContext(1);
217
204
  return <>
218
- <someExtractor.Fallback />
205
+ <e.Joint>
206
+ <div>
207
+ {/* This will contain "1" and "3" */}
208
+ <e.Dest />
209
+ </div>
210
+ <ctx.Provider value={2}>
211
+ <div>
212
+ {/* This will contain "2" and "3" */}
213
+ <e.Dest />
214
+ </div>
215
+ <ctx.Provider value={3}>
216
+ <e.Source>{useContext(ctx)}</e.Source>
217
+ <e.SameContextSource>{useContext(ctx)}</e.SameContextSource>
218
+ </ctx.Provider>
219
+ </ctx.Provider>
220
+ </e.Joint>
219
221
  </>
220
222
  ```
221
223