@unsetsoft/ryunixjs 1.0.0-alpha.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ import { vars } from '../utils/index'
2
+
3
+ /**
4
+ * The function renders an element into a container using a work-in-progress root.
5
+ * @param element - The element parameter is the component or element that needs to be rendered in the
6
+ * container. It could be a Ryunix component or a DOM element.
7
+ * @param container - The container parameter is the DOM element where the rendered element will be
8
+ * appended to. this parameter is optional if you use createRoot().
9
+ */
10
+ const render = (element, container) => {
11
+ vars.wipRoot = {
12
+ dom: vars.containerRoot || container,
13
+ props: {
14
+ children: [element],
15
+ },
16
+ alternate: vars.currentRoot,
17
+ }
18
+ vars.deletions = []
19
+ vars.nextUnitOfWork = vars.wipRoot
20
+ }
21
+
22
+ /**
23
+ * @description The function creates a reference to a DOM element with the specified ID. This will be used to initialize the app.
24
+ * @example Ryunix.init("root") -> <div id="root" />
25
+ * @param root - The parameter "root" is the id of the HTML element that will serve as the container
26
+ * for the root element.
27
+ */
28
+ const init = (root) => {
29
+ const rootElement = root || '__ryunix'
30
+ vars.containerRoot = document.getElementById(rootElement)
31
+ return this
32
+ }
33
+
34
+ export { render, init }
@@ -0,0 +1,61 @@
1
+ import { commitRoot } from './commits'
2
+ import { updateFunctionComponent, updateHostComponent } from './components'
3
+ import { vars } from '../utils/index'
4
+
5
+ /**
6
+ * This function uses requestIdleCallback to perform work on a fiber tree until it is complete or the
7
+ * browser needs to yield to other tasks.
8
+ * @param deadline - The `deadline` parameter is an object that represents the amount of time the
9
+ * browser has to perform work before it needs to handle other tasks. It has a `timeRemaining()` method
10
+ * that returns the amount of time remaining before the deadline is reached. The `shouldYield` variable
11
+ * is used to determine
12
+ */
13
+ const workLoop = (deadline) => {
14
+ let shouldYield = false
15
+ while (vars.nextUnitOfWork && !shouldYield) {
16
+ vars.nextUnitOfWork = performUnitOfWork(vars.nextUnitOfWork)
17
+ shouldYield = deadline.timeRemaining() < 1
18
+ }
19
+
20
+ if (!vars.nextUnitOfWork && vars.wipRoot) {
21
+ commitRoot()
22
+ }
23
+
24
+ requestIdleCallback(workLoop)
25
+ }
26
+
27
+ requestIdleCallback(workLoop)
28
+
29
+ /**
30
+ * The function performs a unit of work by updating either a function component or a host component and
31
+ * returns the next fiber to be processed.
32
+ * @param fiber - A fiber is a unit of work in Ryunix that represents a component and its state. It
33
+ * contains information about the component's type, props, and children, as well as pointers to its
34
+ * parent, child, and sibling fibers. The `performUnitOfWork` function takes a fiber as a parameter and
35
+ * performs work
36
+ * @returns The function `performUnitOfWork` returns the next fiber to be processed. If the current
37
+ * fiber has a child, it returns the child. Otherwise, it looks for the next sibling of the current
38
+ * fiber. If there are no more siblings, it goes up the tree to the parent and looks for the next
39
+ * sibling of the parent. The function returns `undefined` if there are no more fibers to process.
40
+ */
41
+ const performUnitOfWork = (fiber) => {
42
+ const isFunctionComponent = fiber.type instanceof Function
43
+ if (isFunctionComponent) {
44
+ updateFunctionComponent(fiber)
45
+ } else {
46
+ updateHostComponent(fiber)
47
+ }
48
+ if (fiber.child) {
49
+ return fiber.child
50
+ }
51
+ let nextFiber = fiber
52
+ while (nextFiber) {
53
+ if (nextFiber.sibling) {
54
+ return nextFiber.sibling
55
+ }
56
+ nextFiber = nextFiber.parent
57
+ }
58
+ return undefined
59
+ }
60
+
61
+ export { performUnitOfWork, workLoop }
package/src/main.js ADDED
@@ -0,0 +1,15 @@
1
+ import Ryunix from './lib/index.js'
2
+ export {
3
+ useStore,
4
+ useEffect,
5
+ useQuery,
6
+ useRef,
7
+ useMemo,
8
+ useCallback,
9
+ useRouter,
10
+ Fragment,
11
+ } from './lib/index.js'
12
+
13
+ window.Ryunix = Ryunix
14
+
15
+ export default Ryunix
@@ -0,0 +1,41 @@
1
+ const vars = {
2
+ containerRoot: undefined,
3
+ nextUnitOfWork: undefined,
4
+ currentRoot: undefined,
5
+ wipRoot: undefined,
6
+ deletions: undefined,
7
+ wipFiber: undefined,
8
+ hookIndex: undefined,
9
+ }
10
+
11
+ const reg = /[A-Z]/g
12
+
13
+ const RYUNIX_TYPES = Object.freeze({
14
+ TEXT_ELEMENT: Symbol('text.element'),
15
+ RYUNIX_EFFECT: Symbol('ryunix.effect'),
16
+ RYUNIX_MEMO: Symbol('ryunix.memo'),
17
+ RYUNIX_URL_QUERY: Symbol('ryunix.urlQuery'),
18
+ RYUNIX_REF: Symbol('ryunix.ref'),
19
+ })
20
+
21
+ const STRINGS = Object.freeze({
22
+ object: 'object',
23
+ function: 'function',
24
+ style: 'ryunix-style',
25
+ className: 'ryunix-class',
26
+ children: 'children',
27
+ boolean: 'boolean',
28
+ })
29
+
30
+ const OLD_STRINGS = Object.freeze({
31
+ style: 'style',
32
+ className: 'className',
33
+ })
34
+
35
+ const EFFECT_TAGS = Object.freeze({
36
+ PLACEMENT: Symbol(),
37
+ UPDATE: Symbol(),
38
+ DELETION: Symbol(),
39
+ })
40
+
41
+ export { vars, reg, RYUNIX_TYPES, EFFECT_TAGS, STRINGS, OLD_STRINGS }
package/lib/component.js DELETED
@@ -1,16 +0,0 @@
1
- import { reconcile } from "./reconciler";
2
- export class Component {
3
- constructor(props) {
4
- this.props = props;
5
- this.state = this.state || {};
6
- }
7
- setState(partialState) {
8
- this.state = Object.assign({}, this.state, partialState);
9
- updateInstance(this.__internalInstance);
10
- }
11
- }
12
- function updateInstance(internalInstance) {
13
- const parentDom = internalInstance.dom.parentNode;
14
- const element = internalInstance.element;
15
- reconcile(parentDom, internalInstance, element);
16
- }
package/lib/dom-utils.js DELETED
@@ -1,25 +0,0 @@
1
- /**
2
- * This function updates the properties and event listeners of a DOM element based on the previous and
3
- * next props passed as arguments.
4
- * @param dom - The DOM element that needs to be updated with new properties.
5
- * @param prevProps - An object representing the previous properties of a DOM element.
6
- * @param nextProps - An object containing the new props that need to be updated on the DOM element.
7
- */
8
- export function updateDomProperties(dom, prevProps, nextProps) {
9
- const isEvent = name => name.startsWith("on");
10
- const isAttribute = name => !isEvent(name) && name != "children";
11
- Object.keys(prevProps).filter(isEvent).forEach(name => {
12
- const eventType = name.toLowerCase().substring(2);
13
- dom.removeEventListener(eventType, prevProps[name]);
14
- });
15
- Object.keys(prevProps).filter(isAttribute).forEach(name => {
16
- dom[name] = null;
17
- });
18
- Object.keys(nextProps).filter(isAttribute).forEach(name => {
19
- dom[name] = nextProps[name];
20
- });
21
- Object.keys(nextProps).filter(isEvent).forEach(name => {
22
- const eventType = name.toLowerCase().substring(2);
23
- dom.addEventListener(eventType, nextProps[name]);
24
- });
25
- }
package/lib/element.js DELETED
@@ -1,37 +0,0 @@
1
- const TEXT_ELEMENT = "TEXT";
2
-
3
- /**
4
- * This function creates a new element with the given type, configuration object, and children.
5
- * @param type - The type of the element being created (e.g. "div", "span", "h1", etc.).
6
- * @param configObject - The `configObject` parameter is an object that contains the properties and
7
- * values for the element's attributes. These attributes can include things like `className`, `id`,
8
- * `style`, and any other custom attributes that the user wants to add to the element.
9
- * @param args - The `args` parameter is a rest parameter that allows the function to accept any number
10
- * of additional arguments after the `configObject` parameter. These additional arguments are used as
11
- * children elements for the created element.
12
- * @returns An object with two properties: "type" and "props".
13
- */
14
- export function createElement(type, configObject, ...args) {
15
- const props = Object.assign({}, configObject);
16
- const hasChildren = args.length > 0;
17
- const nodeChildren = hasChildren ? [...args] : [];
18
- props.children = nodeChildren.filter(Boolean).map(c => c instanceof Object ? c : createTextElement(c));
19
- return {
20
- type,
21
- props
22
- };
23
- }
24
-
25
- /**
26
- * The function creates a text element with a given node value and an empty array of children.
27
- * @param nodeValue - The value of the text node that will be created.
28
- * @returns The function `createTextElement` is returning an element object with a `nodeValue` property
29
- * and an empty `children` array. This element object represents a text node in the virtual DOM.
30
- */
31
- function createTextElement(nodeValue) {
32
- return createElement(TEXT_ELEMENT, {
33
- nodeValue,
34
- children: []
35
- });
36
- }
37
- export { TEXT_ELEMENT };
package/lib/reconciler.js DELETED
@@ -1,89 +0,0 @@
1
- import { updateDomProperties } from "./dom-utils";
2
- import { TEXT_ELEMENT } from "./element";
3
- let rootInstance = null;
4
- export function render(element, parentDom) {
5
- const prevInstance = rootInstance;
6
- const nextInstance = reconcile(parentDom, prevInstance, element);
7
- rootInstance = nextInstance;
8
- }
9
- export function reconcile(parentDom, instance, element) {
10
- if (instance === null) {
11
- const newInstance = instantiate(element);
12
- parentDom.appendChild(newInstance.dom);
13
- return newInstance;
14
- } else if (element == null) {
15
- parentDom.removeChild(instance.dom);
16
- return null;
17
- } else if (instance.element.type !== element.type) {
18
- const newInstance = instantiate(element);
19
- parentDom.replaceChild(newInstance.dom, instance.dom);
20
- return newInstance;
21
- } else if (typeof element.type === "string") {
22
- instance.childInstances = reconcileChildren(instance, element);
23
- instance.element = element;
24
- return instance;
25
- } else {
26
- instance.publicInstance.props = element.props;
27
- const childElement = instance.publicInstance.render();
28
- const oldChildInstance = instance.childInstance;
29
- const childInstance = reconcile(parentDom, oldChildInstance, childElement);
30
- instance.dom = childInstance.dom;
31
- instance.childInstance = childInstance;
32
- instance.element = element;
33
- return instance;
34
- }
35
- }
36
- function instantiate(element) {
37
- const { type, props } = element;
38
- const isDomElement = typeof type === "string";
39
- if (isDomElement) {
40
- const isTextElement = type === TEXT_ELEMENT;
41
- const dom = isTextElement
42
- ? document.createTextNode("")
43
- : document.createElement(type);
44
- updateDomProperties(dom, [], props);
45
- const childElements = props.children || [];
46
- const childInstances = childElements.map(instantiate);
47
- const childDoms = childInstances.map((childInstance) => childInstance.dom);
48
- childDoms.forEach((childDom) => dom.appendChild(childDom));
49
- const instance = {
50
- dom,
51
- element,
52
- childInstances,
53
- };
54
- return instance;
55
- } else {
56
- const instance = {};
57
- const publicInstance = createPublicInstance(element, instance);
58
- const childElement = publicInstance.render();
59
- const childInstance = instantiate(childElement);
60
- const dom = childInstance.dom;
61
- Object.assign(instance, {
62
- dom,
63
- element,
64
- childInstance,
65
- publicInstance,
66
- });
67
- return instance;
68
- }
69
- }
70
- function createPublicInstance(element, internalInstance) {
71
- const { type, props } = element;
72
- const publicInstance = new type(props);
73
- publicInstance.__internalInstance = internalInstance;
74
- return publicInstance;
75
- }
76
- function reconcileChildren(instance, element) {
77
- const dom = instance.dom;
78
- const childInstances = instance.childInstances;
79
- const nextChildElements = element.props.children || [];
80
- const newChildInstances = [];
81
- const count = Math.max(childInstances.length, nextChildElements.length);
82
- for (let i = 0; i < count; i++) {
83
- const childInstance = childInstances[i];
84
- const childElement = nextChildElements[i];
85
- const newChildInstance = reconcile(dom, childInstance, childElement);
86
- newChildInstances.push(newChildInstance);
87
- }
88
- return newChildInstances.filter((instance) => instance != null);
89
- }
package/lib/ryunix.js DELETED
@@ -1,9 +0,0 @@
1
- import { render } from "./reconciler";
2
- import { createElement } from "./element";
3
- import { Component } from "./component";
4
- export { createElement, render, Component };
5
- export default {
6
- render,
7
- createElement,
8
- Component,
9
- };