kiru 0.48.3 → 0.49.0

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 +8 -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 +2 -1
  34. package/dist/constants.d.ts.map +1 -1
  35. package/dist/constants.js +79 -1
  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 +8 -9
  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 +1 -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 +1 -2
  92. package/dist/renderToString.js.map +1 -1
  93. package/dist/scheduler.js +2 -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 +1 -2
  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 +129 -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 +9 -9
  147. package/src/{transition.ts → components/transition.ts} +5 -5
  148. package/src/constants.ts +80 -1
  149. package/src/context.ts +1 -1
  150. package/src/customEvents.ts +22 -22
  151. package/src/dom.ts +7 -8
  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 +1 -2
  168. package/src/index.ts +2 -5
  169. package/src/reconciler.ts +13 -11
  170. package/src/renderToString.ts +2 -2
  171. package/src/scheduler.ts +2 -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 +2 -2
  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 +158 -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
@@ -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,
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
 
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
@@ -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
 
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
+ }
@@ -0,0 +1,158 @@
1
+ import { unwrap } from "../signals/index.js"
2
+ import {
3
+ booleanAttributes,
4
+ REGEX_UNIT,
5
+ snakeCaseAttributes,
6
+ } from "../constants.js"
7
+
8
+ export {
9
+ className,
10
+ encodeHtmlEntities,
11
+ propFilters,
12
+ propToHtmlAttr,
13
+ styleObjectToString,
14
+ propValueToHtmlAttrValue,
15
+ propsToElementAttributes,
16
+ safeStringify,
17
+ }
18
+
19
+ function className(...classes: (string | false | null | undefined)[]): string {
20
+ return classes.filter(Boolean).join(" ")
21
+ }
22
+
23
+ function encodeHtmlEntities(text: string): string {
24
+ return text
25
+ .replace(REGEX_UNIT.AMP_G, "&amp;")
26
+ .replace(REGEX_UNIT.LT_G, "&lt;")
27
+ .replace(REGEX_UNIT.GT_G, "&gt;")
28
+ .replace(REGEX_UNIT.DBLQT_G, "&quot;")
29
+ .replace(REGEX_UNIT.SQT_G, "&#039;")
30
+ .replace(REGEX_UNIT.SLASH_G, "&#47;")
31
+ }
32
+
33
+ const propFilters = {
34
+ internalProps: ["children", "ref", "key", "innerHTML"],
35
+ isEvent: (key: string) => key.startsWith("on"),
36
+ isProperty: (key: string) =>
37
+ !propFilters.internalProps.includes(key) && !propFilters.isEvent(key),
38
+ }
39
+
40
+ function propToHtmlAttr(key: string): string {
41
+ switch (key) {
42
+ case "className":
43
+ return "class"
44
+ case "htmlFor":
45
+ return "for"
46
+ case "tabIndex":
47
+ case "formAction":
48
+ case "formMethod":
49
+ case "formEncType":
50
+ case "contentEditable":
51
+ case "spellCheck":
52
+ case "allowFullScreen":
53
+ case "autoPlay":
54
+ case "disablePictureInPicture":
55
+ case "disableRemotePlayback":
56
+ case "formNoValidate":
57
+ case "noModule":
58
+ case "noValidate":
59
+ case "popoverTarget":
60
+ case "popoverTargetAction":
61
+ case "playsInline":
62
+ case "readOnly":
63
+ case "itemscope":
64
+ case "rowSpan":
65
+ case "crossOrigin":
66
+ return key.toLowerCase()
67
+
68
+ default:
69
+ if (key.indexOf("-") > -1) return key
70
+ if (key.startsWith("aria"))
71
+ return "aria-" + key.substring(4).toLowerCase()
72
+
73
+ return snakeCaseAttributes.get(key) || key
74
+ }
75
+ }
76
+
77
+ function styleObjectToString(obj: Partial<CSSStyleDeclaration>): string {
78
+ let cssString = ""
79
+ for (const key in obj) {
80
+ const cssKey = key.replace(REGEX_UNIT.ALPHA_UPPER_G, "-$&").toLowerCase()
81
+ cssString += `${cssKey}:${obj[key]};`
82
+ }
83
+ return cssString
84
+ }
85
+
86
+ function stylePropToString(style: unknown) {
87
+ if (typeof style === "string") return style
88
+ if (typeof style === "object" && !!style) return styleObjectToString(style)
89
+ return ""
90
+ }
91
+
92
+ function propValueToHtmlAttrValue(key: string, value: unknown): string {
93
+ return key === "style" && typeof value === "object" && !!value
94
+ ? styleObjectToString(value)
95
+ : String(value)
96
+ }
97
+ function propsToElementAttributes(props: Record<string, unknown>): string {
98
+ const attrs: string[] = []
99
+ const { className, style, ...rest } = props
100
+ if (className) {
101
+ const val = unwrap(className)
102
+ if (!!val) attrs.push(`class="${val}"`)
103
+ }
104
+ if (style) {
105
+ const val = unwrap(style)
106
+ if (!!val) attrs.push(`style="${stylePropToString(val)}"`)
107
+ }
108
+
109
+ const keys = Object.keys(rest).filter(propFilters.isProperty)
110
+ for (let i = 0; i < keys.length; i++) {
111
+ let k = keys[i]
112
+ let val = unwrap(props[k])
113
+ if (val === null || val === undefined) continue
114
+
115
+ k = k.split("bind:")[1] ?? k // normalize bind props
116
+ const key = propToHtmlAttr(k)
117
+
118
+ switch (typeof val) {
119
+ case "function":
120
+ case "symbol":
121
+ continue
122
+ case "boolean":
123
+ if (booleanAttributes.has(key)) {
124
+ if (val) attrs.push(key)
125
+ continue
126
+ }
127
+ }
128
+ attrs.push(`${key}="${val}"`)
129
+ }
130
+ return attrs.join(" ")
131
+ }
132
+
133
+ type SafeStringifyOptions = {
134
+ /**
135
+ * By default, functions are stringified. Specify `false` to instead produce `[FUNCTION (${fn.name})]`.
136
+ */
137
+ functions: boolean
138
+ }
139
+
140
+ function safeStringify(
141
+ value: unknown,
142
+ opts: SafeStringifyOptions = { functions: true }
143
+ ): string {
144
+ const seen = new WeakSet()
145
+ return JSON.stringify(value, (_, value) => {
146
+ if (typeof value === "object" && value !== null) {
147
+ if (seen.has(value)) {
148
+ return "[CIRCULAR]"
149
+ }
150
+ seen.add(value)
151
+ }
152
+ if (typeof value === "function") {
153
+ if (!opts.functions) return `[FUNCTION (${value.name || "anonymous"})]`
154
+ return value.toString()
155
+ }
156
+ return value
157
+ })
158
+ }
@@ -0,0 +1,7 @@
1
+ export * from "./compare.js"
2
+ export * from "./format.js"
3
+ export * from "./runtime.js"
4
+ export * from "./vdom.js"
5
+ export * from "./generateId.js"
6
+
7
+ export const noop = Object.freeze(() => {})
@@ -0,0 +1,25 @@
1
+ import { __DEV__ } from "../env.js"
2
+ import { renderMode } from "../globals.js"
3
+
4
+ export { latest, sideEffectsEnabled }
5
+
6
+ /**
7
+ * This is a no-op in production. It is used to get the latest
8
+ * iteration of a component or signal after HMR has happened.
9
+ */
10
+ function latest<T>(thing: T): T {
11
+ let tgt: any = thing
12
+ if (__DEV__) {
13
+ while ("__next" in tgt) {
14
+ tgt = tgt.__next as typeof tgt
15
+ }
16
+ }
17
+ return tgt
18
+ }
19
+
20
+ /**
21
+ * Returns false if called during "stream" or "string" render modes.
22
+ */
23
+ function sideEffectsEnabled(): boolean {
24
+ return renderMode.current === "dom" || renderMode.current === "hydrate"
25
+ }