@unsetsoft/ryunixjs 1.0.2 → 1.0.3-nightly.11
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/dist/Ryunix.js +137 -119
- package/package.json +2 -2
- package/src/lib/hooks.js +47 -42
- package/src/lib/reconciler.js +11 -6
- package/src/lib/render.js +28 -13
- package/dist/cj/Ryunix.js +0 -702
package/dist/Ryunix.js
CHANGED
|
@@ -108,13 +108,18 @@
|
|
|
108
108
|
};
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
|
-
*
|
|
112
|
-
* @
|
|
113
|
-
* container. It
|
|
114
|
-
* @param container - The container parameter is
|
|
115
|
-
*
|
|
111
|
+
* Renders an element into a container using a work-in-progress (WIP) root.
|
|
112
|
+
* @function render
|
|
113
|
+
* @param {Object|HTMLElement} element - The element to be rendered in the container. It can be a Ryunix component (custom element) or a standard DOM element.
|
|
114
|
+
* @param {HTMLElement} container - The container where the element will be rendered. This parameter is optional if `createRoot()` is used beforehand to set up the container.
|
|
115
|
+
* @description The function assigns the `container` to a work-in-progress root and sets up properties for reconciliation, including children and the reference to the current root.
|
|
116
|
+
* It also clears any scheduled deletions and establishes the next unit of work for incremental rendering.
|
|
116
117
|
*/
|
|
117
118
|
const render = (element, container) => {
|
|
119
|
+
if (vars.wipRoot && vars.wipRoot.dom) {
|
|
120
|
+
vars.wipRoot.container = container;
|
|
121
|
+
}
|
|
122
|
+
|
|
118
123
|
vars.wipRoot = {
|
|
119
124
|
dom: vars.containerRoot || container,
|
|
120
125
|
props: {
|
|
@@ -122,22 +127,95 @@
|
|
|
122
127
|
},
|
|
123
128
|
alternate: vars.currentRoot,
|
|
124
129
|
};
|
|
130
|
+
|
|
125
131
|
vars.deletions = [];
|
|
126
132
|
vars.nextUnitOfWork = vars.wipRoot;
|
|
127
133
|
};
|
|
128
134
|
|
|
129
135
|
/**
|
|
130
|
-
*
|
|
131
|
-
* @
|
|
132
|
-
* @param
|
|
133
|
-
* for the root element.
|
|
136
|
+
* Initializes the application by creating a reference to a DOM element with the specified ID and rendering the main component.
|
|
137
|
+
* @function init
|
|
138
|
+
* @param {Object} MainElement - The main component to render, typically the root component of the application.
|
|
139
|
+
* @param {string} [root='__ryunix'] - The ID of the HTML element that serves as the container for the root element. Defaults to `'__ryunix'` if not provided.
|
|
140
|
+
* @example
|
|
141
|
+
* Ryunix.init(App, "__ryunix"); // Initializes and renders the App component into the <div id="__ryunix"></div> element.
|
|
142
|
+
* @description This function retrieves the container element by its ID and invokes the `render` function to render the main component into it.
|
|
134
143
|
*/
|
|
135
|
-
const init = (root) => {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
144
|
+
const init = (MainElement, root = '__ryunix') => {
|
|
145
|
+
vars.containerRoot = document.getElementById(root);
|
|
146
|
+
|
|
147
|
+
render(MainElement, vars.containerRoot);
|
|
139
148
|
};
|
|
140
149
|
|
|
150
|
+
/**
|
|
151
|
+
* This function reconciles the children of a fiber node with a new set of elements, creating new
|
|
152
|
+
* fibers for new elements, updating existing fibers for elements with the same type, and marking old
|
|
153
|
+
* fibers for deletion if they are not present in the new set of elements.
|
|
154
|
+
* @param wipFiber - A work-in-progress fiber object representing a component or element in the virtual
|
|
155
|
+
* DOM tree.
|
|
156
|
+
* @param elements - an array of elements representing the new children to be rendered in the current
|
|
157
|
+
* fiber's subtree
|
|
158
|
+
*/
|
|
159
|
+
const reconcileChildren = (wipFiber, elements) => {
|
|
160
|
+
let index = 0;
|
|
161
|
+
let oldFiber = wipFiber.alternate && wipFiber.alternate.child;
|
|
162
|
+
let prevSibling;
|
|
163
|
+
|
|
164
|
+
// Recorre los nuevos elementos y los viejos para comparar
|
|
165
|
+
while (index < elements.length || oldFiber != undefined) {
|
|
166
|
+
const element = elements[index];
|
|
167
|
+
let newFiber;
|
|
168
|
+
|
|
169
|
+
// Verifica si el tipo de los elementos coincide
|
|
170
|
+
const sameType = oldFiber && element && element.type == oldFiber.type;
|
|
171
|
+
|
|
172
|
+
if (sameType) {
|
|
173
|
+
// Actualiza el nodo existente con nuevas propiedades
|
|
174
|
+
newFiber = {
|
|
175
|
+
type: oldFiber.type,
|
|
176
|
+
props: element.props,
|
|
177
|
+
dom: oldFiber.dom,
|
|
178
|
+
parent: wipFiber,
|
|
179
|
+
alternate: oldFiber,
|
|
180
|
+
effectTag: EFFECT_TAGS.UPDATE,
|
|
181
|
+
};
|
|
182
|
+
} else if (element) {
|
|
183
|
+
// Crea un nuevo nodo si el tipo es diferente
|
|
184
|
+
newFiber = {
|
|
185
|
+
type: element.type,
|
|
186
|
+
props: element.props,
|
|
187
|
+
dom: null,
|
|
188
|
+
parent: wipFiber,
|
|
189
|
+
alternate: null,
|
|
190
|
+
effectTag: EFFECT_TAGS.PLACEMENT,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (oldFiber && !sameType) {
|
|
195
|
+
oldFiber.effectTag = EFFECT_TAGS.DELETION;
|
|
196
|
+
vars.deletions.push(oldFiber);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (oldFiber) {
|
|
200
|
+
oldFiber = oldFiber.sibling;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (index === 0) {
|
|
204
|
+
wipFiber.child = newFiber;
|
|
205
|
+
} else if (element && prevSibling) {
|
|
206
|
+
prevSibling.sibling = newFiber;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
prevSibling = newFiber;
|
|
210
|
+
index++;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
var Reconciler = /*#__PURE__*/Object.freeze({
|
|
215
|
+
__proto__: null,
|
|
216
|
+
reconcileChildren: reconcileChildren
|
|
217
|
+
});
|
|
218
|
+
|
|
141
219
|
/**
|
|
142
220
|
* @description The function creates a state.
|
|
143
221
|
* @param initial - The initial value of the state for the hook.
|
|
@@ -221,36 +299,6 @@
|
|
|
221
299
|
}
|
|
222
300
|
};
|
|
223
301
|
|
|
224
|
-
/**
|
|
225
|
-
* The `useQuery` function is a custom hook in JavaScript that retrieves query parameters from the URL
|
|
226
|
-
* and stores them in a hook for easy access.
|
|
227
|
-
* @returns The `useQuery` function returns the `query` property of the `hook` object.
|
|
228
|
-
*/
|
|
229
|
-
const useQuery = () => {
|
|
230
|
-
const oldHook =
|
|
231
|
-
vars.wipFiber.alternate &&
|
|
232
|
-
vars.wipFiber.alternate.hooks &&
|
|
233
|
-
vars.wipFiber.alternate.hooks[vars.hookIndex];
|
|
234
|
-
|
|
235
|
-
const hasOld = oldHook ? oldHook : undefined;
|
|
236
|
-
|
|
237
|
-
const urlSearchParams = new URLSearchParams(window.location.search);
|
|
238
|
-
const params = Object.fromEntries(urlSearchParams.entries());
|
|
239
|
-
const Query = hasOld ? hasOld : params;
|
|
240
|
-
|
|
241
|
-
const hook = {
|
|
242
|
-
type: RYUNIX_TYPES.RYUNIX_URL_QUERY,
|
|
243
|
-
query: Query,
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
if (vars.wipFiber.hooks) {
|
|
247
|
-
vars.wipFiber.hooks.push(hook);
|
|
248
|
-
vars.hookIndex++;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return hook.query
|
|
252
|
-
};
|
|
253
|
-
|
|
254
302
|
const useRef = (initial) => {
|
|
255
303
|
const oldHook =
|
|
256
304
|
vars.wipFiber.alternate &&
|
|
@@ -303,27 +351,62 @@
|
|
|
303
351
|
return useMemo(() => callback, deps)
|
|
304
352
|
};
|
|
305
353
|
|
|
354
|
+
/**
|
|
355
|
+
* The `useQuery` function is a custom hook in JavaScript that retrieves query parameters from the URL
|
|
356
|
+
* and stores them in a hook for easy access.
|
|
357
|
+
* @returns The `useQuery` function returns the `query` property of the `hook` object.
|
|
358
|
+
*/
|
|
359
|
+
const useQuery = () => {
|
|
360
|
+
const oldHook =
|
|
361
|
+
vars.wipFiber.alternate &&
|
|
362
|
+
vars.wipFiber.alternate.hooks &&
|
|
363
|
+
vars.wipFiber.alternate.hooks[vars.hookIndex];
|
|
364
|
+
|
|
365
|
+
const hasOld = oldHook ? oldHook : undefined;
|
|
366
|
+
|
|
367
|
+
const urlSearchParams = new URLSearchParams(window.location.search);
|
|
368
|
+
const params = Object.fromEntries(urlSearchParams.entries());
|
|
369
|
+
const Query = hasOld ? hasOld : params;
|
|
370
|
+
|
|
371
|
+
const hook = {
|
|
372
|
+
type: RYUNIX_TYPES.RYUNIX_URL_QUERY,
|
|
373
|
+
query: Query,
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
if (vars.wipFiber.hooks) {
|
|
377
|
+
vars.wipFiber.hooks.push(hook);
|
|
378
|
+
vars.hookIndex++;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return hook.query
|
|
382
|
+
};
|
|
383
|
+
|
|
306
384
|
const useRouter = (routes) => {
|
|
307
385
|
const [location, setLocation] = useStore(window.location.pathname);
|
|
308
386
|
|
|
309
387
|
const navigate = (path) => {
|
|
310
|
-
window.
|
|
311
|
-
|
|
388
|
+
if (window.location.pathname !== path) {
|
|
389
|
+
window.history.pushState({}, '', path);
|
|
390
|
+
setLocation(path);
|
|
391
|
+
}
|
|
312
392
|
};
|
|
313
393
|
|
|
314
394
|
useEffect(() => {
|
|
315
|
-
const onPopState = () =>
|
|
316
|
-
setLocation(window.location.pathname);
|
|
317
|
-
};
|
|
318
|
-
|
|
395
|
+
const onPopState = () => setLocation(window.location.pathname);
|
|
319
396
|
window.addEventListener('popstate', onPopState);
|
|
320
|
-
return () =>
|
|
321
|
-
window.removeEventListener('popstate', onPopState);
|
|
322
|
-
}
|
|
397
|
+
return () => window.removeEventListener('popstate', onPopState)
|
|
323
398
|
}, []);
|
|
324
399
|
|
|
325
|
-
const
|
|
326
|
-
|
|
400
|
+
const matchRoute = (path) => {
|
|
401
|
+
return routes.find((route) => route.path === path)
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
const currentRoute = matchRoute(location);
|
|
405
|
+
|
|
406
|
+
const Children = () => {
|
|
407
|
+
const routeComponent = currentRoute ? currentRoute.component : () => null;
|
|
408
|
+
return routeComponent
|
|
409
|
+
};
|
|
327
410
|
|
|
328
411
|
return { Children, navigate }
|
|
329
412
|
};
|
|
@@ -539,71 +622,6 @@
|
|
|
539
622
|
commitWork: commitWork
|
|
540
623
|
});
|
|
541
624
|
|
|
542
|
-
/**
|
|
543
|
-
* This function reconciles the children of a fiber node with a new set of elements, creating new
|
|
544
|
-
* fibers for new elements, updating existing fibers for elements with the same type, and marking old
|
|
545
|
-
* fibers for deletion if they are not present in the new set of elements.
|
|
546
|
-
* @param wipFiber - A work-in-progress fiber object representing a component or element in the virtual
|
|
547
|
-
* DOM tree.
|
|
548
|
-
* @param elements - an array of elements representing the new children to be rendered in the current
|
|
549
|
-
* fiber's subtree
|
|
550
|
-
*/
|
|
551
|
-
const reconcileChildren = (wipFiber, elements) => {
|
|
552
|
-
let index = 0;
|
|
553
|
-
let oldFiber = wipFiber.alternate && wipFiber.alternate.child;
|
|
554
|
-
let prevSibling;
|
|
555
|
-
|
|
556
|
-
while (index < elements.length || oldFiber != undefined) {
|
|
557
|
-
const element = elements[index];
|
|
558
|
-
let newFiber;
|
|
559
|
-
|
|
560
|
-
const sameType = oldFiber && element && element.type == oldFiber.type;
|
|
561
|
-
|
|
562
|
-
if (sameType) {
|
|
563
|
-
newFiber = {
|
|
564
|
-
type: oldFiber ? oldFiber.type : undefined,
|
|
565
|
-
props: element.props,
|
|
566
|
-
dom: oldFiber ? oldFiber.dom : undefined,
|
|
567
|
-
parent: wipFiber,
|
|
568
|
-
alternate: oldFiber,
|
|
569
|
-
effectTag: EFFECT_TAGS.UPDATE,
|
|
570
|
-
};
|
|
571
|
-
}
|
|
572
|
-
if (element && !sameType) {
|
|
573
|
-
newFiber = {
|
|
574
|
-
type: element.type,
|
|
575
|
-
props: element.props,
|
|
576
|
-
dom: undefined,
|
|
577
|
-
parent: wipFiber,
|
|
578
|
-
alternate: undefined,
|
|
579
|
-
effectTag: EFFECT_TAGS.PLACEMENT,
|
|
580
|
-
};
|
|
581
|
-
}
|
|
582
|
-
if (oldFiber && !sameType) {
|
|
583
|
-
oldFiber.effectTag = EFFECT_TAGS.DELETION;
|
|
584
|
-
vars.deletions.push(oldFiber);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
if (oldFiber) {
|
|
588
|
-
oldFiber = oldFiber.sibling;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
if (index === 0) {
|
|
592
|
-
wipFiber.child = newFiber;
|
|
593
|
-
} else if (element && prevSibling) {
|
|
594
|
-
prevSibling.sibling = newFiber;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
prevSibling = newFiber;
|
|
598
|
-
index++;
|
|
599
|
-
}
|
|
600
|
-
};
|
|
601
|
-
|
|
602
|
-
var Reconciler = /*#__PURE__*/Object.freeze({
|
|
603
|
-
__proto__: null,
|
|
604
|
-
reconcileChildren: reconcileChildren
|
|
605
|
-
});
|
|
606
|
-
|
|
607
625
|
/**
|
|
608
626
|
* This function updates a function component by setting up a work-in-progress fiber, resetting the
|
|
609
627
|
* hook index, creating an empty hooks array, rendering the component, and reconciling its children.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unsetsoft/ryunixjs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3-nightly.11",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "./dist/Ryunix.js",
|
|
6
6
|
"types": "./dist/Ryunix.d.ts",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"rollup": "4.9.2"
|
|
24
24
|
},
|
|
25
25
|
"engines": {
|
|
26
|
-
"node": "
|
|
26
|
+
"node": "^18 || ^22"
|
|
27
27
|
},
|
|
28
28
|
"keywords": [
|
|
29
29
|
"ryunixjs"
|
package/src/lib/hooks.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RYUNIX_TYPES, STRINGS, vars } from '../utils/index'
|
|
2
2
|
import { isEqual } from 'lodash'
|
|
3
|
-
import {
|
|
3
|
+
import { reconcileChildren } from './reconciler'
|
|
4
4
|
/**
|
|
5
5
|
* @description The function creates a state.
|
|
6
6
|
* @param initial - The initial value of the state for the hook.
|
|
@@ -84,36 +84,6 @@ const useEffect = (callback, deps) => {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
/**
|
|
88
|
-
* The `useQuery` function is a custom hook in JavaScript that retrieves query parameters from the URL
|
|
89
|
-
* and stores them in a hook for easy access.
|
|
90
|
-
* @returns The `useQuery` function returns the `query` property of the `hook` object.
|
|
91
|
-
*/
|
|
92
|
-
const useQuery = () => {
|
|
93
|
-
const oldHook =
|
|
94
|
-
vars.wipFiber.alternate &&
|
|
95
|
-
vars.wipFiber.alternate.hooks &&
|
|
96
|
-
vars.wipFiber.alternate.hooks[vars.hookIndex]
|
|
97
|
-
|
|
98
|
-
const hasOld = oldHook ? oldHook : undefined
|
|
99
|
-
|
|
100
|
-
const urlSearchParams = new URLSearchParams(window.location.search)
|
|
101
|
-
const params = Object.fromEntries(urlSearchParams.entries())
|
|
102
|
-
const Query = hasOld ? hasOld : params
|
|
103
|
-
|
|
104
|
-
const hook = {
|
|
105
|
-
type: RYUNIX_TYPES.RYUNIX_URL_QUERY,
|
|
106
|
-
query: Query,
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (vars.wipFiber.hooks) {
|
|
110
|
-
vars.wipFiber.hooks.push(hook)
|
|
111
|
-
vars.hookIndex++
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return hook.query
|
|
115
|
-
}
|
|
116
|
-
|
|
117
87
|
const useRef = (initial) => {
|
|
118
88
|
const oldHook =
|
|
119
89
|
vars.wipFiber.alternate &&
|
|
@@ -166,27 +136,62 @@ const useCallback = (callback, deps) => {
|
|
|
166
136
|
return useMemo(() => callback, deps)
|
|
167
137
|
}
|
|
168
138
|
|
|
139
|
+
/**
|
|
140
|
+
* The `useQuery` function is a custom hook in JavaScript that retrieves query parameters from the URL
|
|
141
|
+
* and stores them in a hook for easy access.
|
|
142
|
+
* @returns The `useQuery` function returns the `query` property of the `hook` object.
|
|
143
|
+
*/
|
|
144
|
+
const useQuery = () => {
|
|
145
|
+
const oldHook =
|
|
146
|
+
vars.wipFiber.alternate &&
|
|
147
|
+
vars.wipFiber.alternate.hooks &&
|
|
148
|
+
vars.wipFiber.alternate.hooks[vars.hookIndex]
|
|
149
|
+
|
|
150
|
+
const hasOld = oldHook ? oldHook : undefined
|
|
151
|
+
|
|
152
|
+
const urlSearchParams = new URLSearchParams(window.location.search)
|
|
153
|
+
const params = Object.fromEntries(urlSearchParams.entries())
|
|
154
|
+
const Query = hasOld ? hasOld : params
|
|
155
|
+
|
|
156
|
+
const hook = {
|
|
157
|
+
type: RYUNIX_TYPES.RYUNIX_URL_QUERY,
|
|
158
|
+
query: Query,
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (vars.wipFiber.hooks) {
|
|
162
|
+
vars.wipFiber.hooks.push(hook)
|
|
163
|
+
vars.hookIndex++
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return hook.query
|
|
167
|
+
}
|
|
168
|
+
|
|
169
169
|
const useRouter = (routes) => {
|
|
170
170
|
const [location, setLocation] = useStore(window.location.pathname)
|
|
171
171
|
|
|
172
172
|
const navigate = (path) => {
|
|
173
|
-
window.
|
|
174
|
-
|
|
173
|
+
if (window.location.pathname !== path) {
|
|
174
|
+
window.history.pushState({}, '', path)
|
|
175
|
+
setLocation(path)
|
|
176
|
+
}
|
|
175
177
|
}
|
|
176
178
|
|
|
177
179
|
useEffect(() => {
|
|
178
|
-
const onPopState = () =>
|
|
179
|
-
setLocation(window.location.pathname)
|
|
180
|
-
}
|
|
181
|
-
|
|
180
|
+
const onPopState = () => setLocation(window.location.pathname)
|
|
182
181
|
window.addEventListener('popstate', onPopState)
|
|
183
|
-
return () =>
|
|
184
|
-
window.removeEventListener('popstate', onPopState)
|
|
185
|
-
}
|
|
182
|
+
return () => window.removeEventListener('popstate', onPopState)
|
|
186
183
|
}, [])
|
|
187
184
|
|
|
188
|
-
const
|
|
189
|
-
|
|
185
|
+
const matchRoute = (path) => {
|
|
186
|
+
return routes.find((route) => route.path === path)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const currentRoute = matchRoute(location)
|
|
190
|
+
|
|
191
|
+
const Children = () => {
|
|
192
|
+
const routeComponent = currentRoute ? currentRoute.component : () => null
|
|
193
|
+
return routeComponent
|
|
194
|
+
}
|
|
190
195
|
|
|
191
196
|
return { Children, navigate }
|
|
192
197
|
}
|
package/src/lib/reconciler.js
CHANGED
|
@@ -14,32 +14,36 @@ const reconcileChildren = (wipFiber, elements) => {
|
|
|
14
14
|
let oldFiber = wipFiber.alternate && wipFiber.alternate.child
|
|
15
15
|
let prevSibling
|
|
16
16
|
|
|
17
|
+
// Recorre los nuevos elementos y los viejos para comparar
|
|
17
18
|
while (index < elements.length || oldFiber != undefined) {
|
|
18
19
|
const element = elements[index]
|
|
19
20
|
let newFiber
|
|
20
21
|
|
|
22
|
+
// Verifica si el tipo de los elementos coincide
|
|
21
23
|
const sameType = oldFiber && element && element.type == oldFiber.type
|
|
22
24
|
|
|
23
25
|
if (sameType) {
|
|
26
|
+
// Actualiza el nodo existente con nuevas propiedades
|
|
24
27
|
newFiber = {
|
|
25
|
-
type: oldFiber
|
|
28
|
+
type: oldFiber.type,
|
|
26
29
|
props: element.props,
|
|
27
|
-
dom: oldFiber
|
|
30
|
+
dom: oldFiber.dom,
|
|
28
31
|
parent: wipFiber,
|
|
29
32
|
alternate: oldFiber,
|
|
30
33
|
effectTag: EFFECT_TAGS.UPDATE,
|
|
31
34
|
}
|
|
32
|
-
}
|
|
33
|
-
|
|
35
|
+
} else if (element) {
|
|
36
|
+
// Crea un nuevo nodo si el tipo es diferente
|
|
34
37
|
newFiber = {
|
|
35
38
|
type: element.type,
|
|
36
39
|
props: element.props,
|
|
37
|
-
dom:
|
|
40
|
+
dom: null,
|
|
38
41
|
parent: wipFiber,
|
|
39
|
-
alternate:
|
|
42
|
+
alternate: null,
|
|
40
43
|
effectTag: EFFECT_TAGS.PLACEMENT,
|
|
41
44
|
}
|
|
42
45
|
}
|
|
46
|
+
|
|
43
47
|
if (oldFiber && !sameType) {
|
|
44
48
|
oldFiber.effectTag = EFFECT_TAGS.DELETION
|
|
45
49
|
vars.deletions.push(oldFiber)
|
|
@@ -59,4 +63,5 @@ const reconcileChildren = (wipFiber, elements) => {
|
|
|
59
63
|
index++
|
|
60
64
|
}
|
|
61
65
|
}
|
|
66
|
+
|
|
62
67
|
export { reconcileChildren }
|
package/src/lib/render.js
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { vars } from '../utils/index'
|
|
2
2
|
|
|
3
|
+
const clearContainer = (container) => {
|
|
4
|
+
while (container.firstChild) {
|
|
5
|
+
container.removeChild(container.firstChild)
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
/**
|
|
4
|
-
*
|
|
5
|
-
* @
|
|
6
|
-
* container. It
|
|
7
|
-
* @param container - The container parameter is
|
|
8
|
-
*
|
|
10
|
+
* Renders an element into a container using a work-in-progress (WIP) root.
|
|
11
|
+
* @function render
|
|
12
|
+
* @param {Object|HTMLElement} element - The element to be rendered in the container. It can be a Ryunix component (custom element) or a standard DOM element.
|
|
13
|
+
* @param {HTMLElement} container - The container where the element will be rendered. This parameter is optional if `createRoot()` is used beforehand to set up the container.
|
|
14
|
+
* @description The function assigns the `container` to a work-in-progress root and sets up properties for reconciliation, including children and the reference to the current root.
|
|
15
|
+
* It also clears any scheduled deletions and establishes the next unit of work for incremental rendering.
|
|
9
16
|
*/
|
|
10
17
|
const render = (element, container) => {
|
|
18
|
+
if (vars.wipRoot && vars.wipRoot.dom) {
|
|
19
|
+
vars.wipRoot.container = container
|
|
20
|
+
}
|
|
21
|
+
|
|
11
22
|
vars.wipRoot = {
|
|
12
23
|
dom: vars.containerRoot || container,
|
|
13
24
|
props: {
|
|
@@ -15,20 +26,24 @@ const render = (element, container) => {
|
|
|
15
26
|
},
|
|
16
27
|
alternate: vars.currentRoot,
|
|
17
28
|
}
|
|
29
|
+
|
|
18
30
|
vars.deletions = []
|
|
19
31
|
vars.nextUnitOfWork = vars.wipRoot
|
|
20
32
|
}
|
|
21
33
|
|
|
22
34
|
/**
|
|
23
|
-
*
|
|
24
|
-
* @
|
|
25
|
-
* @param
|
|
26
|
-
* for the root element.
|
|
35
|
+
* Initializes the application by creating a reference to a DOM element with the specified ID and rendering the main component.
|
|
36
|
+
* @function init
|
|
37
|
+
* @param {Object} MainElement - The main component to render, typically the root component of the application.
|
|
38
|
+
* @param {string} [root='__ryunix'] - The ID of the HTML element that serves as the container for the root element. Defaults to `'__ryunix'` if not provided.
|
|
39
|
+
* @example
|
|
40
|
+
* Ryunix.init(App, "__ryunix"); // Initializes and renders the App component into the <div id="__ryunix"></div> element.
|
|
41
|
+
* @description This function retrieves the container element by its ID and invokes the `render` function to render the main component into it.
|
|
27
42
|
*/
|
|
28
|
-
const init = (root) => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
43
|
+
const init = (MainElement, root = '__ryunix') => {
|
|
44
|
+
vars.containerRoot = document.getElementById(root)
|
|
45
|
+
|
|
46
|
+
render(MainElement, vars.containerRoot)
|
|
32
47
|
}
|
|
33
48
|
|
|
34
49
|
export { render, init }
|
package/dist/cj/Ryunix.js
DELETED
|
@@ -1,702 +0,0 @@
|
|
|
1
|
-
;(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined'
|
|
3
|
-
? factory(exports)
|
|
4
|
-
: typeof define === 'function' && define.amd
|
|
5
|
-
? define(['exports'], factory)
|
|
6
|
-
: ((global =
|
|
7
|
-
typeof globalThis !== 'undefined' ? globalThis : global || self),
|
|
8
|
-
factory((global.Ryunix = {})))
|
|
9
|
-
})(this, function (exports) {
|
|
10
|
-
'use strict'
|
|
11
|
-
|
|
12
|
-
const vars = {
|
|
13
|
-
containerRoot: null,
|
|
14
|
-
nextUnitOfWork: null,
|
|
15
|
-
currentRoot: null,
|
|
16
|
-
wipRoot: null,
|
|
17
|
-
deletions: null,
|
|
18
|
-
wipFiber: null,
|
|
19
|
-
hookIndex: null,
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const reg = /[A-Z]/g
|
|
23
|
-
|
|
24
|
-
const RYUNIX_TYPES = Object.freeze({
|
|
25
|
-
TEXT_ELEMENT: Symbol('text.element'),
|
|
26
|
-
RYUNIX_EFFECT: Symbol('ryunix.effect'),
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
const STRINGS = Object.freeze({
|
|
30
|
-
object: 'object',
|
|
31
|
-
function: 'function',
|
|
32
|
-
style: 'style',
|
|
33
|
-
className: 'className',
|
|
34
|
-
children: 'children',
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const EFFECT_TAGS = Object.freeze({
|
|
38
|
-
PLACEMENT: Symbol(),
|
|
39
|
-
UPDATE: Symbol(),
|
|
40
|
-
DELETION: Symbol(),
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* The function creates a new element with the given type, props, and children.
|
|
45
|
-
* @param type - The type of the element to be created, such as "div", "span", "h1", etc.
|
|
46
|
-
* @param props - The `props` parameter is an object that contains the properties or attributes of the
|
|
47
|
-
* element being created. These properties can include things like `className`, `id`, `style`, and any
|
|
48
|
-
* other custom attributes that the user wants to add to the element. The `props` object is spread
|
|
49
|
-
* using the spread
|
|
50
|
-
* @param children - The `children` parameter is a rest parameter that allows the function to accept
|
|
51
|
-
* any number of arguments after the `props` parameter. These arguments will be treated as children
|
|
52
|
-
* elements of the created element. The `map` function is used to iterate over each child and create a
|
|
53
|
-
* new element if it is not
|
|
54
|
-
* @returns A JavaScript object with a `type` property and a `props` property. The `type` property is
|
|
55
|
-
* set to the `type` argument passed into the function, and the `props` property is an object that
|
|
56
|
-
* includes any additional properties passed in the `props` argument, as well as a `children` property
|
|
57
|
-
* that is an array of any child elements passed in the `...children` argument
|
|
58
|
-
*/
|
|
59
|
-
|
|
60
|
-
const createElement = (type, props, ...children) => {
|
|
61
|
-
return {
|
|
62
|
-
type,
|
|
63
|
-
props: {
|
|
64
|
-
...props,
|
|
65
|
-
children: children
|
|
66
|
-
.flat()
|
|
67
|
-
.map((child) =>
|
|
68
|
-
typeof child === STRINGS.object ? child : createTextElement(child),
|
|
69
|
-
),
|
|
70
|
-
},
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* The function creates a text element with a given text value.
|
|
76
|
-
* @param text - The text content that will be used to create a new text element.
|
|
77
|
-
* @returns A JavaScript object with a `type` property set to `"TEXT_ELEMENT"` and a `props` property
|
|
78
|
-
* that contains a `nodeValue` property set to the `text` parameter and an empty `children` array.
|
|
79
|
-
*/
|
|
80
|
-
|
|
81
|
-
const createTextElement = (text) => {
|
|
82
|
-
return {
|
|
83
|
-
type: RYUNIX_TYPES.TEXT_ELEMENT,
|
|
84
|
-
props: {
|
|
85
|
-
nodeValue: text,
|
|
86
|
-
children: [],
|
|
87
|
-
},
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const Fragments = (props) => {
|
|
92
|
-
if (props.style) {
|
|
93
|
-
throw new Error('The style attribute is not supported')
|
|
94
|
-
}
|
|
95
|
-
if (props.className === '') {
|
|
96
|
-
throw new Error('className cannot be empty.')
|
|
97
|
-
}
|
|
98
|
-
return createElement('div', props, props.children)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* The function renders an element into a container using a work-in-progress root.
|
|
103
|
-
* @param element - The element parameter is the component or element that needs to be rendered in the
|
|
104
|
-
* container. It could be a Ryunix component or a DOM element.
|
|
105
|
-
* @param container - The container parameter is the DOM element where the rendered element will be
|
|
106
|
-
* appended to. this parameter is optional if you use createRoot().
|
|
107
|
-
*/
|
|
108
|
-
const render = (element, container) => {
|
|
109
|
-
vars.wipRoot = {
|
|
110
|
-
dom: vars.containerRoot || container,
|
|
111
|
-
props: {
|
|
112
|
-
children: [element],
|
|
113
|
-
},
|
|
114
|
-
alternate: vars.currentRoot,
|
|
115
|
-
}
|
|
116
|
-
vars.deletions = []
|
|
117
|
-
vars.nextUnitOfWork = vars.wipRoot
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* @description The function creates a reference to a DOM element with the specified ID. This will be used to initialize the app.
|
|
122
|
-
* @example Ryunix.init("root") -> <div id="root" />
|
|
123
|
-
* @param root - The parameter "root" is the id of the HTML element that will serve as the container
|
|
124
|
-
* for the root element.
|
|
125
|
-
*/
|
|
126
|
-
const init = (root) => {
|
|
127
|
-
const rootElement = root || '__ryunix'
|
|
128
|
-
vars.containerRoot = document.getElementById(rootElement)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const isEvent = (key) => key.startsWith('on')
|
|
132
|
-
const isProperty = (key) => key !== STRINGS.children && !isEvent(key)
|
|
133
|
-
const isNew = (prev, next) => (key) => prev[key] !== next[key]
|
|
134
|
-
const isGone = (next) => (key) => !(key in next)
|
|
135
|
-
const hasDepsChanged = (prevDeps, nextDeps) =>
|
|
136
|
-
!prevDeps ||
|
|
137
|
-
!nextDeps ||
|
|
138
|
-
prevDeps.length !== nextDeps.length ||
|
|
139
|
-
prevDeps.some((dep, index) => dep !== nextDeps[index])
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* The function cancels all effect hooks in a given fiber.
|
|
143
|
-
* @param fiber - The "fiber" parameter is likely referring to a data structure used in React.js to
|
|
144
|
-
* represent a component and its state. It contains information about the component's props, state, and
|
|
145
|
-
* children, as well as metadata used by React to manage updates and rendering. The function
|
|
146
|
-
* "cancelEffects" is likely intended
|
|
147
|
-
*/
|
|
148
|
-
const cancelEffects = (fiber) => {
|
|
149
|
-
if (fiber.hooks) {
|
|
150
|
-
fiber.hooks
|
|
151
|
-
.filter(
|
|
152
|
-
(hook) => hook.tag === RYUNIX_TYPES.RYUNIX_EFFECT && hook.cancel,
|
|
153
|
-
)
|
|
154
|
-
.forEach((effectHook) => {
|
|
155
|
-
effectHook.cancel()
|
|
156
|
-
})
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* The function runs all effect hooks in a given fiber.
|
|
162
|
-
* @param fiber - The "fiber" parameter is likely referring to a data structure used in the
|
|
163
|
-
* implementation of a fiber-based reconciliation algorithm, such as the one used in React. A fiber
|
|
164
|
-
* represents a unit of work that needs to be performed by the reconciliation algorithm, and it
|
|
165
|
-
* contains information about a component and its children, as
|
|
166
|
-
*/
|
|
167
|
-
const runEffects = (fiber) => {
|
|
168
|
-
if (fiber.hooks) {
|
|
169
|
-
fiber.hooks
|
|
170
|
-
.filter(
|
|
171
|
-
(hook) => hook.tag === RYUNIX_TYPES.RYUNIX_EFFECT && hook.effect,
|
|
172
|
-
)
|
|
173
|
-
.forEach((effectHook) => {
|
|
174
|
-
effectHook.cancel = effectHook.effect()
|
|
175
|
-
})
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* @description The function creates a state.
|
|
181
|
-
* @param initial - The initial value of the state for the hook.
|
|
182
|
-
* @returns The `useStore` function returns an array with two elements: the current state value and a
|
|
183
|
-
* `setState` function that can be used to update the state.
|
|
184
|
-
*/
|
|
185
|
-
const useStore = (initial) => {
|
|
186
|
-
const oldHook =
|
|
187
|
-
vars.wipFiber.alternate &&
|
|
188
|
-
vars.wipFiber.alternate.hooks &&
|
|
189
|
-
vars.wipFiber.alternate.hooks[vars.hookIndex]
|
|
190
|
-
const hook = {
|
|
191
|
-
state: oldHook ? oldHook.state : initial,
|
|
192
|
-
queue: [],
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const actions = oldHook ? oldHook.queue : []
|
|
196
|
-
actions.forEach((action) => {
|
|
197
|
-
hook.state =
|
|
198
|
-
typeof action === STRINGS.function ? action(hook.state) : action
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* The function `setState` updates the state of a component in Ryunix by adding an action to a queue
|
|
203
|
-
* and setting up a new work-in-progress root.
|
|
204
|
-
* @param action - The `action` parameter is an object that represents a state update to be performed
|
|
205
|
-
* on a component. It contains information about the type of update to be performed and any new data
|
|
206
|
-
* that needs to be applied to the component's state.
|
|
207
|
-
*/
|
|
208
|
-
const setState = (action) => {
|
|
209
|
-
hook.queue.push(action)
|
|
210
|
-
vars.wipRoot = {
|
|
211
|
-
dom: vars.currentRoot.dom,
|
|
212
|
-
props: vars.currentRoot.props,
|
|
213
|
-
alternate: vars.currentRoot,
|
|
214
|
-
}
|
|
215
|
-
vars.nextUnitOfWork = vars.wipRoot
|
|
216
|
-
vars.deletions = []
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
vars.wipFiber.hooks.push(hook)
|
|
220
|
-
vars.hookIndex++
|
|
221
|
-
return [hook.state, setState]
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* This is a function that creates a hook for managing side effects in Ryunix components.
|
|
226
|
-
* @param effect - The effect function that will be executed after the component has rendered or when
|
|
227
|
-
* the dependencies have changed. It can perform side effects such as fetching data, updating the DOM,
|
|
228
|
-
* or subscribing to events.
|
|
229
|
-
* @param deps - An array of dependencies that the effect depends on. If any of the dependencies change
|
|
230
|
-
* between renders, the effect will be re-run. If the array is empty, the effect will only run once on
|
|
231
|
-
* mount and never again.
|
|
232
|
-
*/
|
|
233
|
-
const useEffect = (effect, deps) => {
|
|
234
|
-
const oldHook =
|
|
235
|
-
vars.wipFiber.alternate &&
|
|
236
|
-
vars.wipFiber.alternate.hooks &&
|
|
237
|
-
vars.wipFiber.alternate.hooks[vars.hookIndex]
|
|
238
|
-
|
|
239
|
-
const hasChanged = hasDepsChanged(oldHook ? oldHook.deps : undefined, deps)
|
|
240
|
-
|
|
241
|
-
const hook = {
|
|
242
|
-
tag: RYUNIX_TYPES.RYUNIX_EFFECT,
|
|
243
|
-
effect: hasChanged ? effect : null,
|
|
244
|
-
cancel: hasChanged && oldHook && oldHook.cancel,
|
|
245
|
-
deps,
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
vars.wipFiber.hooks.push(hook)
|
|
249
|
-
vars.hookIndex++
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const useQuery = () => {
|
|
253
|
-
vars.hookIndex++
|
|
254
|
-
|
|
255
|
-
const oldHook =
|
|
256
|
-
vars.wipFiber.alternate &&
|
|
257
|
-
vars.wipFiber.alternate.hooks &&
|
|
258
|
-
vars.wipFiber.alternate.hooks[vars.hookIndex]
|
|
259
|
-
|
|
260
|
-
const hasOld = oldHook ? oldHook : undefined
|
|
261
|
-
|
|
262
|
-
const urlSearchParams = new URLSearchParams(window.location.search)
|
|
263
|
-
const params = Object.fromEntries(urlSearchParams.entries())
|
|
264
|
-
const Query = hasOld ? hasOld : params
|
|
265
|
-
|
|
266
|
-
const hook = {
|
|
267
|
-
tag: RYUNIX_TYPES.RYUNIX_EFFECT,
|
|
268
|
-
query: Query,
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
vars.wipFiber.hooks.push(hook)
|
|
272
|
-
|
|
273
|
-
return hook.query
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
const Router = ({ path, component }) => {
|
|
277
|
-
const [currentPath, setCurrentPath] = useStore(window.location.pathname)
|
|
278
|
-
|
|
279
|
-
useEffect(() => {
|
|
280
|
-
const onLocationChange = () => {
|
|
281
|
-
setCurrentPath(() => window.location.pathname)
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
window.addEventListener('navigate', onLocationChange)
|
|
285
|
-
window.addEventListener('pushsatate', onLocationChange)
|
|
286
|
-
window.addEventListener('popstate', onLocationChange)
|
|
287
|
-
|
|
288
|
-
return () => {
|
|
289
|
-
window.removeEventListener('navigate', onLocationChange)
|
|
290
|
-
window.removeEventListener('pushsatate', onLocationChange)
|
|
291
|
-
window.removeEventListener('popstate', onLocationChange)
|
|
292
|
-
}
|
|
293
|
-
}, [currentPath])
|
|
294
|
-
|
|
295
|
-
return currentPath === path ? component() : null
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
const Navigate = () => {
|
|
299
|
-
/**
|
|
300
|
-
* The function `push` is used to push a new state to the browser's history and trigger a custom
|
|
301
|
-
* event called 'pushstate'.
|
|
302
|
-
* @param to - The `to` parameter is a string representing the URL path to which you want to
|
|
303
|
-
* navigate.
|
|
304
|
-
* @param [state] - The `state` parameter is an optional object that represents the state associated
|
|
305
|
-
* with the new history entry. It can be used to store any data that you want to associate with the
|
|
306
|
-
* new URL. When you navigate back or forward in the browser history, this state object will be
|
|
307
|
-
* passed to the `popstate
|
|
308
|
-
* @returns The function `push` does not have a return statement, so it returns `undefined` by
|
|
309
|
-
* default.
|
|
310
|
-
*/
|
|
311
|
-
const push = (to, state = {}) => {
|
|
312
|
-
if (window.location.pathname === to) return
|
|
313
|
-
window.history.pushState(state, '', to)
|
|
314
|
-
const navigationEvent = new Event('pushsatate')
|
|
315
|
-
window.dispatchEvent(navigationEvent)
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
return { push }
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
const Link = (props) => {
|
|
322
|
-
if (props.style) {
|
|
323
|
-
throw new Error(
|
|
324
|
-
'The style attribute is not supported on internal components, use className.',
|
|
325
|
-
)
|
|
326
|
-
}
|
|
327
|
-
if (props.to === '') {
|
|
328
|
-
throw new Error("'to=' cannot be empty.")
|
|
329
|
-
}
|
|
330
|
-
if (props.className === '') {
|
|
331
|
-
throw new Error('className cannot be empty.')
|
|
332
|
-
}
|
|
333
|
-
if (props.label === '' && !props.children) {
|
|
334
|
-
throw new Error("'label=' cannot be empty.")
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (!props.to) {
|
|
338
|
-
throw new Error("Missig 'to' param.")
|
|
339
|
-
}
|
|
340
|
-
const preventReload = (event) => {
|
|
341
|
-
event.preventDefault()
|
|
342
|
-
const { push } = Navigate()
|
|
343
|
-
push(props.to)
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
const anchor = {
|
|
347
|
-
href: props.to,
|
|
348
|
-
onClick: preventReload,
|
|
349
|
-
...props,
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const children = props.label ? props.label : props.children
|
|
353
|
-
|
|
354
|
-
return createElement('a', anchor, children)
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* The function creates a new DOM element based on the given fiber object and updates its properties.
|
|
359
|
-
* @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
|
|
360
|
-
* contains information about the element type, props, and children of the node.
|
|
361
|
-
* @returns The `createDom` function returns a newly created DOM element based on the `fiber` object
|
|
362
|
-
* passed as an argument. If the `fiber` object represents a text element, a text node is created using
|
|
363
|
-
* `document.createTextNode("")`. Otherwise, a new element is created using
|
|
364
|
-
* `document.createElement(fiber.type)`. The function then calls the `updateDom` function to update the
|
|
365
|
-
* properties of the newly created
|
|
366
|
-
*/
|
|
367
|
-
const createDom = (fiber) => {
|
|
368
|
-
const dom =
|
|
369
|
-
fiber.type == RYUNIX_TYPES.TEXT_ELEMENT
|
|
370
|
-
? document.createTextNode('')
|
|
371
|
-
: document.createElement(fiber.type)
|
|
372
|
-
|
|
373
|
-
updateDom(dom, {}, fiber.props)
|
|
374
|
-
|
|
375
|
-
return dom
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* The function updates the DOM by removing old event listeners and properties, and adding new ones
|
|
380
|
-
* based on the previous and next props.
|
|
381
|
-
* @param dom - The DOM element that needs to be updated with new props.
|
|
382
|
-
* @param prevProps - An object representing the previous props (properties) of a DOM element.
|
|
383
|
-
* @param nextProps - An object containing the new props that need to be updated in the DOM.
|
|
384
|
-
*/
|
|
385
|
-
const updateDom = (dom, prevProps, nextProps) => {
|
|
386
|
-
Object.keys(prevProps)
|
|
387
|
-
.filter(isEvent)
|
|
388
|
-
.filter(
|
|
389
|
-
(key) => isGone(nextProps)(key) || isNew(prevProps, nextProps)(key),
|
|
390
|
-
)
|
|
391
|
-
.forEach((name) => {
|
|
392
|
-
const eventType = name.toLowerCase().substring(2)
|
|
393
|
-
dom.removeEventListener(eventType, prevProps[name])
|
|
394
|
-
})
|
|
395
|
-
|
|
396
|
-
Object.keys(prevProps)
|
|
397
|
-
.filter(isProperty)
|
|
398
|
-
.filter(isGone(nextProps))
|
|
399
|
-
.forEach((name) => {
|
|
400
|
-
dom[name] = ''
|
|
401
|
-
})
|
|
402
|
-
|
|
403
|
-
Object.keys(nextProps)
|
|
404
|
-
.filter(isProperty)
|
|
405
|
-
.filter(isNew(prevProps, nextProps))
|
|
406
|
-
.forEach((name) => {
|
|
407
|
-
if (name === STRINGS.style) {
|
|
408
|
-
DomStyle(dom, nextProps.style)
|
|
409
|
-
} else if (name === STRINGS.className) {
|
|
410
|
-
if (nextProps.className === '') {
|
|
411
|
-
throw new Error('className cannot be empty.')
|
|
412
|
-
}
|
|
413
|
-
prevProps.className &&
|
|
414
|
-
dom.classList.remove(...prevProps.className.split(/\s+/))
|
|
415
|
-
dom.classList.add(...nextProps.className.split(/\s+/))
|
|
416
|
-
} else {
|
|
417
|
-
dom[name] = nextProps[name]
|
|
418
|
-
}
|
|
419
|
-
})
|
|
420
|
-
|
|
421
|
-
Object.keys(nextProps)
|
|
422
|
-
.filter(isEvent)
|
|
423
|
-
.filter(isNew(prevProps, nextProps))
|
|
424
|
-
.forEach((name) => {
|
|
425
|
-
const eventType = name.toLowerCase().substring(2)
|
|
426
|
-
dom.addEventListener(eventType, nextProps[name])
|
|
427
|
-
})
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
const DomStyle = (dom, style) => {
|
|
431
|
-
dom.style = Object.keys(style).reduce((acc, styleName) => {
|
|
432
|
-
const key = styleName.replace(reg, function (v) {
|
|
433
|
-
return '-' + v.toLowerCase()
|
|
434
|
-
})
|
|
435
|
-
acc += `${key}: ${style[styleName]};`
|
|
436
|
-
return acc
|
|
437
|
-
}, '')
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
var Dom = /*#__PURE__*/ Object.freeze({
|
|
441
|
-
__proto__: null,
|
|
442
|
-
DomStyle: DomStyle,
|
|
443
|
-
createDom: createDom,
|
|
444
|
-
updateDom: updateDom,
|
|
445
|
-
})
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* The function commits changes made to the virtual DOM to the actual DOM.
|
|
449
|
-
*/
|
|
450
|
-
const commitRoot = () => {
|
|
451
|
-
vars.deletions.forEach(commitWork)
|
|
452
|
-
commitWork(vars.wipRoot.child)
|
|
453
|
-
vars.currentRoot = vars.wipRoot
|
|
454
|
-
vars.wipRoot = null
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* The function commits changes made to the DOM based on the effect tag of the fiber.
|
|
459
|
-
* @param fiber - A fiber is a unit of work in Ryunix's reconciliation process. It represents a
|
|
460
|
-
* component and its state at a particular point in time. The `commitWork` function takes a fiber as a
|
|
461
|
-
* parameter to commit the changes made during the reconciliation process to the actual DOM.
|
|
462
|
-
* @returns The function does not return anything, it performs side effects by manipulating the DOM.
|
|
463
|
-
*/
|
|
464
|
-
const commitWork = (fiber) => {
|
|
465
|
-
if (!fiber) {
|
|
466
|
-
return
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
let domParentFiber = fiber.parent
|
|
470
|
-
while (!domParentFiber.dom) {
|
|
471
|
-
domParentFiber = domParentFiber.parent
|
|
472
|
-
}
|
|
473
|
-
const domParent = domParentFiber.dom
|
|
474
|
-
|
|
475
|
-
if (fiber.effectTag === EFFECT_TAGS.PLACEMENT) {
|
|
476
|
-
if (fiber.dom != null) {
|
|
477
|
-
domParent.appendChild(fiber.dom)
|
|
478
|
-
}
|
|
479
|
-
runEffects(fiber)
|
|
480
|
-
} else if (fiber.effectTag === EFFECT_TAGS.UPDATE) {
|
|
481
|
-
cancelEffects(fiber)
|
|
482
|
-
if (fiber.dom != null) {
|
|
483
|
-
updateDom(fiber.dom, fiber.alternate.props, fiber.props)
|
|
484
|
-
}
|
|
485
|
-
runEffects(fiber)
|
|
486
|
-
} else if (fiber.effectTag === EFFECT_TAGS.DELETION) {
|
|
487
|
-
cancelEffects(fiber)
|
|
488
|
-
commitDeletion(fiber, domParent)
|
|
489
|
-
return
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
commitWork(fiber.child)
|
|
493
|
-
commitWork(fiber.sibling)
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
/**
|
|
497
|
-
* The function removes a fiber's corresponding DOM node from its parent node or recursively removes
|
|
498
|
-
* its child's DOM node until it finds a node to remove.
|
|
499
|
-
* @param fiber - a fiber node in a fiber tree, which represents a component or an element in the Ryunix
|
|
500
|
-
* application.
|
|
501
|
-
* @param domParent - The parent DOM element from which the fiber's DOM element needs to be removed.
|
|
502
|
-
*/
|
|
503
|
-
const commitDeletion = (fiber, domParent) => {
|
|
504
|
-
if (fiber.dom) {
|
|
505
|
-
domParent.removeChild(fiber.dom)
|
|
506
|
-
} else {
|
|
507
|
-
commitDeletion(fiber.child, domParent)
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
var Commits = /*#__PURE__*/ Object.freeze({
|
|
512
|
-
__proto__: null,
|
|
513
|
-
commitDeletion: commitDeletion,
|
|
514
|
-
commitRoot: commitRoot,
|
|
515
|
-
commitWork: commitWork,
|
|
516
|
-
})
|
|
517
|
-
|
|
518
|
-
/**
|
|
519
|
-
* This function reconciles the children of a fiber node with a new set of elements, creating new
|
|
520
|
-
* fibers for new elements, updating existing fibers for elements with the same type, and marking old
|
|
521
|
-
* fibers for deletion if they are not present in the new set of elements.
|
|
522
|
-
* @param wipFiber - A work-in-progress fiber object representing a component or element in the virtual
|
|
523
|
-
* DOM tree.
|
|
524
|
-
* @param elements - an array of elements representing the new children to be rendered in the current
|
|
525
|
-
* fiber's subtree
|
|
526
|
-
*/
|
|
527
|
-
const reconcileChildren = (wipFiber, elements) => {
|
|
528
|
-
let index = 0
|
|
529
|
-
let oldFiber = wipFiber.alternate && wipFiber.alternate.child
|
|
530
|
-
let prevSibling
|
|
531
|
-
|
|
532
|
-
while (index < elements.length || oldFiber != null) {
|
|
533
|
-
const element = elements[index]
|
|
534
|
-
let newFiber
|
|
535
|
-
|
|
536
|
-
const sameType = oldFiber && element && element.type == oldFiber.type
|
|
537
|
-
|
|
538
|
-
if (sameType) {
|
|
539
|
-
newFiber = {
|
|
540
|
-
type: oldFiber.type,
|
|
541
|
-
props: element.props,
|
|
542
|
-
dom: oldFiber.dom,
|
|
543
|
-
parent: wipFiber,
|
|
544
|
-
alternate: oldFiber,
|
|
545
|
-
effectTag: EFFECT_TAGS.UPDATE,
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
if (element && !sameType) {
|
|
549
|
-
newFiber = {
|
|
550
|
-
type: element.type,
|
|
551
|
-
props: element.props,
|
|
552
|
-
dom: null,
|
|
553
|
-
parent: wipFiber,
|
|
554
|
-
alternate: null,
|
|
555
|
-
effectTag: EFFECT_TAGS.PLACEMENT,
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
if (oldFiber && !sameType) {
|
|
559
|
-
oldFiber.effectTag = EFFECT_TAGS.DELETION
|
|
560
|
-
vars.deletions.push(oldFiber)
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
if (oldFiber) {
|
|
564
|
-
oldFiber = oldFiber.sibling
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
if (index === 0) {
|
|
568
|
-
wipFiber.child = newFiber
|
|
569
|
-
} else if (element) {
|
|
570
|
-
prevSibling.sibling = newFiber
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
prevSibling = newFiber
|
|
574
|
-
index++
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
var Reconciler = /*#__PURE__*/ Object.freeze({
|
|
579
|
-
__proto__: null,
|
|
580
|
-
reconcileChildren: reconcileChildren,
|
|
581
|
-
})
|
|
582
|
-
|
|
583
|
-
/**
|
|
584
|
-
* This function updates a function component by setting up a work-in-progress fiber, resetting the
|
|
585
|
-
* hook index, creating an empty hooks array, rendering the component, and reconciling its children.
|
|
586
|
-
* @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
|
|
587
|
-
* contains information about the component, its props, state, and children. In this function, it is
|
|
588
|
-
* used to update the state of the component and its children.
|
|
589
|
-
*/
|
|
590
|
-
const updateFunctionComponent = (fiber) => {
|
|
591
|
-
vars.wipFiber = fiber
|
|
592
|
-
vars.hookIndex = 0
|
|
593
|
-
vars.wipFiber.hooks = []
|
|
594
|
-
const children = [fiber.type(fiber.props)]
|
|
595
|
-
reconcileChildren(fiber, children)
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
/**
|
|
599
|
-
* This function updates a host component's DOM element and reconciles its children.
|
|
600
|
-
* @param fiber - A fiber is a unit of work in Ryunix that represents a component and its state. It
|
|
601
|
-
* contains information about the component's type, props, and children, as well as pointers to other
|
|
602
|
-
* fibers in the tree.
|
|
603
|
-
*/
|
|
604
|
-
const updateHostComponent = (fiber) => {
|
|
605
|
-
if (!fiber.dom) {
|
|
606
|
-
fiber.dom = createDom(fiber)
|
|
607
|
-
}
|
|
608
|
-
reconcileChildren(fiber, fiber.props.children.flat())
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
var Components = /*#__PURE__*/ Object.freeze({
|
|
612
|
-
__proto__: null,
|
|
613
|
-
updateFunctionComponent: updateFunctionComponent,
|
|
614
|
-
updateHostComponent: updateHostComponent,
|
|
615
|
-
})
|
|
616
|
-
|
|
617
|
-
/**
|
|
618
|
-
* This function uses requestIdleCallback to perform work on a fiber tree until it is complete or the
|
|
619
|
-
* browser needs to yield to other tasks.
|
|
620
|
-
* @param deadline - The `deadline` parameter is an object that represents the amount of time the
|
|
621
|
-
* browser has to perform work before it needs to handle other tasks. It has a `timeRemaining()` method
|
|
622
|
-
* that returns the amount of time remaining before the deadline is reached. The `shouldYield` variable
|
|
623
|
-
* is used to determine
|
|
624
|
-
*/
|
|
625
|
-
const workLoop = (deadline) => {
|
|
626
|
-
let shouldYield = false
|
|
627
|
-
while (vars.nextUnitOfWork && !shouldYield) {
|
|
628
|
-
vars.nextUnitOfWork = performUnitOfWork(vars.nextUnitOfWork)
|
|
629
|
-
shouldYield = deadline.timeRemaining() < 1
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
if (!vars.nextUnitOfWork && vars.wipRoot) {
|
|
633
|
-
commitRoot()
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
requestIdleCallback(workLoop)
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
requestIdleCallback(workLoop)
|
|
640
|
-
|
|
641
|
-
/**
|
|
642
|
-
* The function performs a unit of work by updating either a function component or a host component and
|
|
643
|
-
* returns the next fiber to be processed.
|
|
644
|
-
* @param fiber - A fiber is a unit of work in Ryunix that represents a component and its state. It
|
|
645
|
-
* contains information about the component's type, props, and children, as well as pointers to its
|
|
646
|
-
* parent, child, and sibling fibers. The `performUnitOfWork` function takes a fiber as a parameter and
|
|
647
|
-
* performs work
|
|
648
|
-
* @returns The function `performUnitOfWork` returns the next fiber to be processed. If the current
|
|
649
|
-
* fiber has a child, it returns the child. Otherwise, it looks for the next sibling of the current
|
|
650
|
-
* fiber. If there are no more siblings, it goes up the tree to the parent and looks for the next
|
|
651
|
-
* sibling of the parent. The function returns `null` if there are no more fibers to process.
|
|
652
|
-
*/
|
|
653
|
-
const performUnitOfWork = (fiber) => {
|
|
654
|
-
const isFunctionComponent = fiber.type instanceof Function
|
|
655
|
-
if (isFunctionComponent) {
|
|
656
|
-
updateFunctionComponent(fiber)
|
|
657
|
-
} else {
|
|
658
|
-
updateHostComponent(fiber)
|
|
659
|
-
}
|
|
660
|
-
if (fiber.child) {
|
|
661
|
-
return fiber.child
|
|
662
|
-
}
|
|
663
|
-
let nextFiber = fiber
|
|
664
|
-
while (nextFiber) {
|
|
665
|
-
if (nextFiber.sibling) {
|
|
666
|
-
return nextFiber.sibling
|
|
667
|
-
}
|
|
668
|
-
nextFiber = nextFiber.parent
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
var Workers = /*#__PURE__*/ Object.freeze({
|
|
673
|
-
__proto__: null,
|
|
674
|
-
performUnitOfWork: performUnitOfWork,
|
|
675
|
-
workLoop: workLoop,
|
|
676
|
-
})
|
|
677
|
-
|
|
678
|
-
var Ryunix = {
|
|
679
|
-
createElement,
|
|
680
|
-
render,
|
|
681
|
-
init,
|
|
682
|
-
Fragments,
|
|
683
|
-
Dom,
|
|
684
|
-
Workers,
|
|
685
|
-
Reconciler,
|
|
686
|
-
Components,
|
|
687
|
-
Commits,
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
window.Ryunix = Ryunix
|
|
691
|
-
|
|
692
|
-
exports.Fragments = Fragments
|
|
693
|
-
exports.Link = Link
|
|
694
|
-
exports.Navigate = Navigate
|
|
695
|
-
exports.Router = Router
|
|
696
|
-
exports.default = Ryunix
|
|
697
|
-
exports.useEffect = useEffect
|
|
698
|
-
exports.useQuery = useQuery
|
|
699
|
-
exports.useStore = useStore
|
|
700
|
-
|
|
701
|
-
Object.defineProperty(exports, '__esModule', { value: true })
|
|
702
|
-
})
|