@unsetsoft/ryunixjs 1.1.5 → 1.1.6
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 +867 -1
- package/dist/Ryunix.min.js +1 -0
- package/package.json +8 -9
- package/src/lib/commits.js +0 -72
- package/src/lib/components.js +0 -41
- package/src/lib/createElement.js +0 -84
- package/src/lib/dom.js +0 -96
- package/src/lib/effects.js +0 -55
- package/src/lib/hooks.js +0 -288
- package/src/lib/index.js +0 -39
- package/src/lib/reconciler.js +0 -69
- package/src/lib/render.js +0 -45
- package/src/lib/workers.js +0 -61
- package/src/main.js +0 -15
- package/src/utils/index.js +0 -42
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("lodash")):"function"==typeof define&&define.amd?define(["exports","lodash"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Ryunix={},e.lodash)}(this,(function(e,t){"use strict";let o={containerRoot:{},nextUnitOfWork:{},currentRoot:{},wipRoot:{},deletions:[],wipFiber:{},hookIndex:0};const n=/[A-Z]/g,r=Object.freeze({TEXT_ELEMENT:Symbol("text.element"),Ryunix_ELEMENT:Symbol("ryunix.element"),RYUNIX_EFFECT:Symbol("ryunix.effect"),RYUNIX_MEMO:Symbol("ryunix.memo"),RYUNIX_URL_QUERY:Symbol("ryunix.urlQuery"),RYUNIX_REF:Symbol("ryunix.ref"),RYUNIX_STORE:Symbol("ryunix.store"),RYUNIX_REDUCE:Symbol("ryunix.reduce")}),i=Object.freeze({object:"object",function:"function",style:"ryunix-style",className:"ryunix-class",children:"children",boolean:"boolean",string:"string"}),s=Object.freeze({style:"style",className:"className"}),a=Object.freeze({PLACEMENT:Symbol("ryunix.reconciler.status.placement").toString(),UPDATE:Symbol("ryunix.reconciler.status.update").toString(),DELETION:Symbol("ryunix.reconciler.status.deletion").toString()}),l=(e,t)=>(t=t||[],null==e||typeof e==i.boolean||(Array.isArray(e)?e.some((e=>{l(e,t)})):t.push(e)),t),c=(e,t,...o)=>{o=l(o,[]);const n=t&&t.key?t.key:`${r.Ryunix_ELEMENT.toString()}-${Math.random().toString(36).substring(2,9)}`;return{type:e,props:{...t,key:n,children:o.map((e=>typeof e===i.object?e:p(e)))}}},p=e=>({type:r.TEXT_ELEMENT,props:{nodeValue:e,children:[]}}),u=(e,t)=>{o.wipRoot={dom:t,props:{children:[e]},alternate:o.currentRoot},o.deletions=[],o.nextUnitOfWork=o.wipRoot},d=e=>{const t=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],n={state:t?t.state:e,queue:t?[...t.queue]:[]};n.queue.forEach((e=>{n.state=typeof e===i.function?e(n.state):e})),n.queue=[];return o.wipFiber&&o.wipFiber.hooks&&(o.wipFiber.hooks.push(n),o.hookIndex++),[n.state,e=>{n.queue.push(e),o.wipRoot={dom:o.currentRoot.dom,props:{...o.currentRoot.props},alternate:o.currentRoot},o.nextUnitOfWork=o.wipRoot,o.deletions=[]}]},f=(e,n)=>{const i=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],s={type:r.RYUNIX_EFFECT,deps:n};i&&t.isEqual(i.deps,s.deps)||e(),o.wipFiber.hooks&&(o.wipFiber.hooks.push(s),o.hookIndex++)},m=(e,n)=>{const i=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],s={type:r.RYUNIX_MEMO,value:null,deps:n};return i&&t.isEqual(i.deps,s.deps)?s.value=i.value:s.value=e(),o.wipFiber.hooks&&(o.wipFiber.hooks.push(s),o.hookIndex++),s.value},h=()=>{const e=new URLSearchParams(window.location.search),t={};for(let[o,n]of e.entries())t[o]=n;return t},y=e=>e.startsWith("on"),b=e=>e!==i.children&&!y(e),E=(e,t)=>o=>e[o]!==t[o],w=e=>t=>!(t in e),k=e=>{e.hooks&&e.hooks.filter((e=>e.tag===r.RYUNIX_EFFECT&&e.cancel)).forEach((e=>{e.cancel()}))},R=e=>{e.hooks&&e.hooks.filter((e=>e.tag===r.RYUNIX_EFFECT&&e.effect)).forEach((e=>{e.cancel=e.effect()}))},x=e=>{const t=e.type==r.TEXT_ELEMENT?document.createTextNode(""):document.createElement(e.type);return F(t,{},e.props),t},F=(e,t,o)=>{Object.keys(t).filter(y).filter((e=>w(o)(e)||E(t,o)(e))).forEach((o=>{const n=o.toLowerCase().substring(2);e.removeEventListener(n,t[o])})),Object.keys(t).filter(b).filter(w(o)).forEach((t=>{e[t]=""})),Object.keys(o).filter(b).filter(E(t,o)).forEach((n=>{if(n===i.style)_(e,o["ryunix-style"]);else if(n===s.style)_(e,o.style);else if(n===i.className){if(""===o["ryunix-class"])throw new Error("data-class cannot be empty.");t["ryunix-class"]&&e.classList.remove(...t["ryunix-class"].split(/\s+/)),e.classList.add(...o["ryunix-class"].split(/\s+/))}else if(n===s.className){if(""===o.className)throw new Error("className cannot be empty.");t.className&&e.classList.remove(...t.className.split(/\s+/)),e.classList.add(...o.className.split(/\s+/))}else e[n]=o[n]})),Object.keys(o).filter(y).filter(E(t,o)).forEach((t=>{const n=t.toLowerCase().substring(2);e.addEventListener(n,o[t])}))},_=(e,t)=>{e.style=Object.keys(t).reduce(((e,o)=>e+=`${o.replace(n,(function(e){return"-"+e.toLowerCase()}))}: ${t[o]};`),"")};var N=Object.freeze({__proto__:null,DomStyle:_,createDom:x,updateDom:F});const g=()=>{o.deletions.forEach(T),o.wipRoot&&o.wipRoot.child&&(T(o.wipRoot.child),o.currentRoot=o.wipRoot),o.wipRoot=void 0},T=e=>{if(!e)return;let t=e.parent;for(;!t.dom;)t=t.parent;const o=t.dom;if(e.effectTag===a.PLACEMENT&&null!=e.dom)o.appendChild(e.dom),R(e);else if(e.effectTag===a.UPDATE&&null!=e.dom)k(e),F(e.dom,e.alternate.props,e.props),R(e);else if(e.effectTag===a.DELETION)return v(e,o),void k(e);T(e.child),T(e.sibling)},v=(e,t)=>{e.dom?t.removeChild(e.dom):v(e.child,t)};var O=Object.freeze({__proto__:null,commitDeletion:v,commitRoot:g,commitWork:T});const I=(e,t)=>{let n=0,r=e.alternate&&e.alternate.child,i=null;const s=new Map;for(;r;){const e=r.props.key||r.type;s.set(e,r),r=r.sibling}for(;n<t.length;){const o=t[n],r=o.props.key||o.type,l=s.get(r);let c;l&&o&&o.type===l.type?(c={type:l.type,props:o.props,dom:l.dom,parent:e,alternate:l,effectTag:a.UPDATE},s.delete(r)):o&&(c={type:o.type,props:o.props,dom:void 0,parent:e,alternate:void 0,effectTag:a.PLACEMENT}),0===n?e.child=c:i&&(i.sibling=c),i=c,n++}s.forEach((e=>{e.effectTag=a.DELETION,o.deletions.push(e)}))};var L=Object.freeze({__proto__:null,reconcileChildren:I});const U=e=>{o.wipFiber=e,o.hookIndex=0,o.wipFiber.hooks=[];const t=e.type(e.props);let n=Array.isArray(t)?t:[t];I(e,n)},C=e=>{e.dom||(e.dom=x(e)),I(e,e.props.children)};var S=Object.freeze({__proto__:null,updateFunctionComponent:U,updateHostComponent:C});const j=e=>{let t=!1;for(;o.nextUnitOfWork&&!t;)o.nextUnitOfWork=M(o.nextUnitOfWork),t=e.timeRemaining()<1;!o.nextUnitOfWork&&o.wipRoot&&g(),requestIdleCallback(j)};requestIdleCallback(j);const M=e=>{if(e.type instanceof Function?U(e):C(e),e.child)return e.child;let t=e;for(;t;){if(t.sibling)return t.sibling;t=t.parent}};var X={createElement:c,render:u,init:(e,t="__ryunix")=>{o.containerRoot=document.getElementById(t),u(e,o.containerRoot)},Fragment:e=>e.children,Dom:N,Workers:Object.freeze({__proto__:null,performUnitOfWork:M,workLoop:j}),Reconciler:L,Components:S,Commits:O};window.Ryunix=X,e.default=X,e.useCallback=(e,t)=>m((()=>e),t),e.useEffect=f,e.useMemo=m,e.useQuery=h,e.useRef=e=>{const t=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],n={type:r.RYUNIX_REF,value:t?t.value:{current:e}};return o.wipFiber.hooks&&(o.wipFiber.hooks.push(n),o.hookIndex++),n.value},e.useRouter=e=>{const[t,o]=d(window.location.pathname),n=(e,t)=>{const o=t.split("?")[0],r=e.find((e=>e.NotFound)),i=r?{route:{component:r.NotFound},params:{}}:{route:{component:null},params:{}};for(const r of e){if(r.subRoutes){const e=n(r.subRoutes,t);if(e)return e}if("*"===r.path)return i;if(!r.path||"string"!=typeof r.path){console.warn("Invalid route detected:",r),console.info("if you are using { NotFound: NotFound } please add { path: '*', NotFound: NotFound }");continue}const e=[],s=new RegExp(`^${r.path.replace(/:\w+/g,(t=>(e.push(t.substring(1)),"([^/]+)")))}$`),a=o.match(s);if(a){return{route:r,params:e.reduce(((e,t,o)=>(e[t]=a[o+1],e)),{})}}}return i},r=e=>{window.history.pushState({},"",e),s(e)},s=e=>{const t=e.split("?")[0];o(t)};f((()=>{const e=()=>s(window.location.pathname);return window.addEventListener("popstate",e),()=>window.removeEventListener("popstate",e)}),[]);const a=n(e,t)||{};return{Children:()=>{const e=h(),{route:t}=a;return t&&t.component&&typeof t.component===i.function?t.component({params:a.params||{},query:e}):(console.error("Component not found for current path or the component is not a valid function:",a),null)},NavLink:({to:e,...t})=>c("a",{href:e,onClick:t=>{t.preventDefault(),r(e)},...t},t.children),navigate:r}},e.useStore=d,Object.defineProperty(e,"__esModule",{value:!0})}));
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unsetsoft/ryunixjs",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"main": "./dist/Ryunix.js",
|
|
5
|
+
"main": "./dist/Ryunix.min.js",
|
|
6
6
|
"types": "./dist/Ryunix.d.ts",
|
|
7
7
|
"private": false,
|
|
8
8
|
"bugs": {
|
|
@@ -10,17 +10,17 @@
|
|
|
10
10
|
},
|
|
11
11
|
"homepage": "https://github.com/UnSetSoft/Ryunixjs#readme",
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build:js": "rollup ./src/main.js --file ./dist/Ryunix.js --format umd --name Ryunix --plugin @rollup/plugin-terser",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
13
|
+
"build:js": "rollup ./src/main.js --file ./dist/Ryunix.min.js --format umd --name Ryunix --plugin @rollup/plugin-terser",
|
|
14
|
+
"build": "rollup ./src/main.js --file ./dist/Ryunix.js --format umd --name Ryunix",
|
|
15
|
+
"prepublishOnly": "npm run build:js | npm run build",
|
|
16
16
|
"nightly:release": "npm publish --tag nightly",
|
|
17
17
|
"release": "npm publish",
|
|
18
18
|
"lint": "eslint . --ext .ts --fix --max-warnings=0 --config .eslintrc.js --no-eslintrc"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@rollup/plugin-terser": "
|
|
21
|
+
"@rollup/plugin-terser": "0.4.4",
|
|
22
22
|
"eslint": "8.56.0",
|
|
23
|
-
"lodash": "
|
|
23
|
+
"lodash": "4.17.20",
|
|
24
24
|
"rollup": "4.9.2"
|
|
25
25
|
},
|
|
26
26
|
"engines": {
|
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
"registry": "https://registry.npmjs.org"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
|
-
"dist"
|
|
37
|
-
"src"
|
|
36
|
+
"dist"
|
|
38
37
|
]
|
|
39
38
|
}
|
package/src/lib/commits.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { updateDom } from './dom'
|
|
2
|
-
import { cancelEffects, runEffects } from './effects'
|
|
3
|
-
import { EFFECT_TAGS, vars } from '../utils/index'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* The function commits changes made to the virtual DOM to the actual DOM.
|
|
7
|
-
*/
|
|
8
|
-
const commitRoot = () => {
|
|
9
|
-
vars.deletions.forEach(commitWork)
|
|
10
|
-
if (vars.wipRoot && vars.wipRoot.child) {
|
|
11
|
-
commitWork(vars.wipRoot.child)
|
|
12
|
-
vars.currentRoot = vars.wipRoot
|
|
13
|
-
}
|
|
14
|
-
vars.wipRoot = undefined
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* The function commits changes made to the DOM based on the effect tag of the fiber.
|
|
19
|
-
* @param fiber - A fiber is a unit of work in Ryunix's reconciliation process. It represents a
|
|
20
|
-
* component and its state at a particular point in time. The `commitWork` function takes a fiber as a
|
|
21
|
-
* parameter to commit the changes made during the reconciliation process to the actual DOM.
|
|
22
|
-
* @returns The function does not return anything, it performs side effects by manipulating the DOM.
|
|
23
|
-
*/
|
|
24
|
-
const commitWork = (fiber) => {
|
|
25
|
-
if (!fiber) return
|
|
26
|
-
|
|
27
|
-
let domParentFiber = fiber.parent
|
|
28
|
-
while (!domParentFiber.dom) {
|
|
29
|
-
domParentFiber = domParentFiber.parent
|
|
30
|
-
}
|
|
31
|
-
const domParent = domParentFiber.dom
|
|
32
|
-
|
|
33
|
-
if (fiber.effectTag === EFFECT_TAGS.PLACEMENT) {
|
|
34
|
-
if (fiber.dom != undefined) {
|
|
35
|
-
domParent.appendChild(fiber.dom)
|
|
36
|
-
}
|
|
37
|
-
runEffects(fiber)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (fiber.effectTag === EFFECT_TAGS.UPDATE) {
|
|
41
|
-
cancelEffects(fiber)
|
|
42
|
-
if (fiber.dom != undefined) {
|
|
43
|
-
updateDom(fiber.dom, fiber.alternate.props, fiber.props)
|
|
44
|
-
}
|
|
45
|
-
runEffects(fiber)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (fiber.effectTag === EFFECT_TAGS.DELETION) {
|
|
49
|
-
commitDeletion(fiber, domParent)
|
|
50
|
-
cancelEffects(fiber)
|
|
51
|
-
return
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
commitWork(fiber.child)
|
|
55
|
-
commitWork(fiber.sibling)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* The function removes a fiber's corresponding DOM node from its parent node or recursively removes
|
|
60
|
-
* its child's DOM node until it finds a node to remove.
|
|
61
|
-
* @param fiber - a fiber node in a fiber tree, which represents a component or an element in the Ryunix
|
|
62
|
-
* application.
|
|
63
|
-
* @param domParent - The parent DOM element from which the fiber's DOM element needs to be removed.
|
|
64
|
-
*/
|
|
65
|
-
const commitDeletion = (fiber, domParent) => {
|
|
66
|
-
if (fiber.dom) {
|
|
67
|
-
domParent.removeChild(fiber.dom)
|
|
68
|
-
} else {
|
|
69
|
-
commitDeletion(fiber.child, domParent)
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
export { commitDeletion, commitWork, commitRoot }
|
package/src/lib/components.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { createDom } from './dom'
|
|
2
|
-
import { reconcileChildren } from './reconciler'
|
|
3
|
-
import { vars } from '../utils/index'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* This function updates a function component by setting up a work-in-progress fiber, resetting the
|
|
7
|
-
* hook index, creating an empty hooks array, rendering the component, and reconciling its children.
|
|
8
|
-
* @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
|
|
9
|
-
* contains information about the component, its props, state, and children. In this function, it is
|
|
10
|
-
* used to update the state of the component and its children.
|
|
11
|
-
*/
|
|
12
|
-
const updateFunctionComponent = (fiber) => {
|
|
13
|
-
vars.wipFiber = fiber
|
|
14
|
-
vars.hookIndex = 0
|
|
15
|
-
vars.wipFiber.hooks = []
|
|
16
|
-
const children = fiber.type(fiber.props)
|
|
17
|
-
let childArr = []
|
|
18
|
-
if (Array.isArray(children)) {
|
|
19
|
-
// Fragment results returns array
|
|
20
|
-
childArr = [...children]
|
|
21
|
-
} else {
|
|
22
|
-
// Normal function component returns single root node
|
|
23
|
-
childArr = [children]
|
|
24
|
-
}
|
|
25
|
-
reconcileChildren(fiber, childArr)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* This function updates a host component's DOM element and reconciles its children.
|
|
30
|
-
* @param fiber - A fiber is a unit of work in Ryunix that represents a component and its state. It
|
|
31
|
-
* contains information about the component's type, props, and children, as well as pointers to other
|
|
32
|
-
* fibers in the tree.
|
|
33
|
-
*/
|
|
34
|
-
const updateHostComponent = (fiber) => {
|
|
35
|
-
if (!fiber.dom) {
|
|
36
|
-
fiber.dom = createDom(fiber)
|
|
37
|
-
}
|
|
38
|
-
reconcileChildren(fiber, fiber.props.children)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export { updateFunctionComponent, updateHostComponent }
|
package/src/lib/createElement.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { RYUNIX_TYPES, STRINGS } from '../utils/index'
|
|
2
|
-
|
|
3
|
-
const Fragment = (props) => {
|
|
4
|
-
return props.children
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
const childArray = (children, out) => {
|
|
8
|
-
out = out || []
|
|
9
|
-
if (children == undefined || typeof children == STRINGS.boolean) {
|
|
10
|
-
// pass
|
|
11
|
-
} else if (Array.isArray(children)) {
|
|
12
|
-
children.some((child) => {
|
|
13
|
-
childArray(child, out)
|
|
14
|
-
})
|
|
15
|
-
} else {
|
|
16
|
-
out.push(children)
|
|
17
|
-
}
|
|
18
|
-
return out
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const cloneElement = (element, props) => {
|
|
22
|
-
return {
|
|
23
|
-
...element,
|
|
24
|
-
props: {
|
|
25
|
-
...element.props,
|
|
26
|
-
...props,
|
|
27
|
-
},
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* The function creates a new element with the given type, props, and children.
|
|
33
|
-
* @param type - The type of the element to be created, such as "div", "span", "h1", etc.
|
|
34
|
-
* @param props - The `props` parameter is an object that contains the properties or attributes of the
|
|
35
|
-
* element being created. These properties can include things like `className`, `id`, `style`, and any
|
|
36
|
-
* other custom attributes that the user wants to add to the element. The `props` object is spread
|
|
37
|
-
* using the spread
|
|
38
|
-
* @param children - The `children` parameter is a rest parameter that allows the function to accept
|
|
39
|
-
* any number of arguments after the `props` parameter. These arguments will be treated as children
|
|
40
|
-
* elements of the created element. The `map` function is used to iterate over each child and create a
|
|
41
|
-
* new element if it is not
|
|
42
|
-
* @returns A JavaScript object with a `type` property and a `props` property. The `type` property is
|
|
43
|
-
* set to the `type` argument passed into the function, and the `props` property is an object that
|
|
44
|
-
* includes any additional properties passed in the `props` argument, as well as a `children` property
|
|
45
|
-
* that is an array of any child elements passed in the `...children` argument
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
const createElement = (type, props, ...children) => {
|
|
49
|
-
children = childArray(children, [])
|
|
50
|
-
const key =
|
|
51
|
-
props && props.key
|
|
52
|
-
? props.key
|
|
53
|
-
: `${RYUNIX_TYPES.Ryunix_ELEMENT.toString()}-${Math.random().toString(36).substring(2, 9)}`
|
|
54
|
-
|
|
55
|
-
return {
|
|
56
|
-
type,
|
|
57
|
-
props: {
|
|
58
|
-
...props,
|
|
59
|
-
key,
|
|
60
|
-
children: children.map((child) =>
|
|
61
|
-
typeof child === STRINGS.object ? child : createTextElement(child),
|
|
62
|
-
),
|
|
63
|
-
},
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* The function creates a text element with a given text value.
|
|
69
|
-
* @param text - The text content that will be used to create a new text element.
|
|
70
|
-
* @returns A JavaScript object with a `type` property set to `"TEXT_ELEMENT"` and a `props` property
|
|
71
|
-
* that contains a `nodeValue` property set to the `text` parameter and an empty `children` array.
|
|
72
|
-
*/
|
|
73
|
-
|
|
74
|
-
const createTextElement = (text) => {
|
|
75
|
-
return {
|
|
76
|
-
type: RYUNIX_TYPES.TEXT_ELEMENT,
|
|
77
|
-
props: {
|
|
78
|
-
nodeValue: text,
|
|
79
|
-
children: [],
|
|
80
|
-
},
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export { createElement, createTextElement, Fragment, cloneElement }
|
package/src/lib/dom.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { isEvent, isGone, isNew, isProperty } from './effects'
|
|
2
|
-
import { RYUNIX_TYPES, STRINGS, reg, OLD_STRINGS } from '../utils/index'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The function creates a new DOM element based on the given fiber object and updates its properties.
|
|
6
|
-
* @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
|
|
7
|
-
* contains information about the element type, props, and children of the node.
|
|
8
|
-
* @returns The `createDom` function returns a newly created DOM element based on the `fiber` object
|
|
9
|
-
* passed as an argument. If the `fiber` object represents a text element, a text node is created using
|
|
10
|
-
* `document.createTextNode("")`. Otherwise, a new element is created using
|
|
11
|
-
* `document.createElement(fiber.type)`. The function then calls the `updateDom` function to update the
|
|
12
|
-
* properties of the newly created
|
|
13
|
-
*/
|
|
14
|
-
const createDom = (fiber) => {
|
|
15
|
-
const dom =
|
|
16
|
-
fiber.type == RYUNIX_TYPES.TEXT_ELEMENT
|
|
17
|
-
? document.createTextNode('')
|
|
18
|
-
: document.createElement(fiber.type)
|
|
19
|
-
|
|
20
|
-
updateDom(dom, {}, fiber.props)
|
|
21
|
-
|
|
22
|
-
return dom
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* The function updates the DOM by removing old event listeners and properties, and adding new ones
|
|
27
|
-
* based on the previous and next props.
|
|
28
|
-
* @param dom - The DOM element that needs to be updated with new props.
|
|
29
|
-
* @param prevProps - An object representing the previous props (properties) of a DOM element.
|
|
30
|
-
* @param nextProps - An object containing the new props that need to be updated in the DOM.
|
|
31
|
-
*/
|
|
32
|
-
const updateDom = (dom, prevProps, nextProps) => {
|
|
33
|
-
Object.keys(prevProps)
|
|
34
|
-
.filter(isEvent)
|
|
35
|
-
.filter((key) => isGone(nextProps)(key) || isNew(prevProps, nextProps)(key))
|
|
36
|
-
.forEach((name) => {
|
|
37
|
-
const eventType = name.toLowerCase().substring(2)
|
|
38
|
-
dom.removeEventListener(eventType, prevProps[name])
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
Object.keys(prevProps)
|
|
42
|
-
.filter(isProperty)
|
|
43
|
-
.filter(isGone(nextProps))
|
|
44
|
-
.forEach((name) => {
|
|
45
|
-
dom[name] = ''
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
Object.keys(nextProps)
|
|
49
|
-
.filter(isProperty)
|
|
50
|
-
.filter(isNew(prevProps, nextProps))
|
|
51
|
-
.forEach((name) => {
|
|
52
|
-
if (name === STRINGS.style) {
|
|
53
|
-
DomStyle(dom, nextProps['ryunix-style'])
|
|
54
|
-
} else if (name === OLD_STRINGS.style) {
|
|
55
|
-
DomStyle(dom, nextProps.style)
|
|
56
|
-
} else if (name === STRINGS.className) {
|
|
57
|
-
if (nextProps['ryunix-class'] === '') {
|
|
58
|
-
throw new Error('data-class cannot be empty.')
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
prevProps['ryunix-class'] &&
|
|
62
|
-
dom.classList.remove(...prevProps['ryunix-class'].split(/\s+/))
|
|
63
|
-
dom.classList.add(...nextProps['ryunix-class'].split(/\s+/))
|
|
64
|
-
} else if (name === OLD_STRINGS.className) {
|
|
65
|
-
if (nextProps.className === '') {
|
|
66
|
-
throw new Error('className cannot be empty.')
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
prevProps.className &&
|
|
70
|
-
dom.classList.remove(...prevProps.className.split(/\s+/))
|
|
71
|
-
dom.classList.add(...nextProps.className.split(/\s+/))
|
|
72
|
-
} else {
|
|
73
|
-
dom[name] = nextProps[name]
|
|
74
|
-
}
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
Object.keys(nextProps)
|
|
78
|
-
.filter(isEvent)
|
|
79
|
-
.filter(isNew(prevProps, nextProps))
|
|
80
|
-
.forEach((name) => {
|
|
81
|
-
const eventType = name.toLowerCase().substring(2)
|
|
82
|
-
dom.addEventListener(eventType, nextProps[name])
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const DomStyle = (dom, style) => {
|
|
87
|
-
dom.style = Object.keys(style).reduce((acc, styleName) => {
|
|
88
|
-
const key = styleName.replace(reg, function (v) {
|
|
89
|
-
return '-' + v.toLowerCase()
|
|
90
|
-
})
|
|
91
|
-
acc += `${key}: ${style[styleName]};`
|
|
92
|
-
return acc
|
|
93
|
-
}, '')
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export { DomStyle, createDom, updateDom }
|
package/src/lib/effects.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { RYUNIX_TYPES, STRINGS } from '../utils/index'
|
|
2
|
-
|
|
3
|
-
const isEvent = (key) => key.startsWith('on')
|
|
4
|
-
const isProperty = (key) => key !== STRINGS.children && !isEvent(key)
|
|
5
|
-
const isNew = (prev, next) => (key) => prev[key] !== next[key]
|
|
6
|
-
const isGone = (next) => (key) => !(key in next)
|
|
7
|
-
const hasDepsChanged = (prevDeps, nextDeps) =>
|
|
8
|
-
!prevDeps ||
|
|
9
|
-
!nextDeps ||
|
|
10
|
-
prevDeps.length !== nextDeps.length ||
|
|
11
|
-
prevDeps.some((dep, index) => dep !== nextDeps[index])
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The function cancels all effect hooks in a given fiber.
|
|
15
|
-
* @param fiber - The "fiber" parameter is likely referring to a data structure used in React.js to
|
|
16
|
-
* represent a component and its state. It contains information about the component's props, state, and
|
|
17
|
-
* children, as well as metadata used by React to manage updates and rendering. The function
|
|
18
|
-
* "cancelEffects" is likely intended
|
|
19
|
-
*/
|
|
20
|
-
const cancelEffects = (fiber) => {
|
|
21
|
-
if (fiber.hooks) {
|
|
22
|
-
fiber.hooks
|
|
23
|
-
.filter((hook) => hook.tag === RYUNIX_TYPES.RYUNIX_EFFECT && hook.cancel)
|
|
24
|
-
.forEach((effectHook) => {
|
|
25
|
-
effectHook.cancel()
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* The function runs all effect hooks in a given fiber.
|
|
32
|
-
* @param fiber - The "fiber" parameter is likely referring to a data structure used in the
|
|
33
|
-
* implementation of a fiber-based reconciliation algorithm, such as the one used in React. A fiber
|
|
34
|
-
* represents a unit of work that needs to be performed by the reconciliation algorithm, and it
|
|
35
|
-
* contains information about a component and its children, as
|
|
36
|
-
*/
|
|
37
|
-
const runEffects = (fiber) => {
|
|
38
|
-
if (fiber.hooks) {
|
|
39
|
-
fiber.hooks
|
|
40
|
-
.filter((hook) => hook.tag === RYUNIX_TYPES.RYUNIX_EFFECT && hook.effect)
|
|
41
|
-
.forEach((effectHook) => {
|
|
42
|
-
effectHook.cancel = effectHook.effect()
|
|
43
|
-
})
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export {
|
|
48
|
-
runEffects,
|
|
49
|
-
cancelEffects,
|
|
50
|
-
isEvent,
|
|
51
|
-
isProperty,
|
|
52
|
-
isNew,
|
|
53
|
-
isGone,
|
|
54
|
-
hasDepsChanged,
|
|
55
|
-
}
|