-
Notifications
You must be signed in to change notification settings - Fork 5
/
rcompat.mjs
73 lines (60 loc) · 1.76 KB
/
rcompat.mjs
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
68
69
70
71
72
73
// Optional adapters for migrating React-based apps to Prax.
import * as d from './dom.mjs'
/* Public API */
/*
Replaces `React.createElement`. Usage:
import * as x from 'prax'
import {R} from 'prax/rcompat.mjs'
export {F} from 'prax/rcompat.mjs'
export function E(...args) {return R(x.E, ...args)}
export function S(...args) {return R(x.S, ...args)}
*/
export function R(E, type, props, ...children) {
d.req(E, d.isFun)
props = dict(props)
try {
if (d.isFun(type)) {
propsToReact(props, children)
const pro = type.prototype
if (pro && d.isFun(pro.render)) return new type(props).render()
return type(props)
}
children = propsFromReact(props, children)
return E(type, props, ...children)
}
finally {
Object.freeze(props)
}
}
/*
Replaces `React.Fragment`. The calls should be auto-generated by a JSX/TSX
transpiler.
*/
export function F({children}) {return children}
/* Internal Utils */
function propsToReact(props, children) {
props.key = undefined
props.children = comb(trim(props.children), trim(children))
}
function propsFromReact(props, children) {
if (!props || !('children' in props)) return children
children = comb(props.children, children)
delete props.children
return children
}
// Imitates React's quirky "optimization" of children:
//
// [] -> null
// [a] -> a
// [a, b] -> [a, b]
//
// Only partially redundant with `vac`, which doesn't unwrap arrays.
function trim(children) {
if (d.isArr(children)) {
if (!children.length) return null
if (children.length === 1) return trim(children[0])
}
return children
}
function comb(a, b) {return d.isNil(a) ? b : (d.isNil(b) ? a : [a, b])}
function dict(val) {return d.isNil(val) ? Object.create(null) : d.req(val, d.isDict)}