@unsetsoft/ryunixjs 1.0.3-nightly.9 → 1.1.1
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 +113 -92
- package/package.json +1 -1
- package/src/lib/commits.js +10 -9
- package/src/lib/createElement.js +6 -0
- package/src/lib/hooks.js +57 -40
- package/src/lib/reconciler.js +22 -29
- package/src/lib/render.js +24 -13
- package/src/lib/workers.js +1 -3
package/dist/Ryunix.js
CHANGED
|
@@ -79,10 +79,16 @@
|
|
|
79
79
|
|
|
80
80
|
const createElement = (type, props, ...children) => {
|
|
81
81
|
children = childArray(children, []);
|
|
82
|
+
const key =
|
|
83
|
+
props && props.key
|
|
84
|
+
? props.key
|
|
85
|
+
: `${type}-${Math.random().toString(36).substring(2, 9)}`;
|
|
86
|
+
|
|
82
87
|
return {
|
|
83
88
|
type,
|
|
84
89
|
props: {
|
|
85
90
|
...props,
|
|
91
|
+
key,
|
|
86
92
|
children: children.map((child) =>
|
|
87
93
|
typeof child === STRINGS.object ? child : createTextElement(child),
|
|
88
94
|
),
|
|
@@ -108,11 +114,12 @@
|
|
|
108
114
|
};
|
|
109
115
|
|
|
110
116
|
/**
|
|
111
|
-
*
|
|
112
|
-
* @
|
|
113
|
-
* container. It
|
|
114
|
-
* @param container - The container parameter is
|
|
115
|
-
*
|
|
117
|
+
* Renders an element into a container using a work-in-progress (WIP) root.
|
|
118
|
+
* @function render
|
|
119
|
+
* @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.
|
|
120
|
+
* @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.
|
|
121
|
+
* @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.
|
|
122
|
+
* It also clears any scheduled deletions and establishes the next unit of work for incremental rendering.
|
|
116
123
|
*/
|
|
117
124
|
const render = (element, container) => {
|
|
118
125
|
vars.wipRoot = {
|
|
@@ -122,20 +129,24 @@
|
|
|
122
129
|
},
|
|
123
130
|
alternate: vars.currentRoot,
|
|
124
131
|
};
|
|
132
|
+
|
|
125
133
|
vars.deletions = [];
|
|
126
134
|
vars.nextUnitOfWork = vars.wipRoot;
|
|
127
135
|
};
|
|
128
136
|
|
|
129
137
|
/**
|
|
130
|
-
*
|
|
131
|
-
* @
|
|
132
|
-
* @param
|
|
133
|
-
* for the root element.
|
|
138
|
+
* Initializes the application by creating a reference to a DOM element with the specified ID and rendering the main component.
|
|
139
|
+
* @function init
|
|
140
|
+
* @param {Object} MainElement - The main component to render, typically the root component of the application.
|
|
141
|
+
* @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.
|
|
142
|
+
* @example
|
|
143
|
+
* Ryunix.init(App, "__ryunix"); // Initializes and renders the App component into the <div id="__ryunix"></div> element.
|
|
144
|
+
* @description This function retrieves the container element by its ID and invokes the `render` function to render the main component into it.
|
|
134
145
|
*/
|
|
135
|
-
const init = (root) => {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
146
|
+
const init = (MainElement, root = '__ryunix') => {
|
|
147
|
+
vars.containerRoot = document.getElementById(root);
|
|
148
|
+
|
|
149
|
+
render(MainElement, vars.containerRoot);
|
|
139
150
|
};
|
|
140
151
|
|
|
141
152
|
/**
|
|
@@ -151,24 +162,19 @@
|
|
|
151
162
|
vars.wipFiber.alternate.hooks[vars.hookIndex];
|
|
152
163
|
const hook = {
|
|
153
164
|
state: oldHook ? oldHook.state : initial,
|
|
154
|
-
queue: [],
|
|
165
|
+
queue: oldHook ? [...oldHook.queue] : [],
|
|
155
166
|
};
|
|
156
167
|
|
|
157
|
-
|
|
158
|
-
actions.forEach((action) => {
|
|
168
|
+
hook.queue.forEach((action) => {
|
|
159
169
|
hook.state =
|
|
160
170
|
typeof action === STRINGS.function ? action(hook.state) : action;
|
|
161
171
|
});
|
|
162
172
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
* and setting up a new work-in-progress root.
|
|
166
|
-
* @param action - The `action` parameter is an object that represents a state update to be performed
|
|
167
|
-
* on a component. It contains information about the type of update to be performed and any new data
|
|
168
|
-
* that needs to be applied to the component's state.
|
|
169
|
-
*/
|
|
173
|
+
hook.queue = [];
|
|
174
|
+
|
|
170
175
|
const setState = (action) => {
|
|
171
176
|
hook.queue.push(action);
|
|
177
|
+
|
|
172
178
|
vars.wipRoot = {
|
|
173
179
|
dom: vars.currentRoot.dom,
|
|
174
180
|
props: vars.currentRoot.props,
|
|
@@ -182,6 +188,7 @@
|
|
|
182
188
|
vars.wipFiber.hooks.push(hook);
|
|
183
189
|
vars.hookIndex++;
|
|
184
190
|
}
|
|
191
|
+
|
|
185
192
|
return [hook.state, setState]
|
|
186
193
|
};
|
|
187
194
|
|
|
@@ -221,6 +228,36 @@
|
|
|
221
228
|
}
|
|
222
229
|
};
|
|
223
230
|
|
|
231
|
+
/**
|
|
232
|
+
* The `useQuery` function is a custom hook in JavaScript that retrieves query parameters from the URL
|
|
233
|
+
* and stores them in a hook for easy access.
|
|
234
|
+
* @returns The `useQuery` function returns the `query` property of the `hook` object.
|
|
235
|
+
*/
|
|
236
|
+
const useQuery = () => {
|
|
237
|
+
const oldHook =
|
|
238
|
+
vars.wipFiber.alternate &&
|
|
239
|
+
vars.wipFiber.alternate.hooks &&
|
|
240
|
+
vars.wipFiber.alternate.hooks[vars.hookIndex];
|
|
241
|
+
|
|
242
|
+
const hasOld = oldHook ? oldHook : undefined;
|
|
243
|
+
|
|
244
|
+
const urlSearchParams = new URLSearchParams(window.location.search);
|
|
245
|
+
const params = Object.fromEntries(urlSearchParams.entries());
|
|
246
|
+
const Query = hasOld ? hasOld : params;
|
|
247
|
+
|
|
248
|
+
const hook = {
|
|
249
|
+
type: RYUNIX_TYPES.RYUNIX_URL_QUERY,
|
|
250
|
+
query: Query,
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
if (vars.wipFiber.hooks) {
|
|
254
|
+
vars.wipFiber.hooks.push(hook);
|
|
255
|
+
vars.hookIndex++;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return hook.query
|
|
259
|
+
};
|
|
260
|
+
|
|
224
261
|
const useRef = (initial) => {
|
|
225
262
|
const oldHook =
|
|
226
263
|
vars.wipFiber.alternate &&
|
|
@@ -292,40 +329,31 @@
|
|
|
292
329
|
}
|
|
293
330
|
}, []);
|
|
294
331
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* The `useQuery` function is a custom hook in JavaScript that retrieves query parameters from the URL
|
|
303
|
-
* and stores them in a hook for easy access.
|
|
304
|
-
* @returns The `useQuery` function returns the `query` property of the `hook` object.
|
|
305
|
-
*/
|
|
306
|
-
const useQuery = () => {
|
|
307
|
-
const oldHook =
|
|
308
|
-
vars.wipFiber.alternate &&
|
|
309
|
-
vars.wipFiber.alternate.hooks &&
|
|
310
|
-
vars.wipFiber.alternate.hooks[vars.hookIndex];
|
|
332
|
+
let currentRoute = routes.find((route) => route.path === location);
|
|
333
|
+
if (!currentRoute) {
|
|
334
|
+
currentRoute = {
|
|
335
|
+
component: routes.find((route) => route.NotFound)?.NotFound || null,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
311
338
|
|
|
312
|
-
const
|
|
339
|
+
const Children = () =>
|
|
340
|
+
currentRoute.component ? currentRoute.component : null;
|
|
313
341
|
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
const Query = hasOld ? hasOld : params;
|
|
342
|
+
const NavLink = ({ to, ...props }) => {
|
|
343
|
+
const { children, ...restProps } = props;
|
|
317
344
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
345
|
+
const NewProps = {
|
|
346
|
+
href: to,
|
|
347
|
+
onClick: (e) => {
|
|
348
|
+
e.preventDefault();
|
|
349
|
+
navigate(to);
|
|
350
|
+
},
|
|
351
|
+
...restProps,
|
|
352
|
+
};
|
|
353
|
+
return createElement('a', NewProps, children)
|
|
321
354
|
};
|
|
322
355
|
|
|
323
|
-
|
|
324
|
-
vars.wipFiber.hooks.push(hook);
|
|
325
|
-
vars.hookIndex++;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return hook.query
|
|
356
|
+
return { Children, navigate, NavLink }
|
|
329
357
|
};
|
|
330
358
|
|
|
331
359
|
const isEvent = (key) => key.startsWith('on');
|
|
@@ -486,9 +514,7 @@
|
|
|
486
514
|
* @returns The function does not return anything, it performs side effects by manipulating the DOM.
|
|
487
515
|
*/
|
|
488
516
|
const commitWork = (fiber) => {
|
|
489
|
-
if (!fiber)
|
|
490
|
-
return
|
|
491
|
-
}
|
|
517
|
+
if (!fiber) return
|
|
492
518
|
|
|
493
519
|
let domParentFiber = fiber.parent;
|
|
494
520
|
while (!domParentFiber.dom) {
|
|
@@ -501,15 +527,19 @@
|
|
|
501
527
|
domParent.appendChild(fiber.dom);
|
|
502
528
|
}
|
|
503
529
|
runEffects(fiber);
|
|
504
|
-
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (fiber.effectTag === EFFECT_TAGS.UPDATE) {
|
|
505
533
|
cancelEffects(fiber);
|
|
506
534
|
if (fiber.dom != undefined) {
|
|
507
535
|
updateDom(fiber.dom, fiber.alternate.props, fiber.props);
|
|
508
536
|
}
|
|
509
537
|
runEffects(fiber);
|
|
510
|
-
}
|
|
511
|
-
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
if (fiber.effectTag === EFFECT_TAGS.DELETION) {
|
|
512
541
|
commitDeletion(fiber, domParent);
|
|
542
|
+
cancelEffects(fiber);
|
|
513
543
|
return
|
|
514
544
|
}
|
|
515
545
|
|
|
@@ -525,9 +555,9 @@
|
|
|
525
555
|
* @param domParent - The parent DOM element from which the fiber's DOM element needs to be removed.
|
|
526
556
|
*/
|
|
527
557
|
const commitDeletion = (fiber, domParent) => {
|
|
528
|
-
if (fiber
|
|
558
|
+
if (fiber.dom) {
|
|
529
559
|
domParent.removeChild(fiber.dom);
|
|
530
|
-
} else
|
|
560
|
+
} else {
|
|
531
561
|
commitDeletion(fiber.child, domParent);
|
|
532
562
|
}
|
|
533
563
|
};
|
|
@@ -539,20 +569,6 @@
|
|
|
539
569
|
commitWork: commitWork
|
|
540
570
|
});
|
|
541
571
|
|
|
542
|
-
const isPropsChanged = (prevProps, nextProps) => {
|
|
543
|
-
for (let key in prevProps) {
|
|
544
|
-
if (prevProps[key] !== nextProps[key]) {
|
|
545
|
-
return true
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
for (let key in nextProps) {
|
|
549
|
-
if (!(key in prevProps)) {
|
|
550
|
-
return true
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
return false
|
|
554
|
-
};
|
|
555
|
-
|
|
556
572
|
/**
|
|
557
573
|
* This function reconciles the children of a fiber node with a new set of elements, creating new
|
|
558
574
|
* fibers for new elements, updating existing fibers for elements with the same type, and marking old
|
|
@@ -565,24 +581,33 @@
|
|
|
565
581
|
const reconcileChildren = (wipFiber, elements) => {
|
|
566
582
|
let index = 0;
|
|
567
583
|
let oldFiber = wipFiber.alternate && wipFiber.alternate.child;
|
|
568
|
-
let prevSibling;
|
|
584
|
+
let prevSibling = null;
|
|
585
|
+
|
|
586
|
+
const oldFibersMap = new Map();
|
|
587
|
+
while (oldFiber) {
|
|
588
|
+
const oldKey = oldFiber.props.key || oldFiber.type;
|
|
589
|
+
oldFibersMap.set(oldKey, oldFiber);
|
|
590
|
+
oldFiber = oldFiber.sibling;
|
|
591
|
+
}
|
|
569
592
|
|
|
570
|
-
while (index < elements.length
|
|
593
|
+
while (index < elements.length) {
|
|
571
594
|
const element = elements[index];
|
|
595
|
+
const key = element.props.key || element.type;
|
|
596
|
+
const oldFiber = oldFibersMap.get(key);
|
|
597
|
+
|
|
572
598
|
let newFiber;
|
|
573
|
-
const sameType = oldFiber && element && element.type
|
|
599
|
+
const sameType = oldFiber && element && element.type === oldFiber.type;
|
|
574
600
|
|
|
575
601
|
if (sameType) {
|
|
576
602
|
newFiber = {
|
|
577
|
-
type: oldFiber
|
|
603
|
+
type: oldFiber.type,
|
|
578
604
|
props: element.props,
|
|
579
|
-
dom: oldFiber
|
|
605
|
+
dom: oldFiber.dom,
|
|
580
606
|
parent: wipFiber,
|
|
581
607
|
alternate: oldFiber,
|
|
582
|
-
effectTag:
|
|
583
|
-
? EFFECT_TAGS.UPDATE
|
|
584
|
-
: null,
|
|
608
|
+
effectTag: EFFECT_TAGS.UPDATE,
|
|
585
609
|
};
|
|
610
|
+
oldFibersMap.delete(key);
|
|
586
611
|
} else if (element) {
|
|
587
612
|
newFiber = {
|
|
588
613
|
type: element.type,
|
|
@@ -592,18 +617,16 @@
|
|
|
592
617
|
alternate: undefined,
|
|
593
618
|
effectTag: EFFECT_TAGS.PLACEMENT,
|
|
594
619
|
};
|
|
595
|
-
} else if (oldFiber) {
|
|
596
|
-
oldFiber.effectTag = EFFECT_TAGS.DELETION;
|
|
597
|
-
vars.deletions.push(oldFiber);
|
|
598
620
|
}
|
|
599
621
|
|
|
600
|
-
|
|
601
|
-
oldFiber =
|
|
602
|
-
|
|
622
|
+
oldFibersMap.forEach((oldFiber) => {
|
|
623
|
+
oldFiber.effectTag = EFFECT_TAGS.DELETION;
|
|
624
|
+
vars.deletions.push(oldFiber);
|
|
625
|
+
});
|
|
603
626
|
|
|
604
627
|
if (index === 0) {
|
|
605
628
|
wipFiber.child = newFiber;
|
|
606
|
-
} else if (
|
|
629
|
+
} else if (prevSibling) {
|
|
607
630
|
prevSibling.sibling = newFiber;
|
|
608
631
|
}
|
|
609
632
|
|
|
@@ -678,9 +701,7 @@
|
|
|
678
701
|
commitRoot();
|
|
679
702
|
}
|
|
680
703
|
|
|
681
|
-
|
|
682
|
-
requestIdleCallback(workLoop, { timeout: 100 });
|
|
683
|
-
}
|
|
704
|
+
requestIdleCallback(workLoop);
|
|
684
705
|
};
|
|
685
706
|
|
|
686
707
|
requestIdleCallback(workLoop);
|
package/package.json
CHANGED
package/src/lib/commits.js
CHANGED
|
@@ -22,9 +22,7 @@ const commitRoot = () => {
|
|
|
22
22
|
* @returns The function does not return anything, it performs side effects by manipulating the DOM.
|
|
23
23
|
*/
|
|
24
24
|
const commitWork = (fiber) => {
|
|
25
|
-
if (!fiber)
|
|
26
|
-
return
|
|
27
|
-
}
|
|
25
|
+
if (!fiber) return
|
|
28
26
|
|
|
29
27
|
let domParentFiber = fiber.parent
|
|
30
28
|
while (!domParentFiber.dom) {
|
|
@@ -37,15 +35,19 @@ const commitWork = (fiber) => {
|
|
|
37
35
|
domParent.appendChild(fiber.dom)
|
|
38
36
|
}
|
|
39
37
|
runEffects(fiber)
|
|
40
|
-
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (fiber.effectTag === EFFECT_TAGS.UPDATE) {
|
|
41
41
|
cancelEffects(fiber)
|
|
42
42
|
if (fiber.dom != undefined) {
|
|
43
43
|
updateDom(fiber.dom, fiber.alternate.props, fiber.props)
|
|
44
44
|
}
|
|
45
45
|
runEffects(fiber)
|
|
46
|
-
}
|
|
47
|
-
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (fiber.effectTag === EFFECT_TAGS.DELETION) {
|
|
48
49
|
commitDeletion(fiber, domParent)
|
|
50
|
+
cancelEffects(fiber)
|
|
49
51
|
return
|
|
50
52
|
}
|
|
51
53
|
|
|
@@ -61,11 +63,10 @@ const commitWork = (fiber) => {
|
|
|
61
63
|
* @param domParent - The parent DOM element from which the fiber's DOM element needs to be removed.
|
|
62
64
|
*/
|
|
63
65
|
const commitDeletion = (fiber, domParent) => {
|
|
64
|
-
if (fiber
|
|
66
|
+
if (fiber.dom) {
|
|
65
67
|
domParent.removeChild(fiber.dom)
|
|
66
|
-
} else
|
|
68
|
+
} else {
|
|
67
69
|
commitDeletion(fiber.child, domParent)
|
|
68
70
|
}
|
|
69
71
|
}
|
|
70
|
-
|
|
71
72
|
export { commitDeletion, commitWork, commitRoot }
|
package/src/lib/createElement.js
CHANGED
|
@@ -47,10 +47,16 @@ const cloneElement = (element, props) => {
|
|
|
47
47
|
|
|
48
48
|
const createElement = (type, props, ...children) => {
|
|
49
49
|
children = childArray(children, [])
|
|
50
|
+
const key =
|
|
51
|
+
props && props.key
|
|
52
|
+
? props.key
|
|
53
|
+
: `${type}-${Math.random().toString(36).substring(2, 9)}`
|
|
54
|
+
|
|
50
55
|
return {
|
|
51
56
|
type,
|
|
52
57
|
props: {
|
|
53
58
|
...props,
|
|
59
|
+
key,
|
|
54
60
|
children: children.map((child) =>
|
|
55
61
|
typeof child === STRINGS.object ? child : createTextElement(child),
|
|
56
62
|
),
|
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
|
-
|
|
3
|
+
import { createElement } from './createElement'
|
|
4
4
|
/**
|
|
5
5
|
* @description The function creates a state.
|
|
6
6
|
* @param initial - The initial value of the state for the hook.
|
|
@@ -14,24 +14,19 @@ const useStore = (initial) => {
|
|
|
14
14
|
vars.wipFiber.alternate.hooks[vars.hookIndex]
|
|
15
15
|
const hook = {
|
|
16
16
|
state: oldHook ? oldHook.state : initial,
|
|
17
|
-
queue: [],
|
|
17
|
+
queue: oldHook ? [...oldHook.queue] : [],
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
actions.forEach((action) => {
|
|
20
|
+
hook.queue.forEach((action) => {
|
|
22
21
|
hook.state =
|
|
23
22
|
typeof action === STRINGS.function ? action(hook.state) : action
|
|
24
23
|
})
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
* and setting up a new work-in-progress root.
|
|
29
|
-
* @param action - The `action` parameter is an object that represents a state update to be performed
|
|
30
|
-
* on a component. It contains information about the type of update to be performed and any new data
|
|
31
|
-
* that needs to be applied to the component's state.
|
|
32
|
-
*/
|
|
25
|
+
hook.queue = []
|
|
26
|
+
|
|
33
27
|
const setState = (action) => {
|
|
34
28
|
hook.queue.push(action)
|
|
29
|
+
|
|
35
30
|
vars.wipRoot = {
|
|
36
31
|
dom: vars.currentRoot.dom,
|
|
37
32
|
props: vars.currentRoot.props,
|
|
@@ -45,6 +40,7 @@ const useStore = (initial) => {
|
|
|
45
40
|
vars.wipFiber.hooks.push(hook)
|
|
46
41
|
vars.hookIndex++
|
|
47
42
|
}
|
|
43
|
+
|
|
48
44
|
return [hook.state, setState]
|
|
49
45
|
}
|
|
50
46
|
|
|
@@ -84,6 +80,36 @@ const useEffect = (callback, deps) => {
|
|
|
84
80
|
}
|
|
85
81
|
}
|
|
86
82
|
|
|
83
|
+
/**
|
|
84
|
+
* The `useQuery` function is a custom hook in JavaScript that retrieves query parameters from the URL
|
|
85
|
+
* and stores them in a hook for easy access.
|
|
86
|
+
* @returns The `useQuery` function returns the `query` property of the `hook` object.
|
|
87
|
+
*/
|
|
88
|
+
const useQuery = () => {
|
|
89
|
+
const oldHook =
|
|
90
|
+
vars.wipFiber.alternate &&
|
|
91
|
+
vars.wipFiber.alternate.hooks &&
|
|
92
|
+
vars.wipFiber.alternate.hooks[vars.hookIndex]
|
|
93
|
+
|
|
94
|
+
const hasOld = oldHook ? oldHook : undefined
|
|
95
|
+
|
|
96
|
+
const urlSearchParams = new URLSearchParams(window.location.search)
|
|
97
|
+
const params = Object.fromEntries(urlSearchParams.entries())
|
|
98
|
+
const Query = hasOld ? hasOld : params
|
|
99
|
+
|
|
100
|
+
const hook = {
|
|
101
|
+
type: RYUNIX_TYPES.RYUNIX_URL_QUERY,
|
|
102
|
+
query: Query,
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (vars.wipFiber.hooks) {
|
|
106
|
+
vars.wipFiber.hooks.push(hook)
|
|
107
|
+
vars.hookIndex++
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return hook.query
|
|
111
|
+
}
|
|
112
|
+
|
|
87
113
|
const useRef = (initial) => {
|
|
88
114
|
const oldHook =
|
|
89
115
|
vars.wipFiber.alternate &&
|
|
@@ -155,40 +181,31 @@ const useRouter = (routes) => {
|
|
|
155
181
|
}
|
|
156
182
|
}, [])
|
|
157
183
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* The `useQuery` function is a custom hook in JavaScript that retrieves query parameters from the URL
|
|
166
|
-
* and stores them in a hook for easy access.
|
|
167
|
-
* @returns The `useQuery` function returns the `query` property of the `hook` object.
|
|
168
|
-
*/
|
|
169
|
-
const useQuery = () => {
|
|
170
|
-
const oldHook =
|
|
171
|
-
vars.wipFiber.alternate &&
|
|
172
|
-
vars.wipFiber.alternate.hooks &&
|
|
173
|
-
vars.wipFiber.alternate.hooks[vars.hookIndex]
|
|
174
|
-
|
|
175
|
-
const hasOld = oldHook ? oldHook : undefined
|
|
184
|
+
let currentRoute = routes.find((route) => route.path === location)
|
|
185
|
+
if (!currentRoute) {
|
|
186
|
+
currentRoute = {
|
|
187
|
+
component: routes.find((route) => route.NotFound)?.NotFound || null,
|
|
188
|
+
}
|
|
189
|
+
}
|
|
176
190
|
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
const Query = hasOld ? hasOld : params
|
|
191
|
+
const Children = () =>
|
|
192
|
+
currentRoute.component ? currentRoute.component : null
|
|
180
193
|
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
query: Query,
|
|
184
|
-
}
|
|
194
|
+
const NavLink = ({ to, ...props }) => {
|
|
195
|
+
const { children, ...restProps } = props
|
|
185
196
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
197
|
+
const NewProps = {
|
|
198
|
+
href: to,
|
|
199
|
+
onClick: (e) => {
|
|
200
|
+
e.preventDefault()
|
|
201
|
+
navigate(to)
|
|
202
|
+
},
|
|
203
|
+
...restProps,
|
|
204
|
+
}
|
|
205
|
+
return createElement('a', NewProps, children)
|
|
189
206
|
}
|
|
190
207
|
|
|
191
|
-
return
|
|
208
|
+
return { Children, navigate, NavLink }
|
|
192
209
|
}
|
|
193
210
|
|
|
194
211
|
export {
|
package/src/lib/reconciler.js
CHANGED
|
@@ -1,19 +1,5 @@
|
|
|
1
1
|
import { EFFECT_TAGS, vars } from '../utils/index'
|
|
2
2
|
|
|
3
|
-
const isPropsChanged = (prevProps, nextProps) => {
|
|
4
|
-
for (let key in prevProps) {
|
|
5
|
-
if (prevProps[key] !== nextProps[key]) {
|
|
6
|
-
return true
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
for (let key in nextProps) {
|
|
10
|
-
if (!(key in prevProps)) {
|
|
11
|
-
return true
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
return false
|
|
15
|
-
}
|
|
16
|
-
|
|
17
3
|
/**
|
|
18
4
|
* This function reconciles the children of a fiber node with a new set of elements, creating new
|
|
19
5
|
* fibers for new elements, updating existing fibers for elements with the same type, and marking old
|
|
@@ -26,24 +12,33 @@ const isPropsChanged = (prevProps, nextProps) => {
|
|
|
26
12
|
const reconcileChildren = (wipFiber, elements) => {
|
|
27
13
|
let index = 0
|
|
28
14
|
let oldFiber = wipFiber.alternate && wipFiber.alternate.child
|
|
29
|
-
let prevSibling
|
|
15
|
+
let prevSibling = null
|
|
16
|
+
|
|
17
|
+
const oldFibersMap = new Map()
|
|
18
|
+
while (oldFiber) {
|
|
19
|
+
const oldKey = oldFiber.props.key || oldFiber.type
|
|
20
|
+
oldFibersMap.set(oldKey, oldFiber)
|
|
21
|
+
oldFiber = oldFiber.sibling
|
|
22
|
+
}
|
|
30
23
|
|
|
31
|
-
while (index < elements.length
|
|
24
|
+
while (index < elements.length) {
|
|
32
25
|
const element = elements[index]
|
|
26
|
+
const key = element.props.key || element.type
|
|
27
|
+
const oldFiber = oldFibersMap.get(key)
|
|
28
|
+
|
|
33
29
|
let newFiber
|
|
34
|
-
const sameType = oldFiber && element && element.type
|
|
30
|
+
const sameType = oldFiber && element && element.type === oldFiber.type
|
|
35
31
|
|
|
36
32
|
if (sameType) {
|
|
37
33
|
newFiber = {
|
|
38
|
-
type: oldFiber
|
|
34
|
+
type: oldFiber.type,
|
|
39
35
|
props: element.props,
|
|
40
|
-
dom: oldFiber
|
|
36
|
+
dom: oldFiber.dom,
|
|
41
37
|
parent: wipFiber,
|
|
42
38
|
alternate: oldFiber,
|
|
43
|
-
effectTag:
|
|
44
|
-
? EFFECT_TAGS.UPDATE
|
|
45
|
-
: null,
|
|
39
|
+
effectTag: EFFECT_TAGS.UPDATE,
|
|
46
40
|
}
|
|
41
|
+
oldFibersMap.delete(key)
|
|
47
42
|
} else if (element) {
|
|
48
43
|
newFiber = {
|
|
49
44
|
type: element.type,
|
|
@@ -53,18 +48,16 @@ const reconcileChildren = (wipFiber, elements) => {
|
|
|
53
48
|
alternate: undefined,
|
|
54
49
|
effectTag: EFFECT_TAGS.PLACEMENT,
|
|
55
50
|
}
|
|
56
|
-
} else if (oldFiber) {
|
|
57
|
-
oldFiber.effectTag = EFFECT_TAGS.DELETION
|
|
58
|
-
vars.deletions.push(oldFiber)
|
|
59
51
|
}
|
|
60
52
|
|
|
61
|
-
|
|
62
|
-
oldFiber =
|
|
63
|
-
|
|
53
|
+
oldFibersMap.forEach((oldFiber) => {
|
|
54
|
+
oldFiber.effectTag = EFFECT_TAGS.DELETION
|
|
55
|
+
vars.deletions.push(oldFiber)
|
|
56
|
+
})
|
|
64
57
|
|
|
65
58
|
if (index === 0) {
|
|
66
59
|
wipFiber.child = newFiber
|
|
67
|
-
} else if (
|
|
60
|
+
} else if (prevSibling) {
|
|
68
61
|
prevSibling.sibling = newFiber
|
|
69
62
|
}
|
|
70
63
|
|
package/src/lib/render.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
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) => {
|
|
11
18
|
vars.wipRoot = {
|
|
@@ -15,20 +22,24 @@ const render = (element, container) => {
|
|
|
15
22
|
},
|
|
16
23
|
alternate: vars.currentRoot,
|
|
17
24
|
}
|
|
25
|
+
|
|
18
26
|
vars.deletions = []
|
|
19
27
|
vars.nextUnitOfWork = vars.wipRoot
|
|
20
28
|
}
|
|
21
29
|
|
|
22
30
|
/**
|
|
23
|
-
*
|
|
24
|
-
* @
|
|
25
|
-
* @param
|
|
26
|
-
* for the root element.
|
|
31
|
+
* Initializes the application by creating a reference to a DOM element with the specified ID and rendering the main component.
|
|
32
|
+
* @function init
|
|
33
|
+
* @param {Object} MainElement - The main component to render, typically the root component of the application.
|
|
34
|
+
* @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.
|
|
35
|
+
* @example
|
|
36
|
+
* Ryunix.init(App, "__ryunix"); // Initializes and renders the App component into the <div id="__ryunix"></div> element.
|
|
37
|
+
* @description This function retrieves the container element by its ID and invokes the `render` function to render the main component into it.
|
|
27
38
|
*/
|
|
28
|
-
const init = (root) => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
const init = (MainElement, root = '__ryunix') => {
|
|
40
|
+
vars.containerRoot = document.getElementById(root)
|
|
41
|
+
|
|
42
|
+
render(MainElement, vars.containerRoot)
|
|
32
43
|
}
|
|
33
44
|
|
|
34
45
|
export { render, init }
|