1 | import options from './options';
|
2 |
|
3 | /**
|
4 | * Create an virtual node (used for JSX)
|
5 | * @param {import('./internal').VNode["type"]} type The node name or Component
|
6 | * constructor for this virtual node
|
7 | * @param {object | null | undefined} [props] The properties of the virtual node
|
8 | * @param {Array<import('.').ComponentChildren>} [children] The children of the virtual node
|
9 | * @returns {import('./internal').VNode}
|
10 | */
|
11 | export function createElement(type, props, children) {
|
12 | let normalizedProps = {},
|
13 | key,
|
14 | ref,
|
15 | i;
|
16 | for (i in props) {
|
17 | if (i == 'key') key = props[i];
|
18 | else if (i == 'ref') ref = props[i];
|
19 | else normalizedProps[i] = props[i];
|
20 | }
|
21 |
|
22 | if (arguments.length > 3) {
|
23 | children = [children];
|
24 | // https://github.com/preactjs/preact/issues/1916
|
25 | for (i = 3; i < arguments.length; i++) {
|
26 | children.push(arguments[i]);
|
27 | }
|
28 | }
|
29 | if (children != null) {
|
30 | normalizedProps.children = children;
|
31 | }
|
32 |
|
33 | // If a Component VNode, check for and apply defaultProps
|
34 | // Note: type may be undefined in development, must never error here.
|
35 | if (typeof type == 'function' && type.defaultProps != null) {
|
36 | for (i in type.defaultProps) {
|
37 | if (normalizedProps[i] === undefined) {
|
38 | normalizedProps[i] = type.defaultProps[i];
|
39 | }
|
40 | }
|
41 | }
|
42 |
|
43 | return createVNode(type, normalizedProps, key, ref, null);
|
44 | }
|
45 |
|
46 | /**
|
47 | * Create a VNode (used internally by Preact)
|
48 | * @param {import('./internal').VNode["type"]} type The node name or Component
|
49 | * Constructor for this virtual node
|
50 | * @param {object | string | number | null} props The properties of this virtual node.
|
51 | * If this virtual node represents a text node, this is the text of the node (string or number).
|
52 | * @param {string | number | null} key The key for this virtual node, used when
|
53 | * diffing it against its children
|
54 | * @param {import('./internal').VNode["ref"]} ref The ref property that will
|
55 | * receive a reference to its created child
|
56 | * @returns {import('./internal').VNode}
|
57 | */
|
58 | export function createVNode(type, props, key, ref, original) {
|
59 | // V8 seems to be better at detecting type shapes if the object is allocated from the same call site
|
60 | // Do not inline into createElement and coerceToVNode!
|
61 | const vnode = {
|
62 | type,
|
63 | props,
|
64 | key,
|
65 | ref,
|
66 | _children: null,
|
67 | _parent: null,
|
68 | _depth: 0,
|
69 | _dom: null,
|
70 | // _nextDom must be initialized to undefined b/c it will eventually
|
71 | // be set to dom.nextSibling which can return `null` and it is important
|
72 | // to be able to distinguish between an uninitialized _nextDom and
|
73 | // a _nextDom that has been set to `null`
|
74 | _nextDom: undefined,
|
75 | _component: null,
|
76 | constructor: undefined,
|
77 | _original: original
|
78 | };
|
79 |
|
80 | if (original == null) vnode._original = vnode;
|
81 | if (options.vnode != null) options.vnode(vnode);
|
82 |
|
83 | return vnode;
|
84 | }
|
85 |
|
86 | export function createRef() {
|
87 | return { current: null };
|
88 | }
|
89 |
|
90 | export function Fragment(props) {
|
91 | return props.children;
|
92 | }
|
93 |
|
94 | /**
|
95 | * Check if a the argument is a valid Preact VNode.
|
96 | * @param {*} vnode
|
97 | * @returns {vnode is import('./internal').VNode}
|
98 | */
|
99 | export const isValidElement = vnode =>
|
100 | vnode != null && vnode.constructor === undefined;
|