@unsetsoft/ryunixjs 1.0.2 → 1.0.3-nightly.4

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/src/lib/hooks.js CHANGED
@@ -1,35 +1,18 @@
1
- import { RYUNIX_TYPES, STRINGS, vars } from '../utils/index'
1
+ import { vars } from '../utils/index'
2
2
  import { isEqual } from 'lodash'
3
- import { Fragment, createElement, cloneElement } from './createElement'
3
+
4
4
  /**
5
- * @description The function creates a state.
6
- * @param initial - The initial value of the state for the hook.
7
- * @returns The `useStore` function returns an array with two elements: the current state value and a
8
- * `setState` function that can be used to update the state.
5
+ * useStore is similar to useState in React, managing local state within a functional component.
9
6
  */
10
7
  const useStore = (initial) => {
11
- const oldHook =
12
- vars.wipFiber.alternate &&
13
- vars.wipFiber.alternate.hooks &&
14
- vars.wipFiber.alternate.hooks[vars.hookIndex]
15
- const hook = {
16
- state: oldHook ? oldHook.state : initial,
17
- queue: [],
18
- }
8
+ const oldHook = vars.workInProgressFiber.alternate?.hooks?.[vars.hookIndex]
9
+ const hook = { state: oldHook ? oldHook.state : initial, queue: [] }
19
10
 
20
11
  const actions = oldHook ? oldHook.queue : []
21
12
  actions.forEach((action) => {
22
- hook.state =
23
- typeof action === STRINGS.function ? action(hook.state) : action
13
+ hook.state = typeof action === 'function' ? action(hook.state) : action
24
14
  })
25
15
 
26
- /**
27
- * The function `setState` updates the state of a component in Ryunix by adding an action to a queue
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
- */
33
16
  const setState = (action) => {
34
17
  hook.queue.push(action)
35
18
  vars.wipRoot = {
@@ -41,162 +24,58 @@ const useStore = (initial) => {
41
24
  vars.deletions = []
42
25
  }
43
26
 
44
- if (vars.wipFiber && vars.wipFiber.hooks) {
45
- vars.wipFiber.hooks.push(hook)
46
- vars.hookIndex++
47
- }
27
+ vars.workInProgressFiber.hooks.push(hook)
28
+ vars.hookIndex++
48
29
  return [hook.state, setState]
49
30
  }
50
31
 
51
32
  /**
52
- * This is a function that creates a hook for managing side effects in Ryunix components.
53
- * @param effect - The effect function that will be executed after the component has rendered or when
54
- * the dependencies have changed. It can perform side effects such as fetching data, updating the DOM,
55
- * or subscribing to events.
56
- * @param deps - An array of dependencies that the effect depends on. If any of the dependencies change
57
- * between renders, the effect will be re-run. If the array is empty, the effect will only run once on
58
- * mount and never again.
33
+ * useEffect runs side effects after rendering based on dependencies.
59
34
  */
60
-
61
35
  const useEffect = (callback, deps) => {
62
- const oldHook =
63
- vars.wipFiber.alternate &&
64
- vars.wipFiber.alternate.hooks &&
65
- vars.wipFiber.alternate.hooks[vars.hookIndex]
66
-
67
- const hook = {
68
- type: RYUNIX_TYPES.RYUNIX_EFFECT,
69
- deps,
70
- }
36
+ const oldHook = vars.workInProgressFiber.alternate?.hooks?.[vars.hookIndex]
37
+ const hook = { type: 'effect', deps }
71
38
 
72
- if (!oldHook) {
73
- // invoke callback if this is the first time
74
- callback()
75
- } else {
76
- if (!isEqual(oldHook.deps, hook.deps)) {
77
- callback()
78
- }
39
+ const hasChanged = !oldHook || !isEqual(oldHook.deps, deps)
40
+ if (hasChanged) {
41
+ const cleanup = callback()
42
+ hook.cleanup = cleanup
79
43
  }
80
44
 
81
- if (vars.wipFiber.hooks) {
82
- vars.wipFiber.hooks.push(hook)
83
- vars.hookIndex++
84
- }
45
+ vars.workInProgressFiber.hooks.push(hook)
46
+ vars.hookIndex++
85
47
  }
86
48
 
87
49
  /**
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.
50
+ * useRef creates a mutable ref object to store values across renders.
91
51
  */
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
- const useRef = (initial) => {
118
- const oldHook =
119
- vars.wipFiber.alternate &&
120
- vars.wipFiber.alternate.hooks &&
121
- vars.wipFiber.alternate.hooks[vars.hookIndex]
122
-
123
- const hook = {
124
- type: RYUNIX_TYPES.RYUNIX_REF,
125
- value: oldHook ? oldHook.value : { current: initial },
126
- }
127
-
128
- if (vars.wipFiber.hooks) {
129
- vars.wipFiber.hooks.push(hook)
130
- vars.hookIndex++
131
- }
52
+ const useRef = (initialValue) => {
53
+ const oldHook = vars.workInProgressFiber.alternate?.hooks?.[vars.hookIndex]
54
+ const hook = { value: oldHook ? oldHook.value : { current: initialValue } }
132
55
 
56
+ vars.workInProgressFiber.hooks.push(hook)
57
+ vars.hookIndex++
133
58
  return hook.value
134
59
  }
135
60
 
136
- const useMemo = (comp, deps) => {
137
- const oldHook =
138
- vars.wipFiber.alternate &&
139
- vars.wipFiber.alternate.hooks &&
140
- vars.wipFiber.alternate.hooks[vars.hookIndex]
141
-
61
+ /**
62
+ * useMemo memoizes a value to avoid recomputations.
63
+ */
64
+ const useMemo = (computeFn, deps) => {
65
+ const oldHook = vars.workInProgressFiber.alternate?.hooks?.[vars.hookIndex]
142
66
  const hook = {
143
- type: RYUNIX_TYPES.RYUNIX_MEMO,
144
- value: null,
145
67
  deps,
68
+ value: oldHook && isEqual(deps, oldHook.deps) ? oldHook.value : computeFn(),
146
69
  }
147
70
 
148
- if (oldHook) {
149
- if (isEqual(oldHook.deps, hook.deps)) {
150
- hook.value = oldHook.value
151
- } else {
152
- hook.value = comp()
153
- }
154
- } else {
155
- hook.value = comp()
156
- }
157
-
158
- if (vars.wipFiber.hooks) {
159
- vars.wipFiber.hooks.push(hook)
160
- vars.hookIndex++
161
- }
162
-
71
+ vars.workInProgressFiber.hooks.push(hook)
72
+ vars.hookIndex++
163
73
  return hook.value
164
74
  }
165
- const useCallback = (callback, deps) => {
166
- return useMemo(() => callback, deps)
167
- }
168
-
169
- const useRouter = (routes) => {
170
- const [location, setLocation] = useStore(window.location.pathname)
171
75
 
172
- const navigate = (path) => {
173
- window.history.pushState({}, '', path)
174
- setLocation(path)
175
- }
176
-
177
- useEffect(() => {
178
- const onPopState = () => {
179
- setLocation(window.location.pathname)
180
- }
181
-
182
- window.addEventListener('popstate', onPopState)
183
- return () => {
184
- window.removeEventListener('popstate', onPopState)
185
- }
186
- }, [])
187
-
188
- const currentRoute = routes.find((route) => route.path === location)
189
- const Children = () => (currentRoute ? currentRoute.component : null)
190
-
191
- return { Children, navigate }
192
- }
76
+ /**
77
+ * useCallback memoizes a callback function to avoid unnecessary recreations.
78
+ */
79
+ const useCallback = (callback, deps) => useMemo(() => callback, deps)
193
80
 
194
- export {
195
- useStore,
196
- useEffect,
197
- useQuery,
198
- useRef,
199
- useMemo,
200
- useCallback,
201
- useRouter,
202
- }
81
+ export { useStore, useEffect, useRef, useMemo, useCallback }
package/src/lib/index.js CHANGED
@@ -1,30 +1,13 @@
1
1
  import { createElement, cloneElement, Fragment } from './createElement'
2
2
  import { render, init } from './render'
3
- import {
4
- useStore,
5
- useEffect,
6
- useQuery,
7
- useRef,
8
- useMemo,
9
- useCallback,
10
- useRouter,
11
- } from './hooks'
3
+ import { useStore, useEffect, useRef, useMemo, useCallback } from './hooks'
12
4
  import * as Dom from './dom'
13
5
  import * as Workers from './workers'
14
6
  import * as Reconciler from './reconciler'
15
7
  import * as Components from './components'
16
8
  import * as Commits from './commits'
17
9
 
18
- export {
19
- useStore,
20
- useEffect,
21
- useQuery,
22
- useRef,
23
- useMemo,
24
- useCallback,
25
- useRouter,
26
- Fragment,
27
- }
10
+ export { useStore, useEffect, useRef, useMemo, useCallback, Fragment }
28
11
 
29
12
  export default {
30
13
  createElement,
@@ -22,9 +22,9 @@ const reconcileChildren = (wipFiber, elements) => {
22
22
 
23
23
  if (sameType) {
24
24
  newFiber = {
25
- type: oldFiber ? oldFiber.type : undefined,
25
+ type: oldFiber.type,
26
26
  props: element.props,
27
- dom: oldFiber ? oldFiber.dom : undefined,
27
+ dom: oldFiber.dom,
28
28
  parent: wipFiber,
29
29
  alternate: oldFiber,
30
30
  effectTag: EFFECT_TAGS.UPDATE,
@@ -40,7 +40,7 @@ const reconcileChildren = (wipFiber, elements) => {
40
40
  effectTag: EFFECT_TAGS.PLACEMENT,
41
41
  }
42
42
  }
43
- if (oldFiber && !sameType) {
43
+ if (!element && oldFiber) {
44
44
  oldFiber.effectTag = EFFECT_TAGS.DELETION
45
45
  vars.deletions.push(oldFiber)
46
46
  }
package/src/lib/render.js CHANGED
@@ -1,33 +1,32 @@
1
1
  import { vars } from '../utils/index'
2
+ import { workLoop } from './workers'
2
3
 
3
4
  /**
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().
5
+ * Renders an element into the specified container or the default root element.
9
6
  */
10
7
  const render = (element, container) => {
11
8
  vars.wipRoot = {
12
9
  dom: vars.containerRoot || container,
13
- props: {
14
- children: [element],
15
- },
10
+ props: { children: [element] },
16
11
  alternate: vars.currentRoot,
17
12
  }
13
+
18
14
  vars.deletions = []
19
15
  vars.nextUnitOfWork = vars.wipRoot
16
+ requestIdleCallback(workLoop)
20
17
  }
21
18
 
22
19
  /**
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.
20
+ * Initializes the app with a root container.
27
21
  */
28
- const init = (root) => {
29
- const rootElement = root || '__ryunix'
30
- vars.containerRoot = document.getElementById(rootElement)
22
+ const init = (rootId = '__ryunix') => {
23
+ const rootElement = document.getElementById(rootId)
24
+ if (!rootElement) {
25
+ console.error(`Root element with ID '${rootId}' not found.`)
26
+ return null
27
+ }
28
+
29
+ vars.containerRoot = rootElement
31
30
  return this
32
31
  }
33
32
 
@@ -3,15 +3,13 @@ import { updateFunctionComponent, updateHostComponent } from './components'
3
3
  import { vars } from '../utils/index'
4
4
 
5
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
6
+ * Main work loop that processes the fiber tree using requestIdleCallback.
7
+ * It continues processing until all units of work are completed or the browser needs to yield.
8
+ * @param {IdleDeadline} deadline - Represents the time remaining for the browser to execute tasks before yielding.
12
9
  */
13
10
  const workLoop = (deadline) => {
14
11
  let shouldYield = false
12
+
15
13
  while (vars.nextUnitOfWork && !shouldYield) {
16
14
  vars.nextUnitOfWork = performUnitOfWork(vars.nextUnitOfWork)
17
15
  shouldYield = deadline.timeRemaining() < 1
@@ -24,38 +22,28 @@ const workLoop = (deadline) => {
24
22
  requestIdleCallback(workLoop)
25
23
  }
26
24
 
25
+ // Start the work loop for the first time
27
26
  requestIdleCallback(workLoop)
28
27
 
29
28
  /**
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.
29
+ * Processes a unit of work in the fiber tree.
30
+ * Decides whether to update a function component or a host component (DOM element).
31
+ * @param {Object} fiber - The current fiber representing a component and its state in the virtual DOM tree.
32
+ * @returns {null} The next fiber to process, or undefined if there are no more.
40
33
  */
41
34
  const performUnitOfWork = (fiber) => {
42
35
  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
- }
36
+ isFunctionComponent
37
+ ? updateFunctionComponent(fiber)
38
+ : updateHostComponent(fiber)
39
+
40
+ if (fiber.child) return fiber.child
51
41
  let nextFiber = fiber
52
42
  while (nextFiber) {
53
- if (nextFiber.sibling) {
54
- return nextFiber.sibling
55
- }
43
+ if (nextFiber.sibling) return nextFiber.sibling
56
44
  nextFiber = nextFiber.parent
57
45
  }
58
- return undefined
46
+ return null
59
47
  }
60
48
 
61
49
  export { performUnitOfWork, workLoop }
package/src/main.js CHANGED
@@ -2,11 +2,9 @@ import Ryunix from './lib/index.js'
2
2
  export {
3
3
  useStore,
4
4
  useEffect,
5
- useQuery,
6
5
  useRef,
7
6
  useMemo,
8
7
  useCallback,
9
- useRouter,
10
8
  Fragment,
11
9
  } from './lib/index.js'
12
10
 
@@ -3,12 +3,13 @@ const vars = {
3
3
  nextUnitOfWork: undefined,
4
4
  currentRoot: undefined,
5
5
  wipRoot: undefined,
6
- deletions: undefined,
7
- wipFiber: undefined,
8
- hookIndex: undefined,
6
+ deletions: [],
7
+ workInProgressFiber: undefined,
8
+ hookIndex: 0,
9
+ errorBoundary: null, // New property to hold error boundary references
9
10
  }
10
11
 
11
- const reg = /[A-Z]/g
12
+ const capitalLetterRegex = /[A-Z]/g
12
13
 
13
14
  const RYUNIX_TYPES = Object.freeze({
14
15
  TEXT_ELEMENT: Symbol('text.element'),
@@ -16,6 +17,7 @@ const RYUNIX_TYPES = Object.freeze({
16
17
  RYUNIX_MEMO: Symbol('ryunix.memo'),
17
18
  RYUNIX_URL_QUERY: Symbol('ryunix.urlQuery'),
18
19
  RYUNIX_REF: Symbol('ryunix.ref'),
20
+ RYUNIX_ERROR_BOUNDARY: Symbol('ryunix.errorBoundary'), // New Error Boundary Type
19
21
  })
20
22
 
21
23
  const STRINGS = Object.freeze({
@@ -33,9 +35,16 @@ const OLD_STRINGS = Object.freeze({
33
35
  })
34
36
 
35
37
  const EFFECT_TAGS = Object.freeze({
36
- PLACEMENT: Symbol(),
37
- UPDATE: Symbol(),
38
- DELETION: Symbol(),
38
+ PLACEMENT: Symbol('placement'),
39
+ UPDATE: Symbol('update'),
40
+ DELETION: Symbol('deletion'),
39
41
  })
40
42
 
41
- export { vars, reg, RYUNIX_TYPES, EFFECT_TAGS, STRINGS, OLD_STRINGS }
43
+ export {
44
+ vars,
45
+ capitalLetterRegex,
46
+ RYUNIX_TYPES,
47
+ EFFECT_TAGS,
48
+ STRINGS,
49
+ OLD_STRINGS,
50
+ }