solid-ctrl-flow 1.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/flow.d.ts +128 -0
- package/dist/flow.mjs +120 -0
- package/dist/flow.umd.js +122 -0
- package/package.json +39 -0
- package/readme.md +123 -0
package/dist/flow.d.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Accessor } from 'solid-js';
|
|
2
|
+
import { JSX } from 'solid-js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Allows the use of {@link When}s inside of {@link Switch}es.
|
|
6
|
+
* Example:
|
|
7
|
+
* ```tsx
|
|
8
|
+
* return <>
|
|
9
|
+
* <Switch>
|
|
10
|
+
* <Match when={SOMETHING}>
|
|
11
|
+
* RANDOM_CONDITION
|
|
12
|
+
* </Match>
|
|
13
|
+
* <Case value={1}>
|
|
14
|
+
* <When value={1}>
|
|
15
|
+
* TRUE
|
|
16
|
+
* </When>
|
|
17
|
+
* <When pred={x => x === 2}>
|
|
18
|
+
* FALSE_WITH_PREDICATE
|
|
19
|
+
* </When>
|
|
20
|
+
* <When pred={x => x.innerValue}>
|
|
21
|
+
* {x => <>THRUTHY VALUE {x()}</>}
|
|
22
|
+
* </When>
|
|
23
|
+
* <When keyed pred={x => x.innerValue}>
|
|
24
|
+
* {x => <>THRUTHY KEYED VALUE {x}</>}
|
|
25
|
+
* </When>
|
|
26
|
+
* </Case>
|
|
27
|
+
* <Match when>
|
|
28
|
+
* DEFAULT
|
|
29
|
+
* </Match>
|
|
30
|
+
* </Switch>
|
|
31
|
+
* <>
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function Case(props: {
|
|
35
|
+
value: any;
|
|
36
|
+
children: JSX.Element;
|
|
37
|
+
}): JSX.Element;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Creates a slot that allows you to show a component outside of its parent.
|
|
41
|
+
* It works with arbitrary nesting.
|
|
42
|
+
* Example:
|
|
43
|
+
* ```tsx
|
|
44
|
+
* const e = createExtractor();
|
|
45
|
+
* return <>
|
|
46
|
+
* <e.Joint>
|
|
47
|
+
* <div id="something">
|
|
48
|
+
* <e.Dest />
|
|
49
|
+
* </div>
|
|
50
|
+
* <div id="something-else">
|
|
51
|
+
* <e.Source>
|
|
52
|
+
* This text will be shown instead of "e.Dest".
|
|
53
|
+
* If there weren't to be any "e.Joint" ancestor, then this text would have stayed here
|
|
54
|
+
* </e.Source>
|
|
55
|
+
* </div>
|
|
56
|
+
* </e.Joint>
|
|
57
|
+
* <>
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function createExtractor(name?: string): {
|
|
61
|
+
/** Bound {@link Dest} */
|
|
62
|
+
Dest: () => JSX.Element;
|
|
63
|
+
/** Bound {@link Source} */
|
|
64
|
+
Source: (props: {
|
|
65
|
+
children: JSX.Element;
|
|
66
|
+
}) => JSX.Element;
|
|
67
|
+
/** Bound {@link Joint} */
|
|
68
|
+
Joint: (props: {
|
|
69
|
+
children: JSX.Element;
|
|
70
|
+
}) => JSX.Element;
|
|
71
|
+
/**
|
|
72
|
+
* Gets an {@link Accessor} that tells if the context in which THIS getter has been executed has been extracted (Is inside of a {@link Dest})
|
|
73
|
+
* @returns Returns `null` if there is no parent {@link Joint}, `false` if there is a {@link Joint} but not a {@link Dest} and `true` otherwise
|
|
74
|
+
*/
|
|
75
|
+
readonly isExtracted: () => boolean | null;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/** Sets the value that will be returned by {@link Debug.isDebug} for the children of the current component */
|
|
79
|
+
export declare function Debug(props: {
|
|
80
|
+
value?: boolean;
|
|
81
|
+
children: JSX.Element;
|
|
82
|
+
}): JSX.Element;
|
|
83
|
+
|
|
84
|
+
/** Utility functions for the debug scopes */
|
|
85
|
+
export declare namespace Debug {
|
|
86
|
+
/** Gets an {@link Accessor} that tells if the context in which THIS getter has been executed is in debug mode */
|
|
87
|
+
const isDebug: Accessor<boolean>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Memoizes some of the properties of {@link obj}
|
|
92
|
+
* If {@link keys} is not provided, memoizes everything that get returned by {@link Object.keys} when provided with {@link obj}
|
|
93
|
+
* @param obj Object to partially memoize
|
|
94
|
+
* @param keys The keys of the properties to memoize
|
|
95
|
+
*/
|
|
96
|
+
export declare function memoProps<T, K extends readonly (keyof T)[] = (keyof T)[]>(obj: T, keys?: K): Pick<T, K[number]>;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Esecutes {@link splitProps} and memoizes the first of the two returned objects
|
|
100
|
+
* @param obj Object to split and partially memoize
|
|
101
|
+
* @param keys The keys of the properties to memoize and to include in the first of the two objects
|
|
102
|
+
*/
|
|
103
|
+
export declare function splitAndMemoProps<T extends object, K extends readonly (keyof T)[]>(obj: T, keys: K): readonly [Pick<Pick<T, Extract<K, readonly (keyof T)[]>[number]>, K[number]>, Omit<T, K[number]>];
|
|
104
|
+
|
|
105
|
+
/** Like a {@link Match} but gets the value from the closest {@link Case} ancestor */
|
|
106
|
+
export declare function When(props: {
|
|
107
|
+
value: unknown;
|
|
108
|
+
children: JSX.Element;
|
|
109
|
+
}): JSX.Element;
|
|
110
|
+
|
|
111
|
+
export declare function When(props: {
|
|
112
|
+
pred: (x: any) => unknown;
|
|
113
|
+
children: JSX.Element;
|
|
114
|
+
}): JSX.Element;
|
|
115
|
+
|
|
116
|
+
export declare function When<T>(props: {
|
|
117
|
+
pred: (x: any) => T;
|
|
118
|
+
keyed?: false;
|
|
119
|
+
children: (x: Accessor<NonNullable<T>>) => JSX.Element;
|
|
120
|
+
}): JSX.Element;
|
|
121
|
+
|
|
122
|
+
export declare function When<T>(props: {
|
|
123
|
+
pred: (x: any) => T;
|
|
124
|
+
keyed: true;
|
|
125
|
+
children: (x: NonNullable<T>) => JSX.Element;
|
|
126
|
+
}): JSX.Element;
|
|
127
|
+
|
|
128
|
+
export { }
|
package/dist/flow.mjs
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { createContext, createMemo, createComponent, useContext, Match, mergeProps, onCleanup, children, Show, splitProps } from "solid-js";
|
|
2
|
+
import { createMutable } from "solid-js/store";
|
|
3
|
+
const ctx$1 = createContext(() => void 0, {
|
|
4
|
+
name: "case-when"
|
|
5
|
+
});
|
|
6
|
+
function Case(props) {
|
|
7
|
+
const memo = createMemo(() => props.value);
|
|
8
|
+
return createComponent(ctx$1.Provider, {
|
|
9
|
+
value: memo,
|
|
10
|
+
get children() {
|
|
11
|
+
return props.children;
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function When(props) {
|
|
16
|
+
const [mine, other] = splitAndMemoProps(props, ["value", "pred"]);
|
|
17
|
+
const value = useContext(ctx$1);
|
|
18
|
+
const pred = (x) => mine.pred ? mine.pred(x) : x === mine.value;
|
|
19
|
+
return createComponent(Match, mergeProps({
|
|
20
|
+
get when() {
|
|
21
|
+
return pred(value());
|
|
22
|
+
}
|
|
23
|
+
}, other));
|
|
24
|
+
}
|
|
25
|
+
const ctx = createContext(() => false, {
|
|
26
|
+
name: "debug-scope"
|
|
27
|
+
});
|
|
28
|
+
function Debug(props) {
|
|
29
|
+
return createComponent(ctx.Provider, {
|
|
30
|
+
value: () => props.value ?? true,
|
|
31
|
+
get children() {
|
|
32
|
+
return props.children;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
(function(_Debug) {
|
|
37
|
+
Object.defineProperty(Debug, "isDebug", {
|
|
38
|
+
get: () => useContext(ctx)
|
|
39
|
+
});
|
|
40
|
+
})(Debug || (Debug = {}));
|
|
41
|
+
function createExtractor(name = "extractor") {
|
|
42
|
+
const ctx2 = createContext(void 0, {
|
|
43
|
+
name
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
/** Bound {@link Dest} */
|
|
47
|
+
Dest: Dest.bind(ctx2),
|
|
48
|
+
/** Bound {@link Source} */
|
|
49
|
+
Source: Source.bind(ctx2),
|
|
50
|
+
/** Bound {@link Joint} */
|
|
51
|
+
Joint: Joint.bind(ctx2),
|
|
52
|
+
/**
|
|
53
|
+
* Gets an {@link Accessor} that tells if the context in which THIS getter has been executed has been extracted (Is inside of a {@link Dest})
|
|
54
|
+
* @returns Returns `null` if there is no parent {@link Joint}, `false` if there is a {@link Joint} but not a {@link Dest} and `true` otherwise
|
|
55
|
+
*/
|
|
56
|
+
get isExtracted() {
|
|
57
|
+
const obj = useContext(ctx2);
|
|
58
|
+
return () => obj?.attached ?? null;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function Dest() {
|
|
63
|
+
const obj = useContext(this);
|
|
64
|
+
if (!obj)
|
|
65
|
+
return;
|
|
66
|
+
if (obj.attached)
|
|
67
|
+
throw new Error("Un extractor non può avere più di una destinazione");
|
|
68
|
+
obj.attached = true;
|
|
69
|
+
onCleanup(() => obj.attached = false);
|
|
70
|
+
return createMemo(() => obj.source);
|
|
71
|
+
}
|
|
72
|
+
function Source(props) {
|
|
73
|
+
const obj = useContext(this);
|
|
74
|
+
if (!obj)
|
|
75
|
+
return props.children;
|
|
76
|
+
if (obj.source)
|
|
77
|
+
throw new Error("Un extractor non può avere più di una sorgente");
|
|
78
|
+
const memo = children(() => props.children);
|
|
79
|
+
obj.source = createMemo(memo);
|
|
80
|
+
onCleanup(() => obj.source = void 0);
|
|
81
|
+
return createComponent(Show, {
|
|
82
|
+
get when() {
|
|
83
|
+
return !obj.attached;
|
|
84
|
+
},
|
|
85
|
+
get children() {
|
|
86
|
+
return memo();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function Joint(props) {
|
|
91
|
+
const obj = createMutable({
|
|
92
|
+
attached: false
|
|
93
|
+
});
|
|
94
|
+
return createComponent("this".Provider, {
|
|
95
|
+
value: obj,
|
|
96
|
+
get children() {
|
|
97
|
+
return props.children;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function memoProps(obj, keys = Object.keys(obj)) {
|
|
102
|
+
const out = {};
|
|
103
|
+
for (const elm of keys)
|
|
104
|
+
Object.defineProperty(out, elm, {
|
|
105
|
+
get: createMemo(() => obj[elm])
|
|
106
|
+
});
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
function splitAndMemoProps(obj, keys) {
|
|
110
|
+
const [mine, other] = splitProps(obj, keys);
|
|
111
|
+
return [memoProps(mine, keys), other];
|
|
112
|
+
}
|
|
113
|
+
export {
|
|
114
|
+
Case,
|
|
115
|
+
Debug,
|
|
116
|
+
When,
|
|
117
|
+
createExtractor,
|
|
118
|
+
memoProps,
|
|
119
|
+
splitAndMemoProps
|
|
120
|
+
};
|
package/dist/flow.umd.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
(function(global, factory) {
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("solid-js"), require("solid-js/store")) : typeof define === "function" && define.amd ? define(["exports", "solid-js", "solid-js/store"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.solidFlow = {}, global.solidJs, global.solidJsStore));
|
|
3
|
+
})(this, function(exports2, solidJs, store) {
|
|
4
|
+
"use strict";
|
|
5
|
+
const ctx$1 = solidJs.createContext(() => void 0, {
|
|
6
|
+
name: "case-when"
|
|
7
|
+
});
|
|
8
|
+
function Case(props) {
|
|
9
|
+
const memo = solidJs.createMemo(() => props.value);
|
|
10
|
+
return solidJs.createComponent(ctx$1.Provider, {
|
|
11
|
+
value: memo,
|
|
12
|
+
get children() {
|
|
13
|
+
return props.children;
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function When(props) {
|
|
18
|
+
const [mine, other] = splitAndMemoProps(props, ["value", "pred"]);
|
|
19
|
+
const value = solidJs.useContext(ctx$1);
|
|
20
|
+
const pred = (x) => mine.pred ? mine.pred(x) : x === mine.value;
|
|
21
|
+
return solidJs.createComponent(solidJs.Match, solidJs.mergeProps({
|
|
22
|
+
get when() {
|
|
23
|
+
return pred(value());
|
|
24
|
+
}
|
|
25
|
+
}, other));
|
|
26
|
+
}
|
|
27
|
+
const ctx = solidJs.createContext(() => false, {
|
|
28
|
+
name: "debug-scope"
|
|
29
|
+
});
|
|
30
|
+
function Debug(props) {
|
|
31
|
+
return solidJs.createComponent(ctx.Provider, {
|
|
32
|
+
value: () => props.value ?? true,
|
|
33
|
+
get children() {
|
|
34
|
+
return props.children;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
(function(_Debug) {
|
|
39
|
+
Object.defineProperty(Debug, "isDebug", {
|
|
40
|
+
get: () => solidJs.useContext(ctx)
|
|
41
|
+
});
|
|
42
|
+
})(Debug || (Debug = {}));
|
|
43
|
+
function createExtractor(name = "extractor") {
|
|
44
|
+
const ctx2 = solidJs.createContext(void 0, {
|
|
45
|
+
name
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
/** Bound {@link Dest} */
|
|
49
|
+
Dest: Dest.bind(ctx2),
|
|
50
|
+
/** Bound {@link Source} */
|
|
51
|
+
Source: Source.bind(ctx2),
|
|
52
|
+
/** Bound {@link Joint} */
|
|
53
|
+
Joint: Joint.bind(ctx2),
|
|
54
|
+
/**
|
|
55
|
+
* Gets an {@link Accessor} that tells if the context in which THIS getter has been executed has been extracted (Is inside of a {@link Dest})
|
|
56
|
+
* @returns Returns `null` if there is no parent {@link Joint}, `false` if there is a {@link Joint} but not a {@link Dest} and `true` otherwise
|
|
57
|
+
*/
|
|
58
|
+
get isExtracted() {
|
|
59
|
+
const obj = solidJs.useContext(ctx2);
|
|
60
|
+
return () => obj?.attached ?? null;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function Dest() {
|
|
65
|
+
const obj = solidJs.useContext(this);
|
|
66
|
+
if (!obj)
|
|
67
|
+
return;
|
|
68
|
+
if (obj.attached)
|
|
69
|
+
throw new Error("Un extractor non può avere più di una destinazione");
|
|
70
|
+
obj.attached = true;
|
|
71
|
+
solidJs.onCleanup(() => obj.attached = false);
|
|
72
|
+
return solidJs.createMemo(() => obj.source);
|
|
73
|
+
}
|
|
74
|
+
function Source(props) {
|
|
75
|
+
const obj = solidJs.useContext(this);
|
|
76
|
+
if (!obj)
|
|
77
|
+
return props.children;
|
|
78
|
+
if (obj.source)
|
|
79
|
+
throw new Error("Un extractor non può avere più di una sorgente");
|
|
80
|
+
const memo = solidJs.children(() => props.children);
|
|
81
|
+
obj.source = solidJs.createMemo(memo);
|
|
82
|
+
solidJs.onCleanup(() => obj.source = void 0);
|
|
83
|
+
return solidJs.createComponent(solidJs.Show, {
|
|
84
|
+
get when() {
|
|
85
|
+
return !obj.attached;
|
|
86
|
+
},
|
|
87
|
+
get children() {
|
|
88
|
+
return memo();
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function Joint(props) {
|
|
93
|
+
const obj = store.createMutable({
|
|
94
|
+
attached: false
|
|
95
|
+
});
|
|
96
|
+
return solidJs.createComponent("this".Provider, {
|
|
97
|
+
value: obj,
|
|
98
|
+
get children() {
|
|
99
|
+
return props.children;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function memoProps(obj, keys = Object.keys(obj)) {
|
|
104
|
+
const out = {};
|
|
105
|
+
for (const elm of keys)
|
|
106
|
+
Object.defineProperty(out, elm, {
|
|
107
|
+
get: solidJs.createMemo(() => obj[elm])
|
|
108
|
+
});
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
function splitAndMemoProps(obj, keys) {
|
|
112
|
+
const [mine, other] = solidJs.splitProps(obj, keys);
|
|
113
|
+
return [memoProps(mine, keys), other];
|
|
114
|
+
}
|
|
115
|
+
exports2.Case = Case;
|
|
116
|
+
exports2.Debug = Debug;
|
|
117
|
+
exports2.When = When;
|
|
118
|
+
exports2.createExtractor = createExtractor;
|
|
119
|
+
exports2.memoProps = memoProps;
|
|
120
|
+
exports2.splitAndMemoProps = splitAndMemoProps;
|
|
121
|
+
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
122
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "solid-ctrl-flow",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Control flow components for solid-js",
|
|
5
|
+
"author": "AFatNiBBa",
|
|
6
|
+
"license": "ISC",
|
|
7
|
+
"types": "./dist/flow.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
"require": "./dist/flow.umd.js",
|
|
10
|
+
"import": "./dist/flow.mjs",
|
|
11
|
+
"types": "./dist/flow.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "vite build",
|
|
15
|
+
"save": "npm run build && npm publish"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "^20.6.0",
|
|
19
|
+
"vite": "^4.4.9",
|
|
20
|
+
"vite-plugin-dts": "^3.5.3",
|
|
21
|
+
"vite-plugin-solid": "^2.7.0"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"solid-js": "^1.7.11"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/AFatNiBBa/solid-ctrl-flow.git"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"solid-js",
|
|
32
|
+
"control",
|
|
33
|
+
"flow",
|
|
34
|
+
"switch",
|
|
35
|
+
"case",
|
|
36
|
+
"when",
|
|
37
|
+
"debug"
|
|
38
|
+
]
|
|
39
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
|
|
2
|
+
# solid-ctrl-flow
|
|
3
|
+
Control flow components for "solid-js"
|
|
4
|
+
|
|
5
|
+
## Components
|
|
6
|
+
|
|
7
|
+
### `Case` - `When`
|
|
8
|
+
Allows you to not specify the full condition inside of a `Switch` component.
|
|
9
|
+
The following code
|
|
10
|
+
```tsx
|
|
11
|
+
const value = 1;
|
|
12
|
+
return <>
|
|
13
|
+
<Switch>
|
|
14
|
+
<Case value={value}>
|
|
15
|
+
<When value={1}>One</When>
|
|
16
|
+
<When value={2}>Two</When>
|
|
17
|
+
<When pred={(x) => `${x}`.length === 3}>Long</When>
|
|
18
|
+
</Case>
|
|
19
|
+
<Match when>Default</Match>
|
|
20
|
+
</Switch>
|
|
21
|
+
</>
|
|
22
|
+
```
|
|
23
|
+
Is equivalent to this
|
|
24
|
+
```tsx
|
|
25
|
+
const value = 1;
|
|
26
|
+
return <>
|
|
27
|
+
<Switch>
|
|
28
|
+
<Match when={value === 1}>One</Match>
|
|
29
|
+
<Match when={value === 2}>Two</Match>
|
|
30
|
+
<Match when={`${value}`.length === 3}>Long</Match>
|
|
31
|
+
<Match when>Default</Match>
|
|
32
|
+
</Switch>
|
|
33
|
+
</>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### `Debug`
|
|
37
|
+
Allows you to define ui section that are only visible in debug or NOT in debug
|
|
38
|
+
```tsx
|
|
39
|
+
const value = false;
|
|
40
|
+
return <>
|
|
41
|
+
<Debug value={value}>
|
|
42
|
+
{/* (A LOT OF NESTING...) */}
|
|
43
|
+
<Show when={Debug.isDebug()}>
|
|
44
|
+
THIS WOULD BE VISIBLE IF "value" HAD BEEN {true}
|
|
45
|
+
</Show>
|
|
46
|
+
</Debug>
|
|
47
|
+
</>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### `createExtractor()`
|
|
51
|
+
Creates a context for components that may need to be out of their parent in certain conditions.
|
|
52
|
+
If you have this component
|
|
53
|
+
```tsx
|
|
54
|
+
const myCustomExtractor = createExtractor();
|
|
55
|
+
|
|
56
|
+
function MyCustomComponent() {
|
|
57
|
+
return <>
|
|
58
|
+
1
|
|
59
|
+
<myCustomExtractor.Source>
|
|
60
|
+
2 {/* THIS WILL BE MOVED INSIDE THE "Dest" */}
|
|
61
|
+
</myCustomExtractor.Source>
|
|
62
|
+
3
|
|
63
|
+
</>
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
If you use it normally it will output `1`, `2`, `3`, `4`, `5`
|
|
67
|
+
```tsx
|
|
68
|
+
return <>
|
|
69
|
+
4
|
|
70
|
+
<MyCustomComponent />
|
|
71
|
+
5
|
|
72
|
+
</>
|
|
73
|
+
```
|
|
74
|
+
But if you use it together with a `Dest` and a `Joint` it will output `6`, `7`, `8`, ***`2`***, `9`, `10`, `11`, ***`1`***, ***`3`***, `12`, `13`, `14`
|
|
75
|
+
```tsx
|
|
76
|
+
return <>
|
|
77
|
+
6
|
|
78
|
+
<myCustomExtractor.Joint>
|
|
79
|
+
7
|
|
80
|
+
<div>
|
|
81
|
+
8
|
|
82
|
+
<myCustomExtractor.Dest /> {/* THE CONTENT OF "Source" WILL BE MOVED HERE */}
|
|
83
|
+
9
|
|
84
|
+
</div>
|
|
85
|
+
10
|
|
86
|
+
<div>
|
|
87
|
+
11
|
|
88
|
+
<MyCustomComponent />
|
|
89
|
+
12
|
|
90
|
+
</div>
|
|
91
|
+
13
|
|
92
|
+
</myCustomExtractor.Joint>
|
|
93
|
+
14
|
|
94
|
+
</>
|
|
95
|
+
```
|
|
96
|
+
The `Joint` component is necessary for the `Source` and the `Dest` to communicate with each other.
|
|
97
|
+
For example this will output `15`, `16`, `17`, `18`, `19`, ***`1`***, ***`2`***, ***`3`***, `20`, `21`
|
|
98
|
+
```tsx
|
|
99
|
+
return <>
|
|
100
|
+
15
|
|
101
|
+
<div>
|
|
102
|
+
16
|
|
103
|
+
<myCustomExtractor.Dest />
|
|
104
|
+
17
|
|
105
|
+
</div>
|
|
106
|
+
18
|
|
107
|
+
<div>
|
|
108
|
+
19
|
|
109
|
+
<MyCustomComponent />
|
|
110
|
+
20
|
|
111
|
+
</div>
|
|
112
|
+
21
|
|
113
|
+
</>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Utility functions
|
|
117
|
+
Utility functions needed for the components above
|
|
118
|
+
|
|
119
|
+
### `memoProps()`
|
|
120
|
+
Creates a partial version of an object with memoized remaining properties
|
|
121
|
+
|
|
122
|
+
### `splitAndMemoProps()`
|
|
123
|
+
Like `splitProps()` but memoizes the whole local part
|