@bromscandium/runtime 1.0.0 → 1.0.2
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/LICENSE +20 -20
- package/README.md +91 -91
- package/package.json +49 -49
- package/src/index.ts +56 -56
- package/src/jsx-runtime.ts +132 -132
- package/src/jsx.d.ts +373 -373
- package/src/lifecycle.ts +133 -133
- package/src/renderer.ts +655 -655
- package/src/vnode.ts +159 -159
package/src/vnode.ts
CHANGED
|
@@ -1,159 +1,159 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Virtual DOM node types and utilities.
|
|
3
|
-
* @module
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/** Symbol used to identify Fragment nodes (multiple children without a wrapper) */
|
|
7
|
-
export const Fragment = Symbol('Fragment');
|
|
8
|
-
|
|
9
|
-
/** Symbol used to identify Text nodes */
|
|
10
|
-
export const Text = Symbol('Text');
|
|
11
|
-
|
|
12
|
-
/** The type of a virtual node - can be a tag name, component function, or special symbol */
|
|
13
|
-
export type VNodeType = string | ComponentFunction | typeof Fragment | typeof Text;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* A virtual DOM node representing an element, component, or text.
|
|
17
|
-
*/
|
|
18
|
-
export interface VNode {
|
|
19
|
-
/** The type of node (tag name, component function, Fragment, or Text) */
|
|
20
|
-
type: VNodeType;
|
|
21
|
-
/** Properties/attributes passed to the node */
|
|
22
|
-
props: Record<string, any>;
|
|
23
|
-
/** Child nodes */
|
|
24
|
-
children: VNodeChild[];
|
|
25
|
-
/** Unique key for reconciliation optimization */
|
|
26
|
-
key?: string | number | null;
|
|
27
|
-
/** Reference to the actual DOM node after mounting */
|
|
28
|
-
el?: Node | null;
|
|
29
|
-
/** For component vnodes, the component instance */
|
|
30
|
-
component?: ComponentInstance | null;
|
|
31
|
-
/** For Fragment nodes, the anchor comment node */
|
|
32
|
-
anchor?: Node | null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** A valid child of a virtual node */
|
|
36
|
-
export type VNodeChild = VNode | string | number | boolean | null | undefined;
|
|
37
|
-
|
|
38
|
-
/** Children can be a single child or an array */
|
|
39
|
-
export type VNodeChildren = VNodeChild | VNodeChild[];
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* A component function that receives props and returns a virtual node tree.
|
|
43
|
-
*/
|
|
44
|
-
export interface ComponentFunction {
|
|
45
|
-
(props: Record<string, any>): VNode | null;
|
|
46
|
-
/** Optional display name for debugging */
|
|
47
|
-
displayName?: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Internal state for a mounted component instance.
|
|
52
|
-
*/
|
|
53
|
-
export interface ComponentInstance {
|
|
54
|
-
/** The virtual node representing this component */
|
|
55
|
-
vnode: VNode;
|
|
56
|
-
/** Current props passed to the component */
|
|
57
|
-
props: Record<string, any>;
|
|
58
|
-
/** The rendered subtree */
|
|
59
|
-
subTree: VNode | null;
|
|
60
|
-
/** Whether the component has been mounted to the DOM */
|
|
61
|
-
isMounted: boolean;
|
|
62
|
-
/** Function to trigger a re-render */
|
|
63
|
-
update: (() => void) | null;
|
|
64
|
-
/** Callbacks to invoke after mounting */
|
|
65
|
-
mounted: Array<() => void>;
|
|
66
|
-
/** Callbacks to invoke before unmounting */
|
|
67
|
-
unmounted: Array<() => void>;
|
|
68
|
-
/** Callbacks to invoke after updates */
|
|
69
|
-
updated: Array<() => void>;
|
|
70
|
-
/** Hook state storage for React-style hooks */
|
|
71
|
-
hooks: any[];
|
|
72
|
-
/** Current hook index during render */
|
|
73
|
-
hookIndex: number;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Creates a virtual DOM node.
|
|
78
|
-
*
|
|
79
|
-
* @param type - The node type (tag name, component, Fragment, or Text)
|
|
80
|
-
* @param props - Properties/attributes for the node
|
|
81
|
-
* @param children - Child nodes
|
|
82
|
-
* @returns A new virtual node
|
|
83
|
-
*
|
|
84
|
-
* @example
|
|
85
|
-
* ```ts
|
|
86
|
-
* const vnode = createVNode('div', { className: 'container' }, [
|
|
87
|
-
* createVNode('span', null, ['Hello']),
|
|
88
|
-
* createVNode('span', null, ['World'])
|
|
89
|
-
* ]);
|
|
90
|
-
* ```
|
|
91
|
-
*/
|
|
92
|
-
export function createVNode(
|
|
93
|
-
type: VNodeType,
|
|
94
|
-
props: Record<string, any> | null,
|
|
95
|
-
children: VNodeChildren = []
|
|
96
|
-
): VNode {
|
|
97
|
-
const normalizedChildren = normalizeChildren(children);
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
type,
|
|
101
|
-
props: props || {},
|
|
102
|
-
children: normalizedChildren,
|
|
103
|
-
key: props?.key ?? null,
|
|
104
|
-
el: null,
|
|
105
|
-
component: null,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Normalizes children into a flat array, filtering out invalid values.
|
|
111
|
-
* Handles nested arrays and removes nullish/boolean values from conditional rendering.
|
|
112
|
-
*
|
|
113
|
-
* @param children - The children to normalize
|
|
114
|
-
* @returns A flat array of valid children
|
|
115
|
-
*/
|
|
116
|
-
export function normalizeChildren(children: VNodeChildren): VNodeChild[] {
|
|
117
|
-
if (children == null) {
|
|
118
|
-
return [];
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (!Array.isArray(children)) {
|
|
122
|
-
children = [children];
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return children.flat(Infinity).filter(child => {
|
|
126
|
-
return child != null && child !== false && child !== true && child !== '';
|
|
127
|
-
}) as VNodeChild[];
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Creates a text virtual node.
|
|
132
|
-
*
|
|
133
|
-
* @param text - The text content
|
|
134
|
-
* @returns A virtual node representing text
|
|
135
|
-
*
|
|
136
|
-
* @example
|
|
137
|
-
* ```ts
|
|
138
|
-
* const textNode = createTextVNode('Hello, world!');
|
|
139
|
-
* ```
|
|
140
|
-
*/
|
|
141
|
-
export function createTextVNode(text: string | number): VNode {
|
|
142
|
-
return {
|
|
143
|
-
type: Text,
|
|
144
|
-
props: {},
|
|
145
|
-
children: [String(text)],
|
|
146
|
-
key: null,
|
|
147
|
-
el: null,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Checks if a value is a virtual node.
|
|
153
|
-
*
|
|
154
|
-
* @param value - The value to check
|
|
155
|
-
* @returns True if the value is a VNode
|
|
156
|
-
*/
|
|
157
|
-
export function isVNode(value: any): value is VNode {
|
|
158
|
-
return value != null && typeof value === 'object' && 'type' in value;
|
|
159
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Virtual DOM node types and utilities.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Symbol used to identify Fragment nodes (multiple children without a wrapper) */
|
|
7
|
+
export const Fragment = Symbol('Fragment');
|
|
8
|
+
|
|
9
|
+
/** Symbol used to identify Text nodes */
|
|
10
|
+
export const Text = Symbol('Text');
|
|
11
|
+
|
|
12
|
+
/** The type of a virtual node - can be a tag name, component function, or special symbol */
|
|
13
|
+
export type VNodeType = string | ComponentFunction | typeof Fragment | typeof Text;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A virtual DOM node representing an element, component, or text.
|
|
17
|
+
*/
|
|
18
|
+
export interface VNode {
|
|
19
|
+
/** The type of node (tag name, component function, Fragment, or Text) */
|
|
20
|
+
type: VNodeType;
|
|
21
|
+
/** Properties/attributes passed to the node */
|
|
22
|
+
props: Record<string, any>;
|
|
23
|
+
/** Child nodes */
|
|
24
|
+
children: VNodeChild[];
|
|
25
|
+
/** Unique key for reconciliation optimization */
|
|
26
|
+
key?: string | number | null;
|
|
27
|
+
/** Reference to the actual DOM node after mounting */
|
|
28
|
+
el?: Node | null;
|
|
29
|
+
/** For component vnodes, the component instance */
|
|
30
|
+
component?: ComponentInstance | null;
|
|
31
|
+
/** For Fragment nodes, the anchor comment node */
|
|
32
|
+
anchor?: Node | null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** A valid child of a virtual node */
|
|
36
|
+
export type VNodeChild = VNode | string | number | boolean | null | undefined;
|
|
37
|
+
|
|
38
|
+
/** Children can be a single child or an array */
|
|
39
|
+
export type VNodeChildren = VNodeChild | VNodeChild[];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A component function that receives props and returns a virtual node tree.
|
|
43
|
+
*/
|
|
44
|
+
export interface ComponentFunction {
|
|
45
|
+
(props: Record<string, any>): VNode | null;
|
|
46
|
+
/** Optional display name for debugging */
|
|
47
|
+
displayName?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Internal state for a mounted component instance.
|
|
52
|
+
*/
|
|
53
|
+
export interface ComponentInstance {
|
|
54
|
+
/** The virtual node representing this component */
|
|
55
|
+
vnode: VNode;
|
|
56
|
+
/** Current props passed to the component */
|
|
57
|
+
props: Record<string, any>;
|
|
58
|
+
/** The rendered subtree */
|
|
59
|
+
subTree: VNode | null;
|
|
60
|
+
/** Whether the component has been mounted to the DOM */
|
|
61
|
+
isMounted: boolean;
|
|
62
|
+
/** Function to trigger a re-render */
|
|
63
|
+
update: (() => void) | null;
|
|
64
|
+
/** Callbacks to invoke after mounting */
|
|
65
|
+
mounted: Array<() => void>;
|
|
66
|
+
/** Callbacks to invoke before unmounting */
|
|
67
|
+
unmounted: Array<() => void>;
|
|
68
|
+
/** Callbacks to invoke after updates */
|
|
69
|
+
updated: Array<() => void>;
|
|
70
|
+
/** Hook state storage for React-style hooks */
|
|
71
|
+
hooks: any[];
|
|
72
|
+
/** Current hook index during render */
|
|
73
|
+
hookIndex: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Creates a virtual DOM node.
|
|
78
|
+
*
|
|
79
|
+
* @param type - The node type (tag name, component, Fragment, or Text)
|
|
80
|
+
* @param props - Properties/attributes for the node
|
|
81
|
+
* @param children - Child nodes
|
|
82
|
+
* @returns A new virtual node
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* const vnode = createVNode('div', { className: 'container' }, [
|
|
87
|
+
* createVNode('span', null, ['Hello']),
|
|
88
|
+
* createVNode('span', null, ['World'])
|
|
89
|
+
* ]);
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export function createVNode(
|
|
93
|
+
type: VNodeType,
|
|
94
|
+
props: Record<string, any> | null,
|
|
95
|
+
children: VNodeChildren = []
|
|
96
|
+
): VNode {
|
|
97
|
+
const normalizedChildren = normalizeChildren(children);
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
type,
|
|
101
|
+
props: props || {},
|
|
102
|
+
children: normalizedChildren,
|
|
103
|
+
key: props?.key ?? null,
|
|
104
|
+
el: null,
|
|
105
|
+
component: null,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Normalizes children into a flat array, filtering out invalid values.
|
|
111
|
+
* Handles nested arrays and removes nullish/boolean values from conditional rendering.
|
|
112
|
+
*
|
|
113
|
+
* @param children - The children to normalize
|
|
114
|
+
* @returns A flat array of valid children
|
|
115
|
+
*/
|
|
116
|
+
export function normalizeChildren(children: VNodeChildren): VNodeChild[] {
|
|
117
|
+
if (children == null) {
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!Array.isArray(children)) {
|
|
122
|
+
children = [children];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return children.flat(Infinity).filter(child => {
|
|
126
|
+
return child != null && child !== false && child !== true && child !== '';
|
|
127
|
+
}) as VNodeChild[];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Creates a text virtual node.
|
|
132
|
+
*
|
|
133
|
+
* @param text - The text content
|
|
134
|
+
* @returns A virtual node representing text
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```ts
|
|
138
|
+
* const textNode = createTextVNode('Hello, world!');
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
export function createTextVNode(text: string | number): VNode {
|
|
142
|
+
return {
|
|
143
|
+
type: Text,
|
|
144
|
+
props: {},
|
|
145
|
+
children: [String(text)],
|
|
146
|
+
key: null,
|
|
147
|
+
el: null,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Checks if a value is a virtual node.
|
|
153
|
+
*
|
|
154
|
+
* @param value - The value to check
|
|
155
|
+
* @returns True if the value is a VNode
|
|
156
|
+
*/
|
|
157
|
+
export function isVNode(value: any): value is VNode {
|
|
158
|
+
return value != null && typeof value === 'object' && 'type' in value;
|
|
159
|
+
}
|