solid-js 1.1.6-beta.1 → 1.2.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/README.md +2 -4
- package/dist/dev.cjs +12 -4
- package/dist/dev.js +12 -4
- package/dist/solid.cjs +12 -4
- package/dist/solid.js +12 -4
- package/h/README.md +99 -0
- package/html/README.md +84 -0
- package/html/dist/html.cjs +24 -6
- package/html/dist/html.js +25 -7
- package/package.json +14 -2
- package/store/README.md +23 -0
- package/types/jsx.d.ts +3 -2
- package/types/reactive/signal.d.ts +3 -3
- package/types/render/component.d.ts +1 -1
- package/universal/README.md +102 -0
- package/universal/dist/dev.cjs +258 -0
- package/universal/dist/dev.js +254 -0
- package/universal/dist/universal.cjs +258 -0
- package/universal/dist/universal.js +254 -0
- package/universal/package.json +8 -0
- package/universal/types/index.d.ts +2 -0
- package/universal/types/universal.d.ts +29 -0
- package/web/README.md +7 -0
- package/web/types/client.d.ts +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { requestCallback } from "./scheduler";
|
|
2
2
|
import type { JSX } from "../jsx";
|
|
3
3
|
export declare type Accessor<T> = () => T;
|
|
4
|
-
export declare type Setter<T> = undefined extends T ? <U extends T>(v?: (U extends Function ? never : U) | ((prev?:
|
|
4
|
+
export declare type Setter<T> = undefined extends T ? <U extends T>(v?: (U extends Function ? never : U) | ((prev?: T) => U)) => U : <U extends T>(v: (U extends Function ? never : U) | ((prev: T) => U)) => U;
|
|
5
5
|
export declare const equalFn: <T>(a: T, b: T) => boolean;
|
|
6
6
|
export declare const $PROXY: unique symbol;
|
|
7
7
|
export declare const NOTPENDING: {};
|
|
@@ -248,7 +248,7 @@ export declare function createDeferred<T>(source: Accessor<T>, options?: {
|
|
|
248
248
|
/**
|
|
249
249
|
* Creates a conditional signal that only notifies subscribers when entering or exiting their key matching the value
|
|
250
250
|
* ```typescript
|
|
251
|
-
* export function
|
|
251
|
+
* export function createSelector<T, U>(
|
|
252
252
|
* source: () => T
|
|
253
253
|
* fn: (a: U, b: T) => boolean,
|
|
254
254
|
* options?: { name?: string }
|
|
@@ -267,7 +267,7 @@ export declare function createDeferred<T>(source: Accessor<T>, options?: {
|
|
|
267
267
|
*
|
|
268
268
|
* This makes the operation O(2) instead of O(n).
|
|
269
269
|
*
|
|
270
|
-
* @description https://www.solidjs.com/docs/latest/api#
|
|
270
|
+
* @description https://www.solidjs.com/docs/latest/api#createselector
|
|
271
271
|
*/
|
|
272
272
|
export declare function createSelector<T, U>(source: Accessor<T>, fn?: (a: U, b: T) => boolean, options?: {
|
|
273
273
|
name?: string;
|
|
@@ -15,7 +15,7 @@ export declare function createComponent<T>(Comp: (props: T) => JSX.Element, prop
|
|
|
15
15
|
declare type BoxedTupleTypes<T extends any[]> = {
|
|
16
16
|
[P in keyof T]: [T[P]];
|
|
17
17
|
}[Exclude<keyof T, keyof any[]>];
|
|
18
|
-
declare type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
|
|
18
|
+
declare type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
19
19
|
declare type UnboxIntersection<T> = T extends {
|
|
20
20
|
0: infer U;
|
|
21
21
|
} ? U : never;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Solid Universal
|
|
2
|
+
|
|
3
|
+
This contains the means to create the runtime for a custom renderer for Solid. This can enable using Solid to render to different platforms like native mobile and desktop, canvas or WebGL, or even the terminal. It relies on custom compilation from `babel-preset-solid` and exporting the result of `createRenderer` at a referenceable location.
|
|
4
|
+
|
|
5
|
+
## Example
|
|
6
|
+
|
|
7
|
+
To use a custom renderer available in the (fictional) `solid-custom-dom` package you'd configure your babelrc as:
|
|
8
|
+
```json
|
|
9
|
+
{
|
|
10
|
+
"presets": [
|
|
11
|
+
[
|
|
12
|
+
"babel-preset-solid",
|
|
13
|
+
{
|
|
14
|
+
"moduleName": "solid-custom-dom",
|
|
15
|
+
"generate": "universal"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
To create a custom renderer you must implement certain methods and export (as named exports) the results. You may also want to forward `solid-js` control flow to allow them to be auto imported as well.
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
// example custom dom renderer
|
|
26
|
+
import { createRenderer } from "solid-js/universal";
|
|
27
|
+
|
|
28
|
+
const PROPERTIES = new Set(["className", "textContent"]);
|
|
29
|
+
|
|
30
|
+
export const {
|
|
31
|
+
render,
|
|
32
|
+
effect,
|
|
33
|
+
memo,
|
|
34
|
+
createComponent,
|
|
35
|
+
createElement,
|
|
36
|
+
createTextNode,
|
|
37
|
+
insertNode,
|
|
38
|
+
insert,
|
|
39
|
+
spread,
|
|
40
|
+
setProp,
|
|
41
|
+
mergeProps
|
|
42
|
+
} = createRenderer({
|
|
43
|
+
createElement(string) {
|
|
44
|
+
return document.createElement(string);
|
|
45
|
+
},
|
|
46
|
+
createTextNode(value) {
|
|
47
|
+
return document.createTextNode(value);
|
|
48
|
+
},
|
|
49
|
+
replaceText(textNode, value) {
|
|
50
|
+
textNode.data = value;
|
|
51
|
+
},
|
|
52
|
+
setProperty(node, name, value) {
|
|
53
|
+
if (name === "style") Object.assign(node.style, value);
|
|
54
|
+
else if (name.startsWith("on")) node[name.toLowerCase()] = value;
|
|
55
|
+
else if (PROPERTIES.has(name)) node[name] = value;
|
|
56
|
+
else node.setAttribute(name, value);
|
|
57
|
+
},
|
|
58
|
+
insertNode(parent, node, anchor) {
|
|
59
|
+
parent.insertBefore(node, anchor);
|
|
60
|
+
},
|
|
61
|
+
isTextNode(node) {
|
|
62
|
+
return node.type === 3;
|
|
63
|
+
},
|
|
64
|
+
removeNode(parent, node) {
|
|
65
|
+
parent.removeChild(node);
|
|
66
|
+
},
|
|
67
|
+
getParentNode(node) {
|
|
68
|
+
return node.parentNode;
|
|
69
|
+
},
|
|
70
|
+
getFirstChild(node) {
|
|
71
|
+
return node.firstChild;
|
|
72
|
+
},
|
|
73
|
+
getNextSibling(node) {
|
|
74
|
+
return node.nextSibling;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Forward Solid control flow
|
|
79
|
+
export {
|
|
80
|
+
For,
|
|
81
|
+
Show,
|
|
82
|
+
Suspense,
|
|
83
|
+
SuspenseList,
|
|
84
|
+
Switch,
|
|
85
|
+
Match,
|
|
86
|
+
Index,
|
|
87
|
+
ErrorBoundary
|
|
88
|
+
} from "solid-js";
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Then to consume:
|
|
92
|
+
```js
|
|
93
|
+
import { render } from "solid-custom-dom";
|
|
94
|
+
|
|
95
|
+
function App() {
|
|
96
|
+
// the skies the limits
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
render(() => <App />, mountNode)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
> Note: For TypeScript support of non-standard JSX you will need to provide your own types at a jsx-runtime entry on your package so that it can be set as the `jsxImportSource`. If mixing and matching different JSX implementations you will need use the per file pragmas.
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var solidJs = require('solid-js');
|
|
6
|
+
|
|
7
|
+
function memo(fn, equals) {
|
|
8
|
+
return solidJs.createMemo(fn, undefined, !equals ? {
|
|
9
|
+
equals
|
|
10
|
+
} : undefined);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function createRenderer$1({
|
|
14
|
+
createElement,
|
|
15
|
+
createTextNode,
|
|
16
|
+
isTextNode,
|
|
17
|
+
replaceText,
|
|
18
|
+
insertNode,
|
|
19
|
+
removeNode,
|
|
20
|
+
setProperty,
|
|
21
|
+
getParentNode,
|
|
22
|
+
getFirstChild,
|
|
23
|
+
getNextSibling
|
|
24
|
+
}) {
|
|
25
|
+
function insert(parent, accessor, marker, initial) {
|
|
26
|
+
if (marker !== undefined && !initial) initial = [];
|
|
27
|
+
if (typeof accessor !== "function") return insertExpression(parent, accessor, initial, marker);
|
|
28
|
+
solidJs.createRenderEffect(current => insertExpression(parent, accessor(), current, marker), initial);
|
|
29
|
+
}
|
|
30
|
+
function insertExpression(parent, value, current, marker, unwrapArray) {
|
|
31
|
+
while (typeof current === "function") current = current();
|
|
32
|
+
if (value === current) return current;
|
|
33
|
+
const t = typeof value,
|
|
34
|
+
multi = marker !== undefined;
|
|
35
|
+
if (t === "string" || t === "number") {
|
|
36
|
+
if (t === "number") value = value.toString();
|
|
37
|
+
if (multi) {
|
|
38
|
+
let node = current[0];
|
|
39
|
+
if (node && isTextNode(node)) {
|
|
40
|
+
replaceText(node, value);
|
|
41
|
+
} else node = createTextNode(value);
|
|
42
|
+
current = cleanChildren(parent, current, marker, node);
|
|
43
|
+
} else {
|
|
44
|
+
if (current !== "" && typeof current === "string") {
|
|
45
|
+
replaceText(getFirstChild(parent), current = value);
|
|
46
|
+
} else {
|
|
47
|
+
cleanChildren(parent, current, marker, createTextNode(value));
|
|
48
|
+
current = value;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
} else if (value == null || t === "boolean") {
|
|
52
|
+
current = cleanChildren(parent, current, marker);
|
|
53
|
+
} else if (t === "function") {
|
|
54
|
+
solidJs.createRenderEffect(() => {
|
|
55
|
+
let v = value();
|
|
56
|
+
while (typeof v === "function") v = v();
|
|
57
|
+
current = insertExpression(parent, v, current, marker);
|
|
58
|
+
});
|
|
59
|
+
return () => current;
|
|
60
|
+
} else if (Array.isArray(value)) {
|
|
61
|
+
const array = [];
|
|
62
|
+
if (normalizeIncomingArray(array, value, unwrapArray)) {
|
|
63
|
+
solidJs.createRenderEffect(() => current = insertExpression(parent, array, current, marker, true));
|
|
64
|
+
return () => current;
|
|
65
|
+
}
|
|
66
|
+
if (array.length === 0) {
|
|
67
|
+
const replacement = cleanChildren(parent, current, marker);
|
|
68
|
+
if (multi) return current = replacement;
|
|
69
|
+
} else {
|
|
70
|
+
if (Array.isArray(current)) {
|
|
71
|
+
if (current.length === 0) {
|
|
72
|
+
appendNodes(parent, array, marker);
|
|
73
|
+
} else reconcileArrays(parent, current, array);
|
|
74
|
+
} else if (current == null || current === "") {
|
|
75
|
+
appendNodes(parent, array);
|
|
76
|
+
} else {
|
|
77
|
+
reconcileArrays(parent, multi && current || [getFirstChild(parent)], array);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
current = array;
|
|
81
|
+
} else {
|
|
82
|
+
if (Array.isArray(current)) {
|
|
83
|
+
if (multi) return current = cleanChildren(parent, current, marker, value);
|
|
84
|
+
cleanChildren(parent, current, null, value);
|
|
85
|
+
} else if (current == null || current === "" || !getFirstChild(parent)) {
|
|
86
|
+
insertNode(parent, value);
|
|
87
|
+
} else replaceNode(parent, value, getFirstChild(parent));
|
|
88
|
+
current = value;
|
|
89
|
+
}
|
|
90
|
+
return current;
|
|
91
|
+
}
|
|
92
|
+
function normalizeIncomingArray(normalized, array, unwrap) {
|
|
93
|
+
let dynamic = false;
|
|
94
|
+
for (let i = 0, len = array.length; i < len; i++) {
|
|
95
|
+
let item = array[i],
|
|
96
|
+
t;
|
|
97
|
+
if (item == null || item === true || item === false) ; else if (Array.isArray(item)) {
|
|
98
|
+
dynamic = normalizeIncomingArray(normalized, item) || dynamic;
|
|
99
|
+
} else if ((t = typeof item) === "string" || t === "number") {
|
|
100
|
+
normalized.push(createTextNode(item));
|
|
101
|
+
} else if (t === "function") {
|
|
102
|
+
if (unwrap) {
|
|
103
|
+
while (typeof item === "function") item = item();
|
|
104
|
+
dynamic = normalizeIncomingArray(normalized, Array.isArray(item) ? item : [item]) || dynamic;
|
|
105
|
+
} else {
|
|
106
|
+
normalized.push(item);
|
|
107
|
+
dynamic = true;
|
|
108
|
+
}
|
|
109
|
+
} else normalized.push(item);
|
|
110
|
+
}
|
|
111
|
+
return dynamic;
|
|
112
|
+
}
|
|
113
|
+
function reconcileArrays(parentNode, a, b) {
|
|
114
|
+
let bLength = b.length,
|
|
115
|
+
aEnd = a.length,
|
|
116
|
+
bEnd = bLength,
|
|
117
|
+
aStart = 0,
|
|
118
|
+
bStart = 0,
|
|
119
|
+
after = getNextSibling(a[aEnd - 1]),
|
|
120
|
+
map = null;
|
|
121
|
+
while (aStart < aEnd || bStart < bEnd) {
|
|
122
|
+
if (a[aStart] === b[bStart]) {
|
|
123
|
+
aStart++;
|
|
124
|
+
bStart++;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
while (a[aEnd - 1] === b[bEnd - 1]) {
|
|
128
|
+
aEnd--;
|
|
129
|
+
bEnd--;
|
|
130
|
+
}
|
|
131
|
+
if (aEnd === aStart) {
|
|
132
|
+
const node = bEnd < bLength ? bStart ? getNextSibling(b[bStart - 1]) : b[bEnd - bStart] : after;
|
|
133
|
+
while (bStart < bEnd) insertNode(parentNode, b[bStart++], node);
|
|
134
|
+
} else if (bEnd === bStart) {
|
|
135
|
+
while (aStart < aEnd) {
|
|
136
|
+
if (!map || !map.has(a[aStart])) removeNode(parentNode, a[aStart]);
|
|
137
|
+
aStart++;
|
|
138
|
+
}
|
|
139
|
+
} else if (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]) {
|
|
140
|
+
const node = getNextSibling(a[--aEnd]);
|
|
141
|
+
insertNode(parentNode, b[bStart++], getNextSibling(a[aStart++]));
|
|
142
|
+
insertNode(parentNode, b[--bEnd], node);
|
|
143
|
+
a[aEnd] = b[bEnd];
|
|
144
|
+
} else {
|
|
145
|
+
if (!map) {
|
|
146
|
+
map = new Map();
|
|
147
|
+
let i = bStart;
|
|
148
|
+
while (i < bEnd) map.set(b[i], i++);
|
|
149
|
+
}
|
|
150
|
+
const index = map.get(a[aStart]);
|
|
151
|
+
if (index != null) {
|
|
152
|
+
if (bStart < index && index < bEnd) {
|
|
153
|
+
let i = aStart,
|
|
154
|
+
sequence = 1,
|
|
155
|
+
t;
|
|
156
|
+
while (++i < aEnd && i < bEnd) {
|
|
157
|
+
if ((t = map.get(a[i])) == null || t !== index + sequence) break;
|
|
158
|
+
sequence++;
|
|
159
|
+
}
|
|
160
|
+
if (sequence > index - bStart) {
|
|
161
|
+
const node = a[aStart];
|
|
162
|
+
while (bStart < index) insertNode(parentNode, b[bStart++], node);
|
|
163
|
+
} else replaceNode(parentNode, b[bStart++], a[aStart++]);
|
|
164
|
+
} else aStart++;
|
|
165
|
+
} else removeNode(parentNode, a[aStart++]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function cleanChildren(parent, current, marker, replacement) {
|
|
170
|
+
if (marker === undefined) {
|
|
171
|
+
let removed;
|
|
172
|
+
while (removed = getFirstChild(parent)) removeNode(parent, removed);
|
|
173
|
+
replacement && insertNode(parent, replacement);
|
|
174
|
+
return "";
|
|
175
|
+
}
|
|
176
|
+
const node = replacement || createTextNode("");
|
|
177
|
+
if (current.length) {
|
|
178
|
+
let inserted = false;
|
|
179
|
+
for (let i = current.length - 1; i >= 0; i--) {
|
|
180
|
+
const el = current[i];
|
|
181
|
+
if (node !== el) {
|
|
182
|
+
const isParent = getParentNode(el) === parent;
|
|
183
|
+
if (!inserted && !i) isParent ? replaceNode(parent, node, el) : insertNode(parent, node, marker);else isParent && removeNode(parent, el);
|
|
184
|
+
} else inserted = true;
|
|
185
|
+
}
|
|
186
|
+
} else insertNode(parent, node, marker);
|
|
187
|
+
return [node];
|
|
188
|
+
}
|
|
189
|
+
function appendNodes(parent, array, marker) {
|
|
190
|
+
for (let i = 0, len = array.length; i < len; i++) insertNode(parent, array[i], marker);
|
|
191
|
+
}
|
|
192
|
+
function replaceNode(parent, newNode, oldNode) {
|
|
193
|
+
insertNode(parent, newNode, oldNode);
|
|
194
|
+
removeNode(parent, oldNode);
|
|
195
|
+
}
|
|
196
|
+
function spreadExpression(node, props, prevProps = {}, skipChildren) {
|
|
197
|
+
if (!skipChildren && "children" in props) {
|
|
198
|
+
solidJs.createRenderEffect(() => prevProps.children = insertExpression(node, props.children, prevProps.children));
|
|
199
|
+
}
|
|
200
|
+
solidJs.createRenderEffect(() => {
|
|
201
|
+
for (const prop in props) {
|
|
202
|
+
if (prop === "children") continue;
|
|
203
|
+
const value = props[prop];
|
|
204
|
+
if (value === prevProps[prop]) continue;
|
|
205
|
+
if (prop === "ref") value(node);else {
|
|
206
|
+
setProperty(node, prop, value, prevProps[prop]);
|
|
207
|
+
prevProps[prop] = value;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
return prevProps;
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
render(code, element) {
|
|
215
|
+
let disposer;
|
|
216
|
+
solidJs.createRoot(dispose => {
|
|
217
|
+
disposer = dispose;
|
|
218
|
+
insert(element, code());
|
|
219
|
+
});
|
|
220
|
+
return disposer;
|
|
221
|
+
},
|
|
222
|
+
insert,
|
|
223
|
+
spread(node, accessor, skipChildren) {
|
|
224
|
+
if (typeof accessor === "function") {
|
|
225
|
+
solidJs.createRenderEffect(current => spreadExpression(node, accessor(), current, skipChildren));
|
|
226
|
+
} else spreadExpression(node, accessor, undefined, skipChildren);
|
|
227
|
+
},
|
|
228
|
+
createElement,
|
|
229
|
+
createTextNode,
|
|
230
|
+
insertNode,
|
|
231
|
+
setProp(node, name, value, prev) {
|
|
232
|
+
setProperty(node, name, value, prev);
|
|
233
|
+
return value;
|
|
234
|
+
},
|
|
235
|
+
mergeProps,
|
|
236
|
+
effect: solidJs.createRenderEffect,
|
|
237
|
+
memo,
|
|
238
|
+
createComponent: solidJs.createComponent
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function mergeProps(...sources) {
|
|
242
|
+
const target = {};
|
|
243
|
+
for (let i = 0; i < sources.length; i++) {
|
|
244
|
+
let source = sources[i];
|
|
245
|
+
if (typeof source === "function") source = source();
|
|
246
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
247
|
+
Object.defineProperties(target, descriptors);
|
|
248
|
+
}
|
|
249
|
+
return target;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function createRenderer(options) {
|
|
253
|
+
const renderer = createRenderer$1(options);
|
|
254
|
+
renderer.mergeProps = solidJs.mergeProps;
|
|
255
|
+
return renderer;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
exports.createRenderer = createRenderer;
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { createMemo, createRoot, createRenderEffect, createComponent, mergeProps as mergeProps$1 } from 'solid-js';
|
|
2
|
+
|
|
3
|
+
function memo(fn, equals) {
|
|
4
|
+
return createMemo(fn, undefined, !equals ? {
|
|
5
|
+
equals
|
|
6
|
+
} : undefined);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function createRenderer$1({
|
|
10
|
+
createElement,
|
|
11
|
+
createTextNode,
|
|
12
|
+
isTextNode,
|
|
13
|
+
replaceText,
|
|
14
|
+
insertNode,
|
|
15
|
+
removeNode,
|
|
16
|
+
setProperty,
|
|
17
|
+
getParentNode,
|
|
18
|
+
getFirstChild,
|
|
19
|
+
getNextSibling
|
|
20
|
+
}) {
|
|
21
|
+
function insert(parent, accessor, marker, initial) {
|
|
22
|
+
if (marker !== undefined && !initial) initial = [];
|
|
23
|
+
if (typeof accessor !== "function") return insertExpression(parent, accessor, initial, marker);
|
|
24
|
+
createRenderEffect(current => insertExpression(parent, accessor(), current, marker), initial);
|
|
25
|
+
}
|
|
26
|
+
function insertExpression(parent, value, current, marker, unwrapArray) {
|
|
27
|
+
while (typeof current === "function") current = current();
|
|
28
|
+
if (value === current) return current;
|
|
29
|
+
const t = typeof value,
|
|
30
|
+
multi = marker !== undefined;
|
|
31
|
+
if (t === "string" || t === "number") {
|
|
32
|
+
if (t === "number") value = value.toString();
|
|
33
|
+
if (multi) {
|
|
34
|
+
let node = current[0];
|
|
35
|
+
if (node && isTextNode(node)) {
|
|
36
|
+
replaceText(node, value);
|
|
37
|
+
} else node = createTextNode(value);
|
|
38
|
+
current = cleanChildren(parent, current, marker, node);
|
|
39
|
+
} else {
|
|
40
|
+
if (current !== "" && typeof current === "string") {
|
|
41
|
+
replaceText(getFirstChild(parent), current = value);
|
|
42
|
+
} else {
|
|
43
|
+
cleanChildren(parent, current, marker, createTextNode(value));
|
|
44
|
+
current = value;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
} else if (value == null || t === "boolean") {
|
|
48
|
+
current = cleanChildren(parent, current, marker);
|
|
49
|
+
} else if (t === "function") {
|
|
50
|
+
createRenderEffect(() => {
|
|
51
|
+
let v = value();
|
|
52
|
+
while (typeof v === "function") v = v();
|
|
53
|
+
current = insertExpression(parent, v, current, marker);
|
|
54
|
+
});
|
|
55
|
+
return () => current;
|
|
56
|
+
} else if (Array.isArray(value)) {
|
|
57
|
+
const array = [];
|
|
58
|
+
if (normalizeIncomingArray(array, value, unwrapArray)) {
|
|
59
|
+
createRenderEffect(() => current = insertExpression(parent, array, current, marker, true));
|
|
60
|
+
return () => current;
|
|
61
|
+
}
|
|
62
|
+
if (array.length === 0) {
|
|
63
|
+
const replacement = cleanChildren(parent, current, marker);
|
|
64
|
+
if (multi) return current = replacement;
|
|
65
|
+
} else {
|
|
66
|
+
if (Array.isArray(current)) {
|
|
67
|
+
if (current.length === 0) {
|
|
68
|
+
appendNodes(parent, array, marker);
|
|
69
|
+
} else reconcileArrays(parent, current, array);
|
|
70
|
+
} else if (current == null || current === "") {
|
|
71
|
+
appendNodes(parent, array);
|
|
72
|
+
} else {
|
|
73
|
+
reconcileArrays(parent, multi && current || [getFirstChild(parent)], array);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
current = array;
|
|
77
|
+
} else {
|
|
78
|
+
if (Array.isArray(current)) {
|
|
79
|
+
if (multi) return current = cleanChildren(parent, current, marker, value);
|
|
80
|
+
cleanChildren(parent, current, null, value);
|
|
81
|
+
} else if (current == null || current === "" || !getFirstChild(parent)) {
|
|
82
|
+
insertNode(parent, value);
|
|
83
|
+
} else replaceNode(parent, value, getFirstChild(parent));
|
|
84
|
+
current = value;
|
|
85
|
+
}
|
|
86
|
+
return current;
|
|
87
|
+
}
|
|
88
|
+
function normalizeIncomingArray(normalized, array, unwrap) {
|
|
89
|
+
let dynamic = false;
|
|
90
|
+
for (let i = 0, len = array.length; i < len; i++) {
|
|
91
|
+
let item = array[i],
|
|
92
|
+
t;
|
|
93
|
+
if (item == null || item === true || item === false) ; else if (Array.isArray(item)) {
|
|
94
|
+
dynamic = normalizeIncomingArray(normalized, item) || dynamic;
|
|
95
|
+
} else if ((t = typeof item) === "string" || t === "number") {
|
|
96
|
+
normalized.push(createTextNode(item));
|
|
97
|
+
} else if (t === "function") {
|
|
98
|
+
if (unwrap) {
|
|
99
|
+
while (typeof item === "function") item = item();
|
|
100
|
+
dynamic = normalizeIncomingArray(normalized, Array.isArray(item) ? item : [item]) || dynamic;
|
|
101
|
+
} else {
|
|
102
|
+
normalized.push(item);
|
|
103
|
+
dynamic = true;
|
|
104
|
+
}
|
|
105
|
+
} else normalized.push(item);
|
|
106
|
+
}
|
|
107
|
+
return dynamic;
|
|
108
|
+
}
|
|
109
|
+
function reconcileArrays(parentNode, a, b) {
|
|
110
|
+
let bLength = b.length,
|
|
111
|
+
aEnd = a.length,
|
|
112
|
+
bEnd = bLength,
|
|
113
|
+
aStart = 0,
|
|
114
|
+
bStart = 0,
|
|
115
|
+
after = getNextSibling(a[aEnd - 1]),
|
|
116
|
+
map = null;
|
|
117
|
+
while (aStart < aEnd || bStart < bEnd) {
|
|
118
|
+
if (a[aStart] === b[bStart]) {
|
|
119
|
+
aStart++;
|
|
120
|
+
bStart++;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
while (a[aEnd - 1] === b[bEnd - 1]) {
|
|
124
|
+
aEnd--;
|
|
125
|
+
bEnd--;
|
|
126
|
+
}
|
|
127
|
+
if (aEnd === aStart) {
|
|
128
|
+
const node = bEnd < bLength ? bStart ? getNextSibling(b[bStart - 1]) : b[bEnd - bStart] : after;
|
|
129
|
+
while (bStart < bEnd) insertNode(parentNode, b[bStart++], node);
|
|
130
|
+
} else if (bEnd === bStart) {
|
|
131
|
+
while (aStart < aEnd) {
|
|
132
|
+
if (!map || !map.has(a[aStart])) removeNode(parentNode, a[aStart]);
|
|
133
|
+
aStart++;
|
|
134
|
+
}
|
|
135
|
+
} else if (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]) {
|
|
136
|
+
const node = getNextSibling(a[--aEnd]);
|
|
137
|
+
insertNode(parentNode, b[bStart++], getNextSibling(a[aStart++]));
|
|
138
|
+
insertNode(parentNode, b[--bEnd], node);
|
|
139
|
+
a[aEnd] = b[bEnd];
|
|
140
|
+
} else {
|
|
141
|
+
if (!map) {
|
|
142
|
+
map = new Map();
|
|
143
|
+
let i = bStart;
|
|
144
|
+
while (i < bEnd) map.set(b[i], i++);
|
|
145
|
+
}
|
|
146
|
+
const index = map.get(a[aStart]);
|
|
147
|
+
if (index != null) {
|
|
148
|
+
if (bStart < index && index < bEnd) {
|
|
149
|
+
let i = aStart,
|
|
150
|
+
sequence = 1,
|
|
151
|
+
t;
|
|
152
|
+
while (++i < aEnd && i < bEnd) {
|
|
153
|
+
if ((t = map.get(a[i])) == null || t !== index + sequence) break;
|
|
154
|
+
sequence++;
|
|
155
|
+
}
|
|
156
|
+
if (sequence > index - bStart) {
|
|
157
|
+
const node = a[aStart];
|
|
158
|
+
while (bStart < index) insertNode(parentNode, b[bStart++], node);
|
|
159
|
+
} else replaceNode(parentNode, b[bStart++], a[aStart++]);
|
|
160
|
+
} else aStart++;
|
|
161
|
+
} else removeNode(parentNode, a[aStart++]);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function cleanChildren(parent, current, marker, replacement) {
|
|
166
|
+
if (marker === undefined) {
|
|
167
|
+
let removed;
|
|
168
|
+
while (removed = getFirstChild(parent)) removeNode(parent, removed);
|
|
169
|
+
replacement && insertNode(parent, replacement);
|
|
170
|
+
return "";
|
|
171
|
+
}
|
|
172
|
+
const node = replacement || createTextNode("");
|
|
173
|
+
if (current.length) {
|
|
174
|
+
let inserted = false;
|
|
175
|
+
for (let i = current.length - 1; i >= 0; i--) {
|
|
176
|
+
const el = current[i];
|
|
177
|
+
if (node !== el) {
|
|
178
|
+
const isParent = getParentNode(el) === parent;
|
|
179
|
+
if (!inserted && !i) isParent ? replaceNode(parent, node, el) : insertNode(parent, node, marker);else isParent && removeNode(parent, el);
|
|
180
|
+
} else inserted = true;
|
|
181
|
+
}
|
|
182
|
+
} else insertNode(parent, node, marker);
|
|
183
|
+
return [node];
|
|
184
|
+
}
|
|
185
|
+
function appendNodes(parent, array, marker) {
|
|
186
|
+
for (let i = 0, len = array.length; i < len; i++) insertNode(parent, array[i], marker);
|
|
187
|
+
}
|
|
188
|
+
function replaceNode(parent, newNode, oldNode) {
|
|
189
|
+
insertNode(parent, newNode, oldNode);
|
|
190
|
+
removeNode(parent, oldNode);
|
|
191
|
+
}
|
|
192
|
+
function spreadExpression(node, props, prevProps = {}, skipChildren) {
|
|
193
|
+
if (!skipChildren && "children" in props) {
|
|
194
|
+
createRenderEffect(() => prevProps.children = insertExpression(node, props.children, prevProps.children));
|
|
195
|
+
}
|
|
196
|
+
createRenderEffect(() => {
|
|
197
|
+
for (const prop in props) {
|
|
198
|
+
if (prop === "children") continue;
|
|
199
|
+
const value = props[prop];
|
|
200
|
+
if (value === prevProps[prop]) continue;
|
|
201
|
+
if (prop === "ref") value(node);else {
|
|
202
|
+
setProperty(node, prop, value, prevProps[prop]);
|
|
203
|
+
prevProps[prop] = value;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
return prevProps;
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
render(code, element) {
|
|
211
|
+
let disposer;
|
|
212
|
+
createRoot(dispose => {
|
|
213
|
+
disposer = dispose;
|
|
214
|
+
insert(element, code());
|
|
215
|
+
});
|
|
216
|
+
return disposer;
|
|
217
|
+
},
|
|
218
|
+
insert,
|
|
219
|
+
spread(node, accessor, skipChildren) {
|
|
220
|
+
if (typeof accessor === "function") {
|
|
221
|
+
createRenderEffect(current => spreadExpression(node, accessor(), current, skipChildren));
|
|
222
|
+
} else spreadExpression(node, accessor, undefined, skipChildren);
|
|
223
|
+
},
|
|
224
|
+
createElement,
|
|
225
|
+
createTextNode,
|
|
226
|
+
insertNode,
|
|
227
|
+
setProp(node, name, value, prev) {
|
|
228
|
+
setProperty(node, name, value, prev);
|
|
229
|
+
return value;
|
|
230
|
+
},
|
|
231
|
+
mergeProps,
|
|
232
|
+
effect: createRenderEffect,
|
|
233
|
+
memo,
|
|
234
|
+
createComponent
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function mergeProps(...sources) {
|
|
238
|
+
const target = {};
|
|
239
|
+
for (let i = 0; i < sources.length; i++) {
|
|
240
|
+
let source = sources[i];
|
|
241
|
+
if (typeof source === "function") source = source();
|
|
242
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
243
|
+
Object.defineProperties(target, descriptors);
|
|
244
|
+
}
|
|
245
|
+
return target;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function createRenderer(options) {
|
|
249
|
+
const renderer = createRenderer$1(options);
|
|
250
|
+
renderer.mergeProps = mergeProps$1;
|
|
251
|
+
return renderer;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export { createRenderer };
|