@lukekaalim/act-web 2.1.0 → 2.2.1
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/node.js +29 -13
- package/package.json +2 -2
- package/prop.js +30 -12
- package/reconciler.js +19 -8
- package/renderer.js +43 -48
package/node.js
CHANGED
|
@@ -1,27 +1,21 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
/*:: import type { Element } from '@lukekaalim/act'; */
|
|
3
|
-
/*:: import type { RenderResult } from '@lukekaalim/act-renderer-core'; */
|
|
3
|
+
/*:: import type { RenderResult, RenderResult2 } from '@lukekaalim/act-renderer-core'; */
|
|
4
4
|
/*:: import type { CommitDiff } from '@lukekaalim/act-reconciler'; */
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (
|
|
10
|
-
return null;
|
|
11
|
-
if (element.type === 'act:string')
|
|
6
|
+
import { calculateIndexChanges } from "@lukekaalim/act-reconciler/util";
|
|
7
|
+
|
|
8
|
+
export const createNode = (type/*: string*/, namespace/*: string*/)/*: Node*/ => {
|
|
9
|
+
if (type === 'act:string')
|
|
12
10
|
return document.createTextNode('');
|
|
13
|
-
|
|
14
|
-
return null;
|
|
15
|
-
if (element.type === 'act:boundary')
|
|
16
|
-
return null;
|
|
17
|
-
return document.createElementNS(namespace, element.type);
|
|
11
|
+
return document.createElementNS(namespace, type);
|
|
18
12
|
};
|
|
19
13
|
export const removeNode = (node/*: Node*/) => {
|
|
20
14
|
const parent = node.parentNode;
|
|
21
15
|
if (parent)
|
|
22
16
|
parent.removeChild(node);
|
|
23
17
|
}
|
|
24
|
-
export const setNodeChildren = (
|
|
18
|
+
export const setNodeChildren = (parent/*: Node*/, children/*: RenderResult<Node>[]*/) => {
|
|
25
19
|
const childrenToAttach = children.filter(r => !r.commit.suspension).map(r => r.node);
|
|
26
20
|
const childrenToRemove = children.filter(r => r.commit.suspension).map(r => r.node);
|
|
27
21
|
for (let i = 0; i < childrenToRemove.length; i++)
|
|
@@ -36,3 +30,25 @@ export const setNodeChildren = (diff/*: CommitDiff*/, parent/*: Node*/, children
|
|
|
36
30
|
}
|
|
37
31
|
}
|
|
38
32
|
}
|
|
33
|
+
|
|
34
|
+
export const setNodeChildren2 = (parent/*: Node*/, children/*: Node[]*/) => {
|
|
35
|
+
const parentNodeLength = parent.childNodes.length;
|
|
36
|
+
const parentNodes = [...parent.childNodes];
|
|
37
|
+
|
|
38
|
+
for (let i = 0; i < parentNodeLength; i++) {
|
|
39
|
+
if (!children.includes(parentNodes[i]))
|
|
40
|
+
parent.removeChild(parentNodes[i]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
for (let i = 0; i < children.length; i++) {
|
|
44
|
+
const prevChild = parent.childNodes[i] || null;
|
|
45
|
+
const nextChild = children[i] || null;
|
|
46
|
+
|
|
47
|
+
if (prevChild !== nextChild) {
|
|
48
|
+
if (!prevChild)
|
|
49
|
+
parent.appendChild(nextChild)
|
|
50
|
+
else
|
|
51
|
+
parent.replaceChild(nextChild, prevChild);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"main": "entry.js",
|
|
4
4
|
"types": "entry.d.ts",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"version": "2.1
|
|
6
|
+
"version": "2.2.1",
|
|
7
7
|
"sideEffects": false,
|
|
8
8
|
"scripts": {
|
|
9
9
|
"test": "cd ../..; npm test",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@lukekaalim/act-renderer-core": "^3.2.2",
|
|
15
|
-
"@lukekaalim/act-reconciler": "^3.0
|
|
15
|
+
"@lukekaalim/act-reconciler": "^3.1.0"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@lukekaalim/act": "*"
|
package/prop.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
// @flow strict
|
|
2
|
-
/*::
|
|
3
|
-
import {
|
|
2
|
+
/*::
|
|
3
|
+
import type { Commit3 } from "../../reconciler/commit3";
|
|
4
|
+
import type { Diff3, DiffSet } from "../../reconciler/diff";
|
|
5
|
+
import type { CommitDiff } from '@lukekaalim/act-reconciler';
|
|
6
|
+
import type { PropDiff, PropDiffRegistry } from '@lukekaalim/act-renderer-core';
|
|
7
|
+
*/
|
|
8
|
+
import { calculatePropsDiff } from '@lukekaalim/act-renderer-core'
|
|
4
9
|
|
|
5
10
|
const propBlacklist = new Set(['ref', 'key', 'children']);
|
|
6
11
|
|
|
@@ -12,9 +17,9 @@ export const setStylesProp = (
|
|
|
12
17
|
const prevRules = typeof prev === 'object' && prev || {};
|
|
13
18
|
const nextRules = typeof next === 'object' && next || {};
|
|
14
19
|
|
|
15
|
-
const
|
|
20
|
+
const reg = calculatePropsDiff(prevRules, nextRules);
|
|
16
21
|
|
|
17
|
-
for (const [rule, { next }] of
|
|
22
|
+
for (const [rule, { next }] of reg.map) {
|
|
18
23
|
const nextRuleValue = (typeof next === 'string' || typeof next === 'number') ? next : null;
|
|
19
24
|
if (typeof (style/*: any*/)[rule] !== 'undefined')
|
|
20
25
|
(style/*: any*/)[rule] = nextRuleValue;
|
|
@@ -93,18 +98,17 @@ export const setHTMLProp = (
|
|
|
93
98
|
|
|
94
99
|
export const setHTMLProps = (
|
|
95
100
|
element/*: HTMLElement | SVGElement*/,
|
|
96
|
-
|
|
101
|
+
registry/*: PropDiffRegistry*/
|
|
97
102
|
) => {
|
|
98
|
-
const
|
|
99
|
-
for (const [_, propDiff] of propDiffs)
|
|
103
|
+
for (const [_, propDiff] of registry.map)
|
|
100
104
|
setHTMLProp(element, propDiff);
|
|
101
105
|
};
|
|
102
106
|
|
|
103
107
|
export const setTextProps = (
|
|
104
108
|
element/*: Text*/,
|
|
105
|
-
|
|
109
|
+
registry/*: PropDiffRegistry*/
|
|
106
110
|
) => {
|
|
107
|
-
const
|
|
111
|
+
const content = registry.prop('content', '').next;
|
|
108
112
|
if (content !== element.textContent)
|
|
109
113
|
element.textContent = typeof content === 'string' ? content : '';
|
|
110
114
|
};
|
|
@@ -113,12 +117,26 @@ export const setProps = (
|
|
|
113
117
|
element/*: ?Node*/,
|
|
114
118
|
diff/*: CommitDiff*/
|
|
115
119
|
) => {
|
|
120
|
+
const propDiff = calculatePropsDiff(diff.prev.element.props, diff.next.element.props);
|
|
116
121
|
if (element instanceof HTMLElement || element instanceof SVGElement)
|
|
117
|
-
setHTMLProps(element,
|
|
122
|
+
setHTMLProps(element, propDiff);
|
|
118
123
|
if (element instanceof Text)
|
|
119
|
-
setTextProps(element,
|
|
124
|
+
setTextProps(element, propDiff);
|
|
120
125
|
};
|
|
121
126
|
|
|
127
|
+
export const setWebProps2 = (
|
|
128
|
+
element/*: Node*/,
|
|
129
|
+
set/*: DiffSet*/,
|
|
130
|
+
diff/*: Diff3*/,
|
|
131
|
+
) => {
|
|
132
|
+
const prev = set.prevs.map.get(diff.commit.id);
|
|
133
|
+
const propDiff = calculatePropsDiff(prev ? prev.element.props : {}, diff.commit.element.props);
|
|
134
|
+
if (element instanceof HTMLElement || element instanceof SVGElement)
|
|
135
|
+
setHTMLProps(element, propDiff);
|
|
136
|
+
if (element instanceof Text)
|
|
137
|
+
setTextProps(element, propDiff);
|
|
138
|
+
}
|
|
139
|
+
|
|
122
140
|
export const setRef = (
|
|
123
141
|
node/*: ?Node*/,
|
|
124
142
|
diff/*: CommitDiff*/
|
|
@@ -135,4 +153,4 @@ export const setRef = (
|
|
|
135
153
|
else if (diff.next.pruned)
|
|
136
154
|
ref['current'] = null;
|
|
137
155
|
}
|
|
138
|
-
};
|
|
156
|
+
};
|
package/reconciler.js
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
/*:: import type { Element } from '@lukekaalim/act'; */
|
|
3
|
-
import { createTree } from '@lukekaalim/act-reconciler';
|
|
3
|
+
import { createBoundaryService, createEffectService, createReconciler, createSchedule2, createTree, createTreeService2 } from '@lukekaalim/act-reconciler';
|
|
4
4
|
import { createWebRenderer } from './renderer.js';
|
|
5
|
-
import {
|
|
5
|
+
import { setNodeChildren2 } from "./node.js";
|
|
6
6
|
|
|
7
7
|
export const render = (element/*: Element*/, node/*: HTMLElement*/) => {
|
|
8
8
|
const web = createWebRenderer();
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
cancelWork: (t) => cancelAnimationFrame(t),
|
|
9
|
+
|
|
10
|
+
const onScheduleRequest = (callback) => {
|
|
11
|
+
const id = requestAnimationFrame(() => callback(16));
|
|
12
|
+
return () => cancelAnimationFrame(id);
|
|
14
13
|
};
|
|
15
|
-
|
|
14
|
+
const scheduler = createSchedule2(onScheduleRequest)
|
|
15
|
+
const effect = createEffectService(scheduler);
|
|
16
|
+
const boundary = createBoundaryService();
|
|
17
|
+
const reconciler = createReconciler(scheduler);
|
|
18
|
+
|
|
19
|
+
reconciler.diff.subscribeDiff((set) => {
|
|
20
|
+
setNodeChildren2(node, web.render(set, set.root));
|
|
21
|
+
reconciler.tree.live.registry = effect.runEffectRegistry(set.registry);
|
|
22
|
+
|
|
23
|
+
const map = boundary.calcBoundaryMap(set);
|
|
24
|
+
boundary.getRootBoundaryValue(set.suspensions, set, map);
|
|
25
|
+
});
|
|
26
|
+
reconciler.tree.mount(element);
|
|
16
27
|
};
|
package/renderer.js
CHANGED
|
@@ -2,80 +2,75 @@
|
|
|
2
2
|
/*::
|
|
3
3
|
import type { ElementType } from '@lukekaalim/act';
|
|
4
4
|
import type { CommitDiff, Commit } from '@lukekaalim/act-reconciler';
|
|
5
|
+
import type { Renderer2 } from "../core/renderer2";
|
|
5
6
|
*/
|
|
6
7
|
/*:: import type { Renderer, RenderResult } from '@lukekaalim/act-renderer-core'; */
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { setProps, setRef, setWebProps2 } from './prop.js';
|
|
9
|
+
import { createNode, removeNode, setNodeChildren, setNodeChildren2 } from './node.js';
|
|
10
|
+
import { createRenderer2, setRef2 } from '@lukekaalim/act-renderer-core';
|
|
10
11
|
|
|
11
12
|
export const createDOMRenderer = (
|
|
12
13
|
namespace/*: string*/,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
const node = createNode(diff.next.element, namespace);
|
|
18
|
-
if (node !== null) {
|
|
19
|
-
const parentId = diff.next.path[diff.next.path.length - 1];
|
|
20
|
-
nodeRenderer.nodesByCommitID.get(parentId);
|
|
21
|
-
}
|
|
22
|
-
return node;
|
|
14
|
+
getNextRenderer/*: null | (ElementType => null | Renderer2<Node>)*/ = null,
|
|
15
|
+
)/*: Renderer2<Node>*/ => {
|
|
16
|
+
const create = (type) => {
|
|
17
|
+
return createNode(type, namespace);
|
|
23
18
|
}
|
|
24
|
-
const remove = (node) => {
|
|
19
|
+
const remove = (node, children, diff) => {
|
|
20
|
+
setRef2(node, diff.commit, diff.change);
|
|
25
21
|
removeNode(node);
|
|
26
22
|
};
|
|
27
|
-
const update = (node,
|
|
28
|
-
|
|
23
|
+
const update = (node, set, diff) => {
|
|
24
|
+
if (diff.change.type === 'create')
|
|
25
|
+
setRef2(node, diff.commit, diff.change);
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
setWebProps2(node, set, diff);
|
|
28
|
+
}
|
|
29
|
+
const attach = (node, set, diff, children) => {
|
|
30
|
+
if (diff.commit.element.props["ignoreChildren"])
|
|
31
31
|
return;
|
|
32
|
+
setNodeChildren2(node, children);
|
|
33
|
+
}
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
const getRenderer = (set, commitId) => {
|
|
36
|
+
const commit = set.nexts.get(commitId);
|
|
37
|
+
return getNextRenderer && getNextRenderer(commit.element.type) || nodeRenderer;
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
return null;
|
|
40
|
+
const getNodes = (set, commitId) => {
|
|
41
|
+
const renderer = getRenderer(set, commitId)
|
|
42
|
+
return renderer.getNodes(set, commitId);
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
return nodeRenderer.render(diff);
|
|
45
|
+
const render = (set, commitId) => {
|
|
46
|
+
const renderer = getRenderer(set, commitId)
|
|
47
|
+
return renderer.render(set, commitId);
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
const nodeRenderer =
|
|
50
|
+
const nodeRenderer = createRenderer2({
|
|
51
|
+
create,
|
|
52
|
+
update,
|
|
53
|
+
remove,
|
|
54
|
+
attach,
|
|
55
|
+
}, {
|
|
56
|
+
getNodes,
|
|
57
|
+
render,
|
|
58
|
+
});
|
|
52
59
|
|
|
53
60
|
return nodeRenderer;
|
|
54
61
|
};
|
|
55
62
|
|
|
56
63
|
export const createWebRenderer = (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
)/*: Renderer<Node>*/ => {
|
|
64
|
+
getNextRenderer/*: null | (ElementType => null | Renderer2<Node>)*/ = null,
|
|
65
|
+
)/*: Renderer2<Node>*/ => {
|
|
60
66
|
const svgRenderer = createDOMRenderer('http://www.w3.org/2000/svg')
|
|
61
67
|
|
|
62
|
-
const htmlRenderer = createDOMRenderer('http://www.w3.org/1999/xhtml',
|
|
63
|
-
switch (
|
|
64
|
-
case 'svg':
|
|
65
|
-
return svgRenderer.render(diff);
|
|
66
|
-
default:
|
|
67
|
-
if (nextDOMNode)
|
|
68
|
-
return nextDOMNode(diff);
|
|
69
|
-
return htmlRenderer.render(diff)
|
|
70
|
-
}
|
|
71
|
-
}, commit => {
|
|
72
|
-
switch (commit.element.type) {
|
|
68
|
+
const htmlRenderer = createDOMRenderer('http://www.w3.org/1999/xhtml', type => {
|
|
69
|
+
switch (type) {
|
|
73
70
|
case 'svg':
|
|
74
|
-
return svgRenderer
|
|
71
|
+
return svgRenderer;
|
|
75
72
|
default:
|
|
76
|
-
|
|
77
|
-
return getExternalDOMNode(commit);
|
|
78
|
-
return null;
|
|
73
|
+
return getNextRenderer && getNextRenderer(type);
|
|
79
74
|
}
|
|
80
75
|
});
|
|
81
76
|
|