kiru 0.48.3 → 0.49.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.
Files changed (236) hide show
  1. package/dist/action.d.ts +22 -0
  2. package/dist/action.d.ts.map +1 -0
  3. package/dist/action.js +20 -0
  4. package/dist/action.js.map +1 -0
  5. package/dist/components/index.d.ts +5 -0
  6. package/dist/components/index.d.ts.map +1 -0
  7. package/dist/components/index.js +5 -0
  8. package/dist/components/index.js.map +1 -0
  9. package/dist/components/lazy.d.ts.map +1 -0
  10. package/dist/{lazy.js → components/lazy.js} +11 -11
  11. package/dist/components/lazy.js.map +1 -0
  12. package/dist/{memo.d.ts → components/memo.d.ts} +1 -1
  13. package/dist/components/memo.d.ts.map +1 -0
  14. package/dist/{memo.js → components/memo.js} +2 -2
  15. package/dist/components/memo.js.map +1 -0
  16. package/dist/components/portal.d.ts.map +1 -0
  17. package/dist/{portal.js → components/portal.js} +6 -6
  18. package/dist/components/portal.js.map +1 -0
  19. package/dist/components/router/index.d.ts.map +1 -0
  20. package/dist/components/router/index.js.map +1 -0
  21. package/dist/components/router/route.d.ts.map +1 -0
  22. package/dist/{router → components/router}/route.js +1 -1
  23. package/dist/components/router/route.js.map +1 -0
  24. package/dist/{router → components/router}/router.d.ts +1 -1
  25. package/dist/components/router/router.d.ts.map +1 -0
  26. package/dist/{router → components/router}/router.js +12 -8
  27. package/dist/components/router/router.js.map +1 -0
  28. package/dist/components/router/routerUtils.d.ts.map +1 -0
  29. package/dist/components/router/routerUtils.js.map +1 -0
  30. package/dist/components/transition.d.ts.map +1 -0
  31. package/dist/{transition.js → components/transition.js} +5 -5
  32. package/dist/components/transition.js.map +1 -0
  33. package/dist/constants.d.ts +3 -12
  34. package/dist/constants.d.ts.map +1 -1
  35. package/dist/constants.js +80 -12
  36. package/dist/constants.js.map +1 -1
  37. package/dist/context.js +1 -1
  38. package/dist/context.js.map +1 -1
  39. package/dist/dom.d.ts.map +1 -1
  40. package/dist/dom.js +9 -12
  41. package/dist/dom.js.map +1 -1
  42. package/dist/element.js +2 -2
  43. package/dist/element.js.map +1 -1
  44. package/dist/error.js +1 -1
  45. package/dist/error.js.map +1 -1
  46. package/dist/form/index.d.ts.map +1 -1
  47. package/dist/form/index.js +1 -2
  48. package/dist/form/index.js.map +1 -1
  49. package/dist/hmr.js +1 -1
  50. package/dist/hmr.js.map +1 -1
  51. package/dist/hooks/useAsync.d.ts.map +1 -1
  52. package/dist/hooks/useAsync.js +2 -2
  53. package/dist/hooks/useAsync.js.map +1 -1
  54. package/dist/hooks/useCallback.d.ts.map +1 -1
  55. package/dist/hooks/useCallback.js +2 -1
  56. package/dist/hooks/useCallback.js.map +1 -1
  57. package/dist/hooks/useEffect.d.ts.map +1 -1
  58. package/dist/hooks/useEffect.js +2 -1
  59. package/dist/hooks/useEffect.js.map +1 -1
  60. package/dist/hooks/useEffectEvent.d.ts.map +1 -1
  61. package/dist/hooks/useEffectEvent.js +2 -1
  62. package/dist/hooks/useEffectEvent.js.map +1 -1
  63. package/dist/hooks/useLayoutEffect.d.ts.map +1 -1
  64. package/dist/hooks/useLayoutEffect.js +2 -1
  65. package/dist/hooks/useLayoutEffect.js.map +1 -1
  66. package/dist/hooks/useMemo.d.ts.map +1 -1
  67. package/dist/hooks/useMemo.js +2 -1
  68. package/dist/hooks/useMemo.js.map +1 -1
  69. package/dist/hooks/useReducer.js +2 -2
  70. package/dist/hooks/useReducer.js.map +1 -1
  71. package/dist/hooks/useRef.d.ts.map +1 -1
  72. package/dist/hooks/useRef.js +2 -1
  73. package/dist/hooks/useRef.js.map +1 -1
  74. package/dist/hooks/useState.js +2 -2
  75. package/dist/hooks/useState.js.map +1 -1
  76. package/dist/hooks/useSyncExternalStore.js +2 -2
  77. package/dist/hooks/useSyncExternalStore.js.map +1 -1
  78. package/dist/hooks/useViewTransition.d.ts.map +1 -1
  79. package/dist/hooks/useViewTransition.js +1 -2
  80. package/dist/hooks/useViewTransition.js.map +1 -1
  81. package/dist/hooks/utils.d.ts +0 -1
  82. package/dist/hooks/utils.d.ts.map +1 -1
  83. package/dist/hooks/utils.js +2 -2
  84. package/dist/hooks/utils.js.map +1 -1
  85. package/dist/index.d.ts +2 -5
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +2 -5
  88. package/dist/index.js.map +1 -1
  89. package/dist/reconciler.js +8 -7
  90. package/dist/reconciler.js.map +1 -1
  91. package/dist/renderToString.js +2 -4
  92. package/dist/renderToString.js.map +1 -1
  93. package/dist/scheduler.js +14 -2
  94. package/dist/scheduler.js.map +1 -1
  95. package/dist/signals/base.d.ts.map +1 -1
  96. package/dist/signals/base.js +1 -2
  97. package/dist/signals/base.js.map +1 -1
  98. package/dist/signals/computed.js +1 -1
  99. package/dist/signals/computed.js.map +1 -1
  100. package/dist/signals/effect.js +1 -1
  101. package/dist/signals/effect.js.map +1 -1
  102. package/dist/signals/watch.d.ts.map +1 -1
  103. package/dist/signals/watch.js +2 -3
  104. package/dist/signals/watch.js.map +1 -1
  105. package/dist/ssr/server.js +2 -4
  106. package/dist/ssr/server.js.map +1 -1
  107. package/dist/store.d.ts +1 -1
  108. package/dist/store.d.ts.map +1 -1
  109. package/dist/store.js +2 -2
  110. package/dist/store.js.map +1 -1
  111. package/dist/swr.js +1 -1
  112. package/dist/swr.js.map +1 -1
  113. package/dist/types.d.ts +4 -3
  114. package/dist/types.d.ts.map +1 -1
  115. package/dist/types.dom.d.ts +2 -2
  116. package/dist/types.dom.d.ts.map +1 -1
  117. package/dist/utils/compare.d.ts +3 -0
  118. package/dist/utils/compare.d.ts.map +1 -0
  119. package/dist/utils/compare.js +123 -0
  120. package/dist/utils/compare.js.map +1 -0
  121. package/dist/utils/format.d.ts +20 -0
  122. package/dist/utils/format.d.ts.map +1 -0
  123. package/dist/utils/format.js +136 -0
  124. package/dist/utils/format.js.map +1 -0
  125. package/dist/utils/generateId.d.ts.map +1 -0
  126. package/dist/utils/generateId.js.map +1 -0
  127. package/dist/utils/index.d.ts +7 -0
  128. package/dist/utils/index.d.ts.map +1 -0
  129. package/dist/utils/index.js +7 -0
  130. package/dist/utils/index.js.map +1 -0
  131. package/dist/utils/runtime.d.ts +11 -0
  132. package/dist/utils/runtime.d.ts.map +1 -0
  133. package/dist/utils/runtime.js +23 -0
  134. package/dist/utils/runtime.js.map +1 -0
  135. package/dist/utils/vdom.d.ts +25 -0
  136. package/dist/utils/vdom.d.ts.map +1 -0
  137. package/dist/utils/vdom.js +124 -0
  138. package/dist/utils/vdom.js.map +1 -0
  139. package/package.json +6 -6
  140. package/src/action.ts +42 -0
  141. package/src/components/index.ts +4 -0
  142. package/src/{lazy.ts → components/lazy.ts} +12 -12
  143. package/src/{memo.ts → components/memo.ts} +3 -3
  144. package/src/{portal.ts → components/portal.ts} +6 -6
  145. package/src/{router → components/router}/route.ts +1 -1
  146. package/src/{router → components/router}/router.ts +14 -9
  147. package/src/{transition.ts → components/transition.ts} +5 -5
  148. package/src/constants.ts +80 -13
  149. package/src/context.ts +1 -1
  150. package/src/customEvents.ts +22 -22
  151. package/src/dom.ts +8 -11
  152. package/src/element.ts +2 -2
  153. package/src/error.ts +1 -1
  154. package/src/form/index.ts +5 -2
  155. package/src/hmr.ts +1 -1
  156. package/src/hooks/useAsync.ts +5 -3
  157. package/src/hooks/useCallback.ts +2 -1
  158. package/src/hooks/useEffect.ts +2 -6
  159. package/src/hooks/useEffectEvent.ts +2 -1
  160. package/src/hooks/useLayoutEffect.ts +2 -6
  161. package/src/hooks/useMemo.ts +2 -1
  162. package/src/hooks/useReducer.ts +2 -2
  163. package/src/hooks/useRef.ts +2 -1
  164. package/src/hooks/useState.ts +2 -2
  165. package/src/hooks/useSyncExternalStore.ts +2 -2
  166. package/src/hooks/useViewTransition.ts +1 -2
  167. package/src/hooks/utils.ts +2 -2
  168. package/src/index.ts +2 -5
  169. package/src/reconciler.ts +13 -11
  170. package/src/renderToString.ts +3 -4
  171. package/src/scheduler.ts +16 -2
  172. package/src/signals/base.ts +6 -2
  173. package/src/signals/computed.ts +1 -1
  174. package/src/signals/effect.ts +1 -1
  175. package/src/signals/watch.ts +2 -3
  176. package/src/ssr/server.ts +3 -4
  177. package/src/store.ts +6 -2
  178. package/src/swr.ts +3 -3
  179. package/src/types.dom.ts +2 -1
  180. package/src/types.ts +9 -2
  181. package/src/utils/compare.ts +125 -0
  182. package/src/utils/format.ts +162 -0
  183. package/src/utils/index.ts +7 -0
  184. package/src/utils/runtime.ts +25 -0
  185. package/src/utils/vdom.ts +184 -0
  186. package/dist/cloneVNode.d.ts +0 -2
  187. package/dist/cloneVNode.d.ts.map +0 -1
  188. package/dist/cloneVNode.js +0 -14
  189. package/dist/cloneVNode.js.map +0 -1
  190. package/dist/generateId.d.ts.map +0 -1
  191. package/dist/generateId.js.map +0 -1
  192. package/dist/lazy.d.ts.map +0 -1
  193. package/dist/lazy.js.map +0 -1
  194. package/dist/memo.d.ts.map +0 -1
  195. package/dist/memo.js.map +0 -1
  196. package/dist/portal.d.ts.map +0 -1
  197. package/dist/portal.js.map +0 -1
  198. package/dist/props.d.ts +0 -4
  199. package/dist/props.d.ts.map +0 -1
  200. package/dist/props.js +0 -27
  201. package/dist/props.js.map +0 -1
  202. package/dist/router/index.d.ts.map +0 -1
  203. package/dist/router/index.js.map +0 -1
  204. package/dist/router/route.d.ts.map +0 -1
  205. package/dist/router/route.js.map +0 -1
  206. package/dist/router/router.d.ts.map +0 -1
  207. package/dist/router/router.js.map +0 -1
  208. package/dist/router/routerUtils.d.ts.map +0 -1
  209. package/dist/router/routerUtils.js.map +0 -1
  210. package/dist/transition.d.ts.map +0 -1
  211. package/dist/transition.js.map +0 -1
  212. package/dist/utils.d.ts +0 -52
  213. package/dist/utils.d.ts.map +0 -1
  214. package/dist/utils.js +0 -433
  215. package/dist/utils.js.map +0 -1
  216. package/dist/warning.d.ts +0 -2
  217. package/dist/warning.d.ts.map +0 -1
  218. package/dist/warning.js +0 -4
  219. package/dist/warning.js.map +0 -1
  220. package/src/cloneVNode.ts +0 -14
  221. package/src/props.ts +0 -34
  222. package/src/utils.ts +0 -518
  223. package/src/warning.ts +0 -9
  224. /package/dist/{lazy.d.ts → components/lazy.d.ts} +0 -0
  225. /package/dist/{portal.d.ts → components/portal.d.ts} +0 -0
  226. /package/dist/{router → components/router}/index.d.ts +0 -0
  227. /package/dist/{router → components/router}/index.js +0 -0
  228. /package/dist/{router → components/router}/route.d.ts +0 -0
  229. /package/dist/{router → components/router}/routerUtils.d.ts +0 -0
  230. /package/dist/{router → components/router}/routerUtils.js +0 -0
  231. /package/dist/{transition.d.ts → components/transition.d.ts} +0 -0
  232. /package/dist/{generateId.d.ts → utils/generateId.d.ts} +0 -0
  233. /package/dist/{generateId.js → utils/generateId.js} +0 -0
  234. /package/src/{router → components/router}/index.ts +0 -0
  235. /package/src/{router → components/router}/routerUtils.ts +0 -0
  236. /package/src/{generateId.ts → utils/generateId.ts} +0 -0
package/src/dom.ts CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  propFilters,
5
5
  propToHtmlAttr,
6
6
  getVNodeAppContext,
7
- } from "./utils.js"
7
+ } from "./utils/index.js"
8
8
  import {
9
9
  booleanAttributes,
10
10
  FLAG_PLACEMENT,
@@ -100,15 +100,14 @@ function createDom(vNode: DomVNode): SomeDom {
100
100
  return dom
101
101
  }
102
102
  function createTextNode(vNode: VNode): Text {
103
- const nodeValue = vNode.props.nodeValue
104
- if (Signal.isSignal(nodeValue)) {
105
- const value = nodeValue.peek()
106
- const textNode = document.createTextNode(value)
107
- subTextNode(vNode, textNode, nodeValue)
108
- return textNode
103
+ const { nodeValue } = vNode.props
104
+ if (!Signal.isSignal(nodeValue)) {
105
+ return document.createTextNode(nodeValue)
109
106
  }
110
107
 
111
- const textNode = document.createTextNode(nodeValue)
108
+ const value = nodeValue.peek() ?? ""
109
+ const textNode = document.createTextNode(value)
110
+ subTextNode(vNode, textNode, nodeValue)
112
111
  return textNode
113
112
  }
114
113
 
@@ -720,9 +719,7 @@ function placeAndCommitNoopChildren(
720
719
  const nextSiblingDom = getNextSiblingDom(parent, node)
721
720
  const parentDom = node.dom
722
721
  if (nextSiblingDom) {
723
- const [first, ...rest] = domChildren
724
- parentDom.insertBefore(first, nextSiblingDom)
725
- first.after(...rest)
722
+ nextSiblingDom.before(...domChildren)
726
723
  } else {
727
724
  parentDom.append(...domChildren)
728
725
  }
package/src/element.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { $FRAGMENT, $MEMO, FLAG_MEMO } from "./constants.js"
2
- import { isMemoFn } from "./memo.js"
3
- import { isValidElementKeyProp, isValidElementRefProp } from "./props.js"
2
+ import { isMemoFn } from "./components/memo.js"
3
+ import { isValidElementKeyProp, isValidElementRefProp } from "./utils/index.js"
4
4
 
5
5
  export function createElement<T extends Kiru.VNode["type"]>(
6
6
  type: T,
package/src/error.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { $KIRU_ERROR } from "./constants.js"
2
2
  import { __DEV__ } from "./env.js"
3
- import { findParent, noop } from "./utils.js"
3
+ import { findParent, noop } from "./utils/index.js"
4
4
 
5
5
  type KiruErrorOptions =
6
6
  | string
package/src/form/index.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  import { __DEV__ } from "../env.js"
2
2
  import { Fragment } from "../element.js"
3
- import { generateRandomID } from "../generateId.js"
4
- import { safeStringify, shallowCompare } from "../utils.js"
3
+ import {
4
+ safeStringify,
5
+ shallowCompare,
6
+ generateRandomID,
7
+ } from "../utils/index.js"
5
8
  import { useEffect } from "../hooks/useEffect.js"
6
9
  import { useMemo } from "../hooks/useMemo.js"
7
10
  import { useRef } from "../hooks/useRef.js"
package/src/hmr.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { $HMR_ACCEPT } from "./constants.js"
2
2
  import { __DEV__ } from "./env.js"
3
- import { traverseApply } from "./utils.js"
3
+ import { traverseApply } from "./utils/index.js"
4
4
  import { requestUpdate } from "./scheduler.js"
5
5
  import { Signal } from "./signals/base.js"
6
6
  import type { WatchEffect } from "./signals/watch.js"
@@ -1,6 +1,6 @@
1
1
  import { __DEV__ } from "../env.js"
2
- import { noop } from "../utils.js"
3
- import { depsRequireChange, sideEffectsEnabled, useHook } from "./utils.js"
2
+ import { noop, sideEffectsEnabled } from "../utils/index.js"
3
+ import { depsRequireChange, useHook } from "./utils.js"
4
4
  import type { AsyncTaskState } from "../types.utils.js"
5
5
 
6
6
  export type UseAsyncState<T> = AsyncTaskState<T, UseAsyncError> & {
@@ -48,7 +48,9 @@ export function useAsync<T>(
48
48
  deps,
49
49
  id: 0,
50
50
  task: null as any as InternalTaskState<T>,
51
- load: noop as (func: (ctx: UseAsyncCallbackContext) => Promise<T>) => void,
51
+ load: noop as (
52
+ func: (ctx: UseAsyncCallbackContext) => Promise<T>
53
+ ) => void,
52
54
  },
53
55
  ({ hook, isInit, isHMR, update }) => {
54
56
  if (__DEV__) {
@@ -1,5 +1,6 @@
1
1
  import { __DEV__ } from "../env.js"
2
- import { depsRequireChange, useHook, sideEffectsEnabled } from "./utils.js"
2
+ import { sideEffectsEnabled } from "../utils/index.js"
3
+ import { depsRequireChange, useHook } from "./utils.js"
3
4
 
4
5
  /**
5
6
  * Creates a memoized callback function.
@@ -1,10 +1,6 @@
1
+ import { sideEffectsEnabled } from "../utils/index.js"
1
2
  import { __DEV__ } from "../env.js"
2
- import {
3
- cleanupHook,
4
- depsRequireChange,
5
- sideEffectsEnabled,
6
- useHook,
7
- } from "./utils.js"
3
+ import { cleanupHook, depsRequireChange, useHook } from "./utils.js"
8
4
 
9
5
  /**
10
6
  * Runs a function after the component is rendered, or when a value provided in the optional [dependency
@@ -1,6 +1,7 @@
1
+ import { sideEffectsEnabled } from "../utils/index.js"
1
2
  import { node } from "../globals.js"
2
3
  import { __DEV__ } from "../env.js"
3
- import { sideEffectsEnabled, useHook } from "./utils.js"
4
+ import { useHook } from "./utils.js"
4
5
 
5
6
  /**
6
7
  * Wraps a function to be called within effects and other callbacks.
@@ -1,10 +1,6 @@
1
+ import { sideEffectsEnabled } from "../utils/index.js"
1
2
  import { __DEV__ } from "../env.js"
2
- import {
3
- cleanupHook,
4
- depsRequireChange,
5
- sideEffectsEnabled,
6
- useHook,
7
- } from "./utils.js"
3
+ import { cleanupHook, depsRequireChange, useHook } from "./utils.js"
8
4
 
9
5
  /**
10
6
  * Runs a function before the component is rendered, or when a value provided in the optional [dependency
@@ -1,5 +1,6 @@
1
+ import { sideEffectsEnabled } from "../utils/index.js"
1
2
  import { __DEV__ } from "../env.js"
2
- import { depsRequireChange, sideEffectsEnabled, useHook } from "./utils.js"
3
+ import { depsRequireChange, useHook } from "./utils.js"
3
4
 
4
5
  /**
5
6
  * Creates a memoized value that only changes when the [dependency
@@ -1,6 +1,6 @@
1
1
  import { __DEV__ } from "../env.js"
2
- import { noop } from "../utils.js"
3
- import { sideEffectsEnabled, useHook } from "./utils.js"
2
+ import { noop, sideEffectsEnabled } from "../utils/index.js"
3
+ import { useHook } from "./utils.js"
4
4
 
5
5
  /**
6
6
  * Creates 'dispatcher-driven' state.
@@ -1,5 +1,6 @@
1
1
  import { __DEV__ } from "../env.js"
2
- import { sideEffectsEnabled, useHook } from "./utils.js"
2
+ import { sideEffectsEnabled } from "../utils/index.js"
3
+ import { useHook } from "./utils.js"
3
4
 
4
5
  /**
5
6
  * Creates a ref object. Useful for persisting values between renders or getting
@@ -1,6 +1,6 @@
1
1
  import { __DEV__ } from "../env.js"
2
- import { noop } from "../utils.js"
3
- import { sideEffectsEnabled, useHook } from "./utils.js"
2
+ import { noop, sideEffectsEnabled } from "../utils/index.js"
3
+ import { useHook } from "./utils.js"
4
4
 
5
5
  /**
6
6
  * Creates a stateful value, and returns the current value and a function to update it.
@@ -1,7 +1,7 @@
1
1
  import { node } from "../globals.js"
2
2
  import { KiruError } from "../error.js"
3
- import { noop } from "../utils.js"
4
- import { sideEffectsEnabled, useHook } from "./utils.js"
3
+ import { noop, sideEffectsEnabled } from "../utils/index.js"
4
+ import { useHook } from "./utils.js"
5
5
  import { __DEV__ } from "../env.js"
6
6
 
7
7
  /**
@@ -1,7 +1,6 @@
1
1
  import { flushSync } from "../scheduler.js"
2
2
  import { node } from "../globals.js"
3
- import { noop } from "../utils.js"
4
- import { sideEffectsEnabled } from "./utils.js"
3
+ import { noop, sideEffectsEnabled } from "../utils/index.js"
5
4
 
6
5
  /**
7
6
  * Allows you to easily use the [View Transition API](https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition)
@@ -1,9 +1,8 @@
1
1
  import { KiruError } from "../error.js"
2
2
  import { __DEV__ } from "../env.js"
3
3
  import { hookIndex, node } from "../globals.js"
4
- import { noop } from "../utils.js"
4
+ import { noop } from "../utils/index.js"
5
5
  import { requestUpdate } from "../scheduler.js"
6
- export { sideEffectsEnabled } from "../utils.js"
7
6
  export {
8
7
  cleanupHook,
9
8
  depsRequireChange,
@@ -158,6 +157,7 @@ function useHook<
158
157
  console.warn(
159
158
  `[kiru]: hooks must be called in the same order. Hook "${hookName}" was called in place of "${vNode.hookSig[index]}". Strange things may happen.`
160
159
  )
160
+ oldHook?.cleanup?.()
161
161
  vNode.hooks.length = index
162
162
  vNode.hookSig.length = index
163
163
  oldHook = undefined
package/src/index.ts CHANGED
@@ -3,19 +3,16 @@ import { createKiruGlobalContext } from "./globalContext.js"
3
3
 
4
4
  export type * from "./types"
5
5
  export * from "./signals/index.js"
6
+ export * from "./action.js"
6
7
  export * from "./appContext.js"
7
- export * from "./cloneVNode.js"
8
8
  export * from "./context.js"
9
9
  export * from "./customEvents.js"
10
10
  export * from "./element.js"
11
11
  export * from "./hooks/index.js"
12
- export * from "./lazy.js"
13
- export { memo } from "./memo.js"
14
- export * from "./portal.js"
12
+ export * from "./components/index.js"
15
13
  export * from "./renderToString.js"
16
14
  export { nextIdle, flushSync, requestUpdate } from "./scheduler.js"
17
15
  export * from "./store.js"
18
- export * from "./transition.js"
19
16
 
20
17
  if (__DEV__) {
21
18
  if ("window" in globalThis) {
package/src/reconciler.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { $FRAGMENT, FLAG_PLACEMENT, FLAG_UPDATE } from "./constants.js"
2
- import { getVNodeAppContext, isVNode, latest } from "./utils.js"
2
+ import { getVNodeAppContext, isVNode, latest } from "./utils/index.js"
3
3
  import { Signal } from "./signals/base.js"
4
4
  import { __DEV__ } from "./env.js"
5
5
  import { createElement, Fragment } from "./element.js"
@@ -150,11 +150,7 @@ function reconcileChildrenArray(parent: VNode, children: unknown[]) {
150
150
  function updateSlot(parent: VNode, oldChild: VNode | null, child: unknown) {
151
151
  // Update the node if the keys match, otherwise return null.
152
152
  const key = oldChild?.props.key
153
- if (
154
- (typeof child === "string" && child !== "") ||
155
- typeof child === "number" ||
156
- typeof child === "bigint"
157
- ) {
153
+ if (isValidTextNodeValue(child)) {
158
154
  if (key !== undefined) return null
159
155
  if (
160
156
  oldChild?.type === "#text" &&
@@ -272,11 +268,7 @@ function updateFragment(
272
268
  }
273
269
 
274
270
  function createChild(parent: VNode, child: unknown): VNode | null {
275
- if (
276
- (typeof child === "string" && child !== "") ||
277
- typeof child === "number" ||
278
- typeof child === "bigint"
279
- ) {
271
+ if (isValidTextNodeValue(child)) {
280
272
  if (__DEV__) {
281
273
  dev_emitCreateNode()
282
274
  }
@@ -438,6 +430,16 @@ function updateFromMap(
438
430
  return null
439
431
  }
440
432
 
433
+ function isValidTextNodeValue(
434
+ value: unknown
435
+ ): value is string | number | bigint {
436
+ return (
437
+ (typeof value === "string" && value !== "") ||
438
+ typeof value === "number" ||
439
+ typeof value === "bigint"
440
+ )
441
+ }
442
+
441
443
  function propsChanged(oldProps: VNode["props"], newProps: VNode["props"]) {
442
444
  const aKeys = Object.keys(oldProps)
443
445
  const bKeys = Object.keys(newProps)
@@ -5,10 +5,10 @@ import {
5
5
  encodeHtmlEntities,
6
6
  propsToElementAttributes,
7
7
  isExoticType,
8
- } from "./utils.js"
8
+ assertValidElementProps,
9
+ } from "./utils/index.js"
9
10
  import { Signal } from "./signals/base.js"
10
11
  import { $HYDRATION_BOUNDARY, voidElements } from "./constants.js"
11
- import { assertValidElementProps } from "./props.js"
12
12
  import { HYDRATION_BOUNDARY_MARKER } from "./ssr/hydrationBoundary.js"
13
13
  import { __DEV__ } from "./env.js"
14
14
 
@@ -39,8 +39,7 @@ function renderToString_internal(
39
39
  el.parent = parent
40
40
  el.depth = (parent?.depth ?? -1) + 1
41
41
  el.index = idx
42
- const props = el.props ?? {}
43
- const type = el.type
42
+ const { type, props = {} } = el
44
43
  if (type === "#text") return encodeHtmlEntities(props.nodeValue ?? "")
45
44
 
46
45
  const children = props.children
package/src/scheduler.ts CHANGED
@@ -23,14 +23,14 @@ import { __DEV__ } from "./env.js"
23
23
  import { KiruError } from "./error.js"
24
24
  import { hookIndex, node, renderMode } from "./globals.js"
25
25
  import { hydrationStack } from "./hydration.js"
26
- import { assertValidElementProps } from "./props.js"
26
+ import { assertValidElementProps } from "./utils/index.js"
27
27
  import { reconcileChildren } from "./reconciler.js"
28
28
  import {
29
29
  latest,
30
30
  traverseApply,
31
31
  isExoticType,
32
32
  getVNodeAppContext,
33
- } from "./utils.js"
33
+ } from "./utils/index.js"
34
34
  import type { AppContext } from "./appContext"
35
35
 
36
36
  type VNode = Kiru.VNode
@@ -318,6 +318,20 @@ function updateFunctionComponent(vNode: FunctionVNode) {
318
318
 
319
319
  if (__DEV__) {
320
320
  newChild = latest(type)(props)
321
+
322
+ if (vNode.hmrUpdated && vNode.hooks && vNode.hookSig) {
323
+ const len = vNode.hooks.length
324
+ if (hookIndex.current < len) {
325
+ // clean up any hooks that were removed
326
+ for (let i = hookIndex.current; i < len; i++) {
327
+ const hook = vNode.hooks[i]
328
+ hook.cleanup?.()
329
+ }
330
+ vNode.hooks.length = hookIndex.current
331
+ vNode.hookSig.length = hookIndex.current
332
+ }
333
+ }
334
+
321
335
  delete vNode.hmrUpdated
322
336
  if (++renderTryCount > CONSECUTIVE_DIRTY_LIMIT) {
323
337
  throw new KiruError({
@@ -1,9 +1,13 @@
1
- import { latest, safeStringify, sideEffectsEnabled } from "../utils.js"
1
+ import {
2
+ latest,
3
+ safeStringify,
4
+ sideEffectsEnabled,
5
+ generateRandomID,
6
+ } from "../utils/index.js"
2
7
  import { $HMR_ACCEPT, $SIGNAL } from "../constants.js"
3
8
  import { __DEV__ } from "../env.js"
4
9
  import { node } from "../globals.js"
5
10
  import { useHook } from "../hooks/utils.js"
6
- import { generateRandomID } from "../generateId.js"
7
11
  import { requestUpdate } from "../scheduler.js"
8
12
  import { tracking, signalSubsMap } from "./globals.js"
9
13
  import type { SignalSubscriber, ReadonlySignal } from "./types.js"
@@ -1,7 +1,7 @@
1
1
  import { __DEV__ } from "../env.js"
2
2
  import { $HMR_ACCEPT } from "../constants.js"
3
3
  import { useHook } from "../hooks/utils.js"
4
- import { latest } from "../utils.js"
4
+ import { latest } from "../utils/index.js"
5
5
  import { effectQueue, signalSubsMap } from "./globals.js"
6
6
  import { executeWithTracking } from "./effect.js"
7
7
  import { Signal } from "./base.js"
@@ -1,5 +1,5 @@
1
1
  import { node } from "../globals.js"
2
- import { sideEffectsEnabled } from "../utils.js"
2
+ import { sideEffectsEnabled } from "../utils/index.js"
3
3
  import { tracking, effectQueue } from "./globals.js"
4
4
  import { tick } from "./utils.js"
5
5
  import type { Signal } from "./base.js"
@@ -1,11 +1,10 @@
1
1
  import { __DEV__ } from "../env.js"
2
2
  import type { HMRAccept } from "../hmr.js"
3
3
  import { $HMR_ACCEPT } from "../constants.js"
4
- import { sideEffectsEnabled, useHook } from "../hooks/utils.js"
4
+ import { useHook } from "../hooks/utils.js"
5
5
  import { effectQueue } from "./globals.js"
6
- import { generateRandomID } from "../generateId.js"
7
6
  import { executeWithTracking } from "./effect.js"
8
- import { latest } from "../utils.js"
7
+ import { latest, sideEffectsEnabled, generateRandomID } from "../utils/index.js"
9
8
  import type { Signal } from "./base.js"
10
9
  import type { SignalValues } from "./types.js"
11
10
 
package/src/ssr/server.ts CHANGED
@@ -6,10 +6,10 @@ import {
6
6
  encodeHtmlEntities,
7
7
  propsToElementAttributes,
8
8
  isExoticType,
9
- } from "../utils.js"
9
+ assertValidElementProps,
10
+ } from "../utils/index.js"
10
11
  import { Signal } from "../signals/base.js"
11
12
  import { $HYDRATION_BOUNDARY, voidElements } from "../constants.js"
12
- import { assertValidElementProps } from "../props.js"
13
13
  import { HYDRATION_BOUNDARY_MARKER } from "./hydrationBoundary.js"
14
14
  import { __DEV__ } from "../env.js"
15
15
 
@@ -58,9 +58,8 @@ function renderToStream_internal(
58
58
  el.parent = parent
59
59
  el.depth = (parent?.depth ?? -1) + 1
60
60
  el.index = idx
61
- const props = el.props ?? {}
61
+ const { type, props = {} } = el
62
62
  const children = props.children
63
- const type = el.type
64
63
  if (type === "#text") {
65
64
  stream.push(encodeHtmlEntities(props.nodeValue ?? ""))
66
65
  return
package/src/store.ts CHANGED
@@ -1,9 +1,13 @@
1
1
  import type { Prettify } from "./types.utils.js"
2
2
  import { __DEV__ } from "./env.js"
3
- import { sideEffectsEnabled, useHook } from "./hooks/utils.js"
4
- import { safeStringify, shallowCompare } from "./utils.js"
3
+ import { useHook } from "./hooks/utils.js"
5
4
  import { $HMR_ACCEPT } from "./constants.js"
6
5
  import { HMRAccept } from "./hmr.js"
6
+ import {
7
+ safeStringify,
8
+ shallowCompare,
9
+ sideEffectsEnabled,
10
+ } from "./utils/index.js"
7
11
 
8
12
  export { createStore }
9
13
  export type { Store, MethodFactory }
package/src/swr.ts CHANGED
@@ -3,12 +3,12 @@ import { useHook } from "./hooks/utils.js"
3
3
  import { Signal } from "./signals/base.js"
4
4
  import { AsyncTaskState } from "./types.utils.js"
5
5
  import {
6
- noop,
7
6
  deepCompare,
7
+ noop,
8
8
  safeStringify,
9
- sideEffectsEnabled,
10
9
  shallowCompare,
11
- } from "./utils.js"
10
+ sideEffectsEnabled,
11
+ } from "./utils/index.js"
12
12
 
13
13
  export type UseSWRState<T> = AsyncTaskState<T, UseSWRError> & {
14
14
  mutate: (callback: () => Promise<T>) => void
package/src/types.dom.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Signal } from "./signals"
1
+ import type { Signal } from "./signals"
2
2
  import type { Prettify, Signalable } from "./types.utils"
3
3
 
4
4
  export type {
@@ -60,6 +60,7 @@ type NumericStyleKeys =
60
60
  | "width"
61
61
 
62
62
  // Flexbox
63
+ | "flex"
63
64
  | "flexBasis"
64
65
  | "flexGrow"
65
66
  | "flexShrink"
package/src/types.ts CHANGED
@@ -16,7 +16,12 @@ import type {
16
16
  HTMLTagToElement,
17
17
  SVGTagToElement,
18
18
  } from "./types.dom"
19
- import { AsyncTaskState, Prettify, Signalable, SomeDom } from "./types.utils"
19
+ import type {
20
+ AsyncTaskState,
21
+ Prettify,
22
+ Signalable,
23
+ SomeDom,
24
+ } from "./types.utils"
20
25
  import type { AppContext } from "./appContext"
21
26
 
22
27
  export type { AsyncTaskState, ElementProps, Prettify, Signalable, StyleObject }
@@ -128,10 +133,12 @@ declare global {
128
133
  displayName?: string
129
134
  }
130
135
 
131
- type FC<T = {}> = ((props: FCProps<T>) => JSX.Element) & {
136
+ interface FC<T = {}> {
137
+ (props: FCProps<T>): JSX.Element
132
138
  /** Used to display the name of the component in devtools */
133
139
  displayName?: string
134
140
  }
141
+
135
142
  type FCProps<T = {}> = T & { children?: JSX.Children }
136
143
  type InferProps<T> = T extends Kiru.FC<infer P> ? P : never
137
144
 
@@ -0,0 +1,125 @@
1
+ export function deepCompare<T>(a: T, b: T): boolean {
2
+ return compare(a, b, true)
3
+ }
4
+
5
+ export function shallowCompare<T>(a: T, b: T): boolean {
6
+ return compare(a, b, false)
7
+ }
8
+
9
+ function compare<T>(a: T, b: T, deep = false): boolean {
10
+ // Fast path: identity comparison
11
+ if (a === b) return true
12
+
13
+ // Handle primitive types and null/undefined
14
+ if (
15
+ a == null ||
16
+ b == null ||
17
+ typeof a !== "object" ||
18
+ typeof b !== "object"
19
+ ) {
20
+ return false
21
+ }
22
+
23
+ // Handle arrays efficiently
24
+ if (Array.isArray(a) && Array.isArray(b)) {
25
+ if (a.length !== b.length) return false
26
+
27
+ if (deep) {
28
+ for (let i = 0; i < a.length; i++) {
29
+ if (!compare(a[i], b[i], true)) return false
30
+ }
31
+ } else {
32
+ for (let i = 0; i < a.length; i++) {
33
+ if (!Object.is(a[i], b[i])) return false
34
+ }
35
+ }
36
+ return true
37
+ }
38
+
39
+ // Handle Maps
40
+ if (a instanceof Map && b instanceof Map) {
41
+ if (a.size !== b.size) return false
42
+
43
+ for (const [key, valueA] of a) {
44
+ if (!b.has(key)) return false
45
+
46
+ const valueB = b.get(key)
47
+ if (deep) {
48
+ if (!compare(valueA, valueB, true)) return false
49
+ } else {
50
+ if (!Object.is(valueA, valueB)) return false
51
+ }
52
+ }
53
+ return true
54
+ }
55
+
56
+ // Handle Sets more efficiently
57
+ if (a instanceof Set && b instanceof Set) {
58
+ if (a.size !== b.size) return false
59
+
60
+ if (deep) {
61
+ // For deep equality of Sets, we need to compare the values themselves
62
+ // Convert to arrays and sort for comparison
63
+ const aValues = Array.from(a)
64
+ const bValues = Array.from(b)
65
+
66
+ if (aValues.length !== bValues.length) return false
67
+
68
+ // Simple compare doesn't work for objects in Sets with deep comparison
69
+ // Using a matching algorithm instead
70
+ for (const valueA of aValues) {
71
+ // Find matching element in bValues
72
+ let found = false
73
+ for (let i = 0; i < bValues.length; i++) {
74
+ if (compare(valueA, bValues[i], true)) {
75
+ bValues.splice(i, 1) // Remove the matched element
76
+ found = true
77
+ break
78
+ }
79
+ }
80
+ if (!found) return false
81
+ }
82
+ return true
83
+ } else {
84
+ // Regular Set comparison
85
+ for (const valueA of a) {
86
+ if (!b.has(valueA)) return false
87
+ }
88
+ return true
89
+ }
90
+ }
91
+
92
+ // Handle Date objects
93
+ if (a instanceof Date && b instanceof Date) {
94
+ return a.getTime() === b.getTime()
95
+ }
96
+
97
+ // Handle RegExp objects
98
+ if (a instanceof RegExp && b instanceof RegExp) {
99
+ return a.toString() === b.toString()
100
+ }
101
+
102
+ // Handle plain objects
103
+ const keysA = Object.keys(a)
104
+ const keysB = Object.keys(b)
105
+
106
+ if (keysA.length !== keysB.length) return false
107
+
108
+ // Use a Set for faster key lookup
109
+ const keySet = new Set(keysB)
110
+
111
+ for (const key of keysA) {
112
+ if (!keySet.has(key)) return false
113
+
114
+ const valueA = a[key as keyof T]
115
+ const valueB = b[key as keyof T]
116
+
117
+ if (deep) {
118
+ if (!compare(valueA, valueB, true)) return false
119
+ } else {
120
+ if (!Object.is(valueA, valueB)) return false
121
+ }
122
+ }
123
+
124
+ return true
125
+ }