-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
67 lines (59 loc) · 1.7 KB
/
Copy pathindex.js
File metadata and controls
67 lines (59 loc) · 1.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
export { dom } from './packages/effects/dom.js'
export const compile = (nodes, getOptions) =>
nodes.reduce((acc, node) => {
if(Array.isArray(node)
&& typeof node[0] === 'function'
&& !node[0].name.endsWith('Effect'))
node = compile(
[ node[0](getOptions(node[1]), node[2]) ],
getOptions
)
return acc.concat(
Array.isArray(node)
? typeof node[0] === 'function'
? Array.isArray(node[2]) && node[2].length
? [ [node[0], node[1], compile([node[2]], getOptions)] ]
: [node]
: compile(node, getOptions)
: void 0
)
}, [])
// TODO: More efficient effects mapping algorithm?
export const patch = (prevTree, nextTree, context) => {
prevTree = prevTree.map((prev, idx) => {
const next = nextTree[idx]
return prev && (!next || prev[0] !== next[0])
? prev[3](context)
: prev
})
return nextTree.map((next, idx) => {
const prev = prevTree[idx]
if(next){
const cancel = next[0](prev, next,
(...args) => next[2] = patch(...args), context)
next.push((ctx) => {
patch(next[2], [], cancel(ctx))
})
}
return next
})
}
export const app = (src, state, ...helpers) => {
const options = helpers.reduce((prev, helper) =>
Object.assign(prev, helper), {})
let tree = []
src = [[src]]
return (function render(){
tree = patch(tree, compile(src, (props) =>
Object.assign(Object.create(options), {
useState: (getter, setter) => [
getter(state), (value) =>
render(state = setter(state, value))
],
useProps: () => props
})
))
return end =>
render(src = [[end]])
})()
}