vaderjs 1.4.1-lv56aadeg5 → 1.4.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/.editorconfig +11 -0
- package/.vscode/c_cpp_properties.json +21 -0
- package/.vscode/settings.json +12 -0
- package/README.md +35 -198
- package/binaries/Kalix/index.js +665 -0
- package/binaries/compiler/main.js +461 -0
- package/binaries/vader.js +74 -0
- package/binaries/watcher/hmr.js +36 -0
- package/client/index.d.ts +226 -0
- package/client/runtime/index.js +417 -0
- package/client/runtime/router.js +235 -0
- package/config/index.ts +68 -0
- package/index.ts +344 -0
- package/package.json +14 -25
- package/plugins/cloudflare/functions/index.js +98 -0
- package/plugins/cloudflare/toCopy/@server/Kalix/index.js +625 -0
- package/plugins/cloudflare/toCopy/@server/cloudflare_ssr/index.js +85 -0
- package/plugins/cloudflare/toCopy/node_modules/vaderjs/server/index.js +99 -0
- package/plugins/cloudflare/toCopy/src/client.js +432 -0
- package/plugins/cloudflare/toCopy/src/router.js +235 -0
- package/plugins/ssg/index.js +124 -0
- package/plugins/vercel/functions/index.ts +8 -0
- package/router/index.ts +181 -0
- package/server/index.js +129 -0
- package/vader.js +59 -112
- package/@integrations/ssg.js +0 -163
- package/LICENSE +0 -21
- package/binaries/IPC/index.js +0 -277
- package/binaries/main.js +0 -1328
- package/binaries/readme.md +0 -4
- package/binaries/watcher.js +0 -74
- package/binaries/win32/check.ps1 +0 -7
- package/client/index.js +0 -441
- package/config/index.js +0 -36
- package/logo.png +0 -0
- package/runtime/router.js +0 -1
- package/runtime/vader.js +0 -1
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
declare namespace Vader{
|
|
3
|
+
export let useState: <T>(initialState: T) => [T, (newState: T) => void];
|
|
4
|
+
export let useReducer: <T>(reducer: (state: T, action: any) => T, initialState: T) => [T, (newState: T) => void];
|
|
5
|
+
export const useRef: <T>(initialValue: T | null) => { current: T | null };
|
|
6
|
+
export const Mounted: (fn: () => void) => void;
|
|
7
|
+
}
|
|
8
|
+
declare global {
|
|
9
|
+
/**
|
|
10
|
+
* @type {boolean}
|
|
11
|
+
* @description A boolean value that returns true if the current environment is a server
|
|
12
|
+
*/
|
|
13
|
+
const isServer: boolean
|
|
14
|
+
/**
|
|
15
|
+
* @type {boolean}
|
|
16
|
+
* @description Default(true) - A boolean value that lets you opt out of prerendering (Only applies towards using the vaderjs serverside )
|
|
17
|
+
*/
|
|
18
|
+
var preRender: boolean
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @description HTMLTextNode is a global interface that represents a text node
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
interface HTMLTextNode {
|
|
26
|
+
nodeValue: string;
|
|
27
|
+
nodeType: number;
|
|
28
|
+
tagName: string;
|
|
29
|
+
props:{nodeValue: string};
|
|
30
|
+
toString: () => string;
|
|
31
|
+
insertBefore: (child: HTMLTextNode, ref: HTMLTextNode) => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @description HTMLElement is a global interface that represents an HTML element
|
|
35
|
+
*/
|
|
36
|
+
interface HTMLElement{
|
|
37
|
+
tagName: string;
|
|
38
|
+
id: string;
|
|
39
|
+
nodeType: number;
|
|
40
|
+
classList:{
|
|
41
|
+
add: (className: string) => void;
|
|
42
|
+
remove: (className: string) => void;
|
|
43
|
+
toggle: (className: string) => void;
|
|
44
|
+
contains: (className: string) => boolean;
|
|
45
|
+
}
|
|
46
|
+
props: {
|
|
47
|
+
[key: string]: string;
|
|
48
|
+
}
|
|
49
|
+
children: HTMLElement[];
|
|
50
|
+
outerHTML: string;
|
|
51
|
+
innerHTML: string;
|
|
52
|
+
textContent: string;
|
|
53
|
+
firstChild: HTMLElement | HTMLTextNode | null;
|
|
54
|
+
style?: {
|
|
55
|
+
|
|
56
|
+
display: string;
|
|
57
|
+
position: string;
|
|
58
|
+
top: string;
|
|
59
|
+
left: string;
|
|
60
|
+
right: string;
|
|
61
|
+
bottom: string;
|
|
62
|
+
width: string;
|
|
63
|
+
height: string;
|
|
64
|
+
maxWidth: string;
|
|
65
|
+
maxHeight: string;
|
|
66
|
+
minWidth: string;
|
|
67
|
+
minHeight: string;
|
|
68
|
+
margin: string;
|
|
69
|
+
marginTop: string;
|
|
70
|
+
marginRight: string;
|
|
71
|
+
marginBottom: string;
|
|
72
|
+
marginLeft: string;
|
|
73
|
+
padding: string;
|
|
74
|
+
paddingTop: string;
|
|
75
|
+
paddingRight: string;
|
|
76
|
+
paddingBottom: string;
|
|
77
|
+
paddingLeft: string;
|
|
78
|
+
overflow: string;
|
|
79
|
+
zIndex: string;
|
|
80
|
+
cursor: string;
|
|
81
|
+
textAlign: string;
|
|
82
|
+
fontSize: string;
|
|
83
|
+
fontWeight: string;
|
|
84
|
+
fontStyle: string;
|
|
85
|
+
textDecoration: string;
|
|
86
|
+
lineHeight: string;
|
|
87
|
+
letterSpacing: string;
|
|
88
|
+
textTransform: string;
|
|
89
|
+
backgroundColor: string;
|
|
90
|
+
backgroundImage: string;
|
|
91
|
+
backgroundSize: string;
|
|
92
|
+
backgroundPosition: string;
|
|
93
|
+
backgroundRepeat: string;
|
|
94
|
+
backgroundAttachment: string;
|
|
95
|
+
backgroundClip: string;
|
|
96
|
+
backgroundOrigin: string;
|
|
97
|
+
backgroundBlendMode: string;
|
|
98
|
+
boxShadow: string;
|
|
99
|
+
transition: string;
|
|
100
|
+
transform: string;
|
|
101
|
+
transformOrigin: string;
|
|
102
|
+
transformStyle: string;
|
|
103
|
+
perspective: string;
|
|
104
|
+
perspectiveOrigin: string;
|
|
105
|
+
backfaceVisibility: string;
|
|
106
|
+
filter: string;
|
|
107
|
+
backdropFilter: string;
|
|
108
|
+
mixBlendMode: string;
|
|
109
|
+
border: string;
|
|
110
|
+
borderTop: string;
|
|
111
|
+
borderRight: string;
|
|
112
|
+
borderBottom: string;
|
|
113
|
+
borderLeft: string;
|
|
114
|
+
borderStyle: string;
|
|
115
|
+
borderTopStyle: string;
|
|
116
|
+
borderRightStyle: string;
|
|
117
|
+
borderBottomStyle: string;
|
|
118
|
+
borderLeftStyle: string;
|
|
119
|
+
borderColor: string;
|
|
120
|
+
borderTopColor: string;
|
|
121
|
+
borderRightColor: string;
|
|
122
|
+
borderBottomColor: string;
|
|
123
|
+
borderLeftColor: string;
|
|
124
|
+
borderRadius: string;
|
|
125
|
+
borderTopLeftRadius: string;
|
|
126
|
+
borderTopRightRadius: string;
|
|
127
|
+
borderBottomRightRadius: string;
|
|
128
|
+
borderBottomLeftRadius: string;
|
|
129
|
+
borderWidth: string;
|
|
130
|
+
borderTopWidth: string;
|
|
131
|
+
borderRightWidth: string;
|
|
132
|
+
borderBottomWidth: string;
|
|
133
|
+
borderLeftWidth: string;
|
|
134
|
+
|
|
135
|
+
[key: string]: string;
|
|
136
|
+
}
|
|
137
|
+
attributes: {
|
|
138
|
+
[key: string]: string;
|
|
139
|
+
};
|
|
140
|
+
events: [];
|
|
141
|
+
toString: () => string;
|
|
142
|
+
getAttribute: (attr: string) => string | null;
|
|
143
|
+
appendChild: (child: HTMLElement) => void;
|
|
144
|
+
prepend: (child: HTMLElement) => void;
|
|
145
|
+
append: (...child: HTMLElement[]) => void;
|
|
146
|
+
insertBefore: (node1: HTMLElement, node2: HTMLElement) => void;
|
|
147
|
+
removeChild: (child: HTMLElement) => void;
|
|
148
|
+
querySelector: (selector: string) => HTMLElement | null;
|
|
149
|
+
querySelectorAll: (selector: string) => HTMLElement[];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
interface LastModified {
|
|
153
|
+
date: string;
|
|
154
|
+
time: string;
|
|
155
|
+
parsed: string;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* @type {Object}
|
|
159
|
+
* @description The file object
|
|
160
|
+
* @property {string} name - The name of the file
|
|
161
|
+
* @property {string} filetype - The type of the file
|
|
162
|
+
* @property {string} dataUrl - The data url of the file
|
|
163
|
+
* @property {string} text - The text content of the file
|
|
164
|
+
* @property {string} fileUrl - The file url
|
|
165
|
+
* @property {number} filesize - The file size
|
|
166
|
+
* @property {Blob} blob - The file blob
|
|
167
|
+
* @property {LastModified} lastModified - The last modified date
|
|
168
|
+
* @property {string} mimetype - The file mimetype
|
|
169
|
+
*/
|
|
170
|
+
interface File {
|
|
171
|
+
name: string;
|
|
172
|
+
filetype: string;
|
|
173
|
+
dataUrl: string;
|
|
174
|
+
fileUrl: string;
|
|
175
|
+
filesize: number;
|
|
176
|
+
lastModified: LastModified;
|
|
177
|
+
mimetype: string;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* @description Returns a stateful value, and a function to update it.
|
|
182
|
+
* @template T
|
|
183
|
+
* @param {T} initialState - The initial state value.
|
|
184
|
+
* @returns {[T, (newState: T) => void]} - A tuple containing the current state value and a function to update the state.
|
|
185
|
+
* @see https://react.dev/reference/react/useState
|
|
186
|
+
*/
|
|
187
|
+
|
|
188
|
+
declare const useState: <T>(initialState: T) => [T, (newState: T) => void];
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* An alternative to `useState`.
|
|
192
|
+
*
|
|
193
|
+
* `useReducer` is usually preferable to `useState` when you have complex state logic that involves
|
|
194
|
+
* multiple sub-values. It also lets you optimize performance for components that trigger deep
|
|
195
|
+
* updates because you can pass `dispatch` down instead of callbacks.
|
|
196
|
+
*
|
|
197
|
+
* @see https://react.dev/reference/react/useReducer
|
|
198
|
+
*/
|
|
199
|
+
|
|
200
|
+
declare const useReducer: <T>(reducer: (state: T, action: any) => T, initialState: T) => [T, (newState: T) => void];
|
|
201
|
+
/**
|
|
202
|
+
* `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument
|
|
203
|
+
* (`initialValue`). The returned object will persist for the full lifetime of the component.
|
|
204
|
+
*
|
|
205
|
+
* Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable
|
|
206
|
+
* value around similar to how you’d use instance fields in classes.
|
|
207
|
+
*
|
|
208
|
+
* @see https://react.dev/reference/react/useRef
|
|
209
|
+
*/
|
|
210
|
+
declare const useRef: <T>(initialValue: T | null) => {
|
|
211
|
+
current: T extends null ? HTMLElement : T;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Accepts a function that contains imperative, possibly effectful code.
|
|
216
|
+
*
|
|
217
|
+
* @param {Function} fn Imperative function that can be ran once the component is mounted - (does not apply when running on the server)
|
|
218
|
+
* @returns {void}
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
declare function Mounted(fn: Function): void;
|
|
222
|
+
export { useState, useReducer, useRef, useFile, Mounted, require }
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
window.vader = {
|
|
2
|
+
version: '1.0.0'
|
|
3
|
+
}
|
|
4
|
+
globalThis.isServer = false
|
|
5
|
+
window.hasRan = []
|
|
6
|
+
globalThis.memoizedFunctions = []
|
|
7
|
+
const memoizedRefs = []
|
|
8
|
+
/**
|
|
9
|
+
* @description This function is used to calculate the difference between two nodes - and return the elements in which the difference is found
|
|
10
|
+
* @param {HTMLElement} oldNode
|
|
11
|
+
* @param {HTMLElement} newNode
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
function calculateDiff(oldNode, newNode){
|
|
15
|
+
if(oldNode === undefined || newNode === undefined){
|
|
16
|
+
return []
|
|
17
|
+
}
|
|
18
|
+
let diff = []
|
|
19
|
+
if(oldNode?.children.length > 0){
|
|
20
|
+
for(var i = 0; i < oldNode.children.length; i++){
|
|
21
|
+
diff.push(...calculateDiff(oldNode.children[i], newNode.children[i]))
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
return diff
|
|
25
|
+
}
|
|
26
|
+
if(!oldNode?._isRoot){
|
|
27
|
+
if(oldNode.nodeType === 3 && oldNode.nodeValue !== newNode.nodeValue){
|
|
28
|
+
diff.push({type: 'REPLACE', oldNode, newNode})
|
|
29
|
+
}
|
|
30
|
+
else if(oldNode.nodeType === 1 && oldNode.innerHTML !== newNode.innerHTML
|
|
31
|
+
){
|
|
32
|
+
diff.push({type: 'REPLACE', oldNode, newNode})
|
|
33
|
+
}
|
|
34
|
+
else if(oldNode.nodeType === 1 && oldNode.tagName === newNode.tagName){
|
|
35
|
+
for(var i = 0; i < oldNode.attributes.length; i++){
|
|
36
|
+
if(oldNode.attributes[i].value !== newNode.attributes[i].value){
|
|
37
|
+
diff.push({type: 'PROPS', oldNode, newNode})
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
return diff
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @description This function is used to generate functonal components
|
|
50
|
+
* @param {Function} tag
|
|
51
|
+
* @param {Object} props
|
|
52
|
+
* @param {...any} children
|
|
53
|
+
* @returns {Object} - The first child of the functional component
|
|
54
|
+
*/
|
|
55
|
+
function generateJSX(tag, props, ...children){
|
|
56
|
+
let node = {
|
|
57
|
+
state: {},
|
|
58
|
+
mainFunction: tag,
|
|
59
|
+
_key: tag.name || Math.random().toString(36).substring(7),
|
|
60
|
+
$$typeof: 'JSX_CHILD',
|
|
61
|
+
firstChild:null,
|
|
62
|
+
children: children,
|
|
63
|
+
_name: tag.name,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
node.firstChild = tag()
|
|
67
|
+
node.firstChild.htmlNode._key = node._key
|
|
68
|
+
node.firstChild.htmlRoot = node
|
|
69
|
+
node.firstChild.htmlNode._isRoot = true
|
|
70
|
+
node.firstChild.props = props || {}
|
|
71
|
+
node.firstChild._isRoot = true
|
|
72
|
+
node.firstChild._key = node._key
|
|
73
|
+
node.firstChild.props['key'] = node._key
|
|
74
|
+
return node.firstChild
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
function handleStyles(styles, nodeEl) {
|
|
79
|
+
|
|
80
|
+
for (let key in styles) {
|
|
81
|
+
if(typeof styles[key] === 'object'){
|
|
82
|
+
handleStyles(styles[key], nodeEl)
|
|
83
|
+
}
|
|
84
|
+
nodeEl.style[key] = styles[key];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
let hasBeenCalled = []
|
|
91
|
+
/**
|
|
92
|
+
* @description Create a virtual DOM element
|
|
93
|
+
* @param {string | Function} tag
|
|
94
|
+
* @param {Object} props
|
|
95
|
+
* @param {...any} children
|
|
96
|
+
* @returns {Object} - The virtual DOM element
|
|
97
|
+
*/
|
|
98
|
+
function Element(tag, props, ...children){
|
|
99
|
+
!props ? props = {} : null
|
|
100
|
+
if(!props?.['$$key']){
|
|
101
|
+
props['$$key'] = tag.name || Math.random().toString(36).substring(7)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if(typeof tag === 'function'){
|
|
105
|
+
return generateJSX(tag, props, children)
|
|
106
|
+
}
|
|
107
|
+
let node = {
|
|
108
|
+
tag: tag,
|
|
109
|
+
props: props,
|
|
110
|
+
children: children,
|
|
111
|
+
_key: props['$$key'],
|
|
112
|
+
events: [],
|
|
113
|
+
staticEl: document.createElement(tag),
|
|
114
|
+
parentNode: null
|
|
115
|
+
}
|
|
116
|
+
for(var i = 0; i < children.length; i++){
|
|
117
|
+
if(typeof children[i] === 'string' || typeof children[i] === 'number'){
|
|
118
|
+
children[i] = {
|
|
119
|
+
tag: 'TEXT_ELEMENT',
|
|
120
|
+
props: {nodeValue: children[i]},
|
|
121
|
+
_key: props['$$key'],
|
|
122
|
+
parentNode: {tag: tag, props: props, children: children, _key: props['$$key']},
|
|
123
|
+
children: []
|
|
124
|
+
}
|
|
125
|
+
}else{
|
|
126
|
+
if(children[i]){
|
|
127
|
+
children[i].parentNode = {tag: tag, props: props, children: children}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
let nodeEl = node.tag === 'TEXT_ELEMENT' ? document.createTextNode('') : document.createElement(node.tag)
|
|
132
|
+
node.staticEl = nodeEl
|
|
133
|
+
|
|
134
|
+
for(var key in props){
|
|
135
|
+
if(key.toLowerCase().startsWith('on')){
|
|
136
|
+
nodeEl.addEventListener(key.substring(2).toLowerCase(), props[key])
|
|
137
|
+
node.events.push({type: key.substring(2).toLowerCase(), listener: props[key]})
|
|
138
|
+
continue
|
|
139
|
+
}
|
|
140
|
+
if(key === '$$key' && !nodeEl._key && nodeEl.nodeType === 1
|
|
141
|
+
){
|
|
142
|
+
Object.defineProperty(nodeEl, '_key', {
|
|
143
|
+
value: props[key],
|
|
144
|
+
writable: true
|
|
145
|
+
})
|
|
146
|
+
continue
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if(nodeEl && nodeEl.nodeType === 1){
|
|
150
|
+
nodeEl.setAttribute(key, props[key])
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
}
|
|
154
|
+
if(props.style){
|
|
155
|
+
handleStyles(props.style, nodeEl)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if(props.id){
|
|
159
|
+
nodeEl.id = props.id
|
|
160
|
+
}
|
|
161
|
+
if(props.ref){
|
|
162
|
+
switch(true){
|
|
163
|
+
case Array.isArray(props.ref.current):
|
|
164
|
+
if(!props.ref.current.find((el) => el === nodeEl)){
|
|
165
|
+
props.ref.current.push(nodeEl)
|
|
166
|
+
}
|
|
167
|
+
break;
|
|
168
|
+
case props.ref.current === HTMLElement:
|
|
169
|
+
props.ref.current = nodeEl
|
|
170
|
+
break;
|
|
171
|
+
case props.ref.current === null:
|
|
172
|
+
props.ref.current = nodeEl
|
|
173
|
+
break;
|
|
174
|
+
case typeof props.ref === 'function' && !window.hasRan.includes(props.ref):
|
|
175
|
+
window.hasRan.push(props.ref)
|
|
176
|
+
props.ref(nodeEl)
|
|
177
|
+
setTimeout(() => {
|
|
178
|
+
window.hasRan.filter((el) => el !== props.ref)
|
|
179
|
+
}, 0)
|
|
180
|
+
break;
|
|
181
|
+
default:
|
|
182
|
+
props.ref.current = nodeEl
|
|
183
|
+
break;
|
|
184
|
+
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
node['htmlNode'] = nodeEl
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
if(nodeEl.nodeType === 1){
|
|
191
|
+
for(var i = 0; i < children.length; i++){
|
|
192
|
+
if(children[i]){
|
|
193
|
+
if(children[i].tag === 'TEXT_ELEMENT'){
|
|
194
|
+
nodeEl.appendChild(document.createTextNode(children[i].props.nodeValue))
|
|
195
|
+
}
|
|
196
|
+
nodeEl.appendChild(Element(children[i].tag, children[i].props, ...children[i].children).htmlNode)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return node;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
function handleDiff(diff){
|
|
207
|
+
for(var i = 0; i < diff.length; i++){
|
|
208
|
+
switch(true){
|
|
209
|
+
case diff[i].type === 'REPLACE' && !diff[i].oldNode._isRoot:
|
|
210
|
+
let parent = diff[i].oldNode.parentNode
|
|
211
|
+
diff[i].oldNode.parentNode.replaceChild(diff[i].newNode, diff[i].oldNode)
|
|
212
|
+
break;
|
|
213
|
+
case diff[i].type === 'PROPS':
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
}
|
|
219
|
+
let states = {}
|
|
220
|
+
export const useState = (name, initialValue) => {}
|
|
221
|
+
export function useRef(name, initialValue){
|
|
222
|
+
let ref = initialValue
|
|
223
|
+
if(!memoizedRefs.find((el) => el.name === name)){
|
|
224
|
+
memoizedRefs.push({name, ref})
|
|
225
|
+
}
|
|
226
|
+
let getRef = () => memoizedRefs.find((el) => el.name === name).ref
|
|
227
|
+
let setRef = (newValue) => {
|
|
228
|
+
memoizedRefs.find((el) => el.name === name).ref = newValue
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
current: getRef(),
|
|
232
|
+
name,
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
export function Mounted(fn, node){
|
|
236
|
+
let el = Array.from(document.querySelectorAll('*')).find((el) => el._key === memoizedFunctions.find((el) => el.mainFunction === node)._key)
|
|
237
|
+
if(el && !hasBeenCalled.find((el) => el === node)){
|
|
238
|
+
fn()
|
|
239
|
+
hasBeenCalled.push(node)
|
|
240
|
+
}
|
|
241
|
+
else{
|
|
242
|
+
setTimeout(() => {
|
|
243
|
+
Mounted(fn, node)
|
|
244
|
+
}, 0)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
let effects = [];
|
|
250
|
+
|
|
251
|
+
export function useEffect(fn, deps){
|
|
252
|
+
if(!effects.find((el) => el.fn.toString() === fn.toString())){
|
|
253
|
+
effects.push({fn, deps})
|
|
254
|
+
}
|
|
255
|
+
else{
|
|
256
|
+
let effect = effects.find((el) => el.fn.toString() === fn.toString())
|
|
257
|
+
if(effect.deps.toString() !== deps.toString()){
|
|
258
|
+
effect.deps = deps
|
|
259
|
+
effect.fn()
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return () => {
|
|
263
|
+
effects = effects.filter((el) => el.fn !== fn)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
}
|
|
267
|
+
export function useReducer(name, reducer, vnode, initialState){
|
|
268
|
+
let [state, setState] = useState(name, vnode, initialState)
|
|
269
|
+
let dispatch = (action) => {
|
|
270
|
+
let newState = reducer(state, action)
|
|
271
|
+
setState(newState)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return [state, dispatch]
|
|
275
|
+
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
class Component {
|
|
279
|
+
constructor(props){
|
|
280
|
+
this.props = props
|
|
281
|
+
this._key = props['$$key'] || Math.random().toString(36).substring(7)
|
|
282
|
+
this.state = {}
|
|
283
|
+
this.htmlNode = null
|
|
284
|
+
this.firstChild = null
|
|
285
|
+
this.Element = Element
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
setState(newState){
|
|
290
|
+
this.state = newState
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
handleDiff(diff){
|
|
294
|
+
for(var i = 0; i < diff.length; i++){
|
|
295
|
+
switch(true){
|
|
296
|
+
case diff[i].type === 'REPLACE' && !diff[i].oldNode._isRoot:
|
|
297
|
+
let parent = diff[i].oldNode.parentNode
|
|
298
|
+
diff[i].oldNode.parentNode.replaceChild(diff[i].newNode, diff[i].oldNode)
|
|
299
|
+
break;
|
|
300
|
+
case diff[i].type === 'PROPS':
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
calculateDiff(oldNode, newNode){
|
|
306
|
+
if(oldNode === undefined || newNode === undefined){
|
|
307
|
+
return []
|
|
308
|
+
}
|
|
309
|
+
let diff = []
|
|
310
|
+
if(oldNode?.children.length > 0){
|
|
311
|
+
for(var i = 0; i < oldNode.children.length; i++){
|
|
312
|
+
diff.push(...this.calculateDiff(oldNode.children[i], newNode.children[i]))
|
|
313
|
+
|
|
314
|
+
}
|
|
315
|
+
return diff
|
|
316
|
+
}
|
|
317
|
+
if(!oldNode?._isRoot){
|
|
318
|
+
if(oldNode.nodeType === 3 && oldNode.nodeValue !== newNode.nodeValue){
|
|
319
|
+
diff.push({type: 'REPLACE', oldNode, newNode})
|
|
320
|
+
}
|
|
321
|
+
else if(oldNode.nodeType === 1 && oldNode.innerHTML !== newNode.innerHTML
|
|
322
|
+
){
|
|
323
|
+
diff.push({type: 'REPLACE', oldNode, newNode})
|
|
324
|
+
}
|
|
325
|
+
else if(oldNode.nodeType === 1 && oldNode.tagName === newNode.tagName){
|
|
326
|
+
for(var i = 0; i < oldNode.attributes.length; i++){
|
|
327
|
+
if(oldNode.attributes[i].value !== newNode.attributes[i].value){
|
|
328
|
+
diff.push({type: 'PROPS', oldNode, newNode})
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
return diff
|
|
337
|
+
}
|
|
338
|
+
useState(name, initialValue){
|
|
339
|
+
if(!this.state[name]){
|
|
340
|
+
this.state[name] = initialValue
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
let getState = () => this.state[name]
|
|
344
|
+
let setState = (newValue) => {
|
|
345
|
+
let dEl = this.firstChild.htmlNode
|
|
346
|
+
if(dEl.tagName === 'HTML'){
|
|
347
|
+
let firstChild = dEl.querySelector('body').firstChild
|
|
348
|
+
dEl = firstChild
|
|
349
|
+
}
|
|
350
|
+
this.state[name] = newValue
|
|
351
|
+
let el = Array.from(document.querySelectorAll('*')).find((el) =>{
|
|
352
|
+
return el._key === dEl._key
|
|
353
|
+
})
|
|
354
|
+
let diff = calculateDiff(el, this.render().htmlNode.tagName === 'HTML' ? this.render().htmlNode.querySelector('body').firstChild : this.render().htmlNode)
|
|
355
|
+
handleDiff(diff)
|
|
356
|
+
|
|
357
|
+
}
|
|
358
|
+
return [getState, setState]
|
|
359
|
+
|
|
360
|
+
}
|
|
361
|
+
useEffect = useEffect
|
|
362
|
+
useReducer(name, reducer, initialState){
|
|
363
|
+
let [state, setState] = this.useState(name, initialState)
|
|
364
|
+
let dispatch = (action) => {
|
|
365
|
+
let newState = reducer(state(), action)
|
|
366
|
+
setState(newState)
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return [state, dispatch]
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
render(){
|
|
373
|
+
return null
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export async function render(vnode, container, ...passProps){
|
|
379
|
+
|
|
380
|
+
if(!vnode){
|
|
381
|
+
throw new Error('No vnode was provided')
|
|
382
|
+
}
|
|
383
|
+
// create an object for the node then bind to firstChild
|
|
384
|
+
let comp = new Component({$$key: vnode.name || Math.random().toString(36).substring(7)})
|
|
385
|
+
vnode = vnode.bind(comp)
|
|
386
|
+
comp.render = () => {
|
|
387
|
+
return vnode(...passProps)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
comp.firstChild = comp.render()
|
|
391
|
+
|
|
392
|
+
if(comp.firstChild.htmlNode.tagName === 'HTML'){
|
|
393
|
+
let hasHead = comp.firstChild.htmlNode.querySelector('head') ? true : false
|
|
394
|
+
let hasBody = comp.firstChild.htmlNode.querySelector('body') ? true : false
|
|
395
|
+
|
|
396
|
+
if(hasHead){
|
|
397
|
+
document.head.innerHTML = comp.firstChild.htmlNode.querySelector('head').innerHTML
|
|
398
|
+
comp.firstChild.children = comp.firstChild.children.filter((el) =>{
|
|
399
|
+
return el.htmlNode.tagName !== 'HEAD'
|
|
400
|
+
})
|
|
401
|
+
}
|
|
402
|
+
if(hasBody){
|
|
403
|
+
comp.firstChild.children = comp.firstChild.children.filter((el) =>{
|
|
404
|
+
if(el.htmlNode.tagName == 'BODY'){
|
|
405
|
+
comp.firstChild = el.children[0]
|
|
406
|
+
}
|
|
407
|
+
})
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
container.innerHTML = ''
|
|
411
|
+
|
|
412
|
+
container.appendChild(comp.firstChild.htmlNode)
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export default Element
|