kiru 0.54.4 → 1.1.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 (381) hide show
  1. package/dist/{appContext.d.ts → appHandle.d.ts} +4 -4
  2. package/dist/appHandle.d.ts.map +1 -0
  3. package/dist/{appContext.js → appHandle.js} +13 -10
  4. package/dist/appHandle.js.map +1 -0
  5. package/dist/components/derive.d.ts +10 -8
  6. package/dist/components/derive.d.ts.map +1 -1
  7. package/dist/components/derive.js +50 -47
  8. package/dist/components/derive.js.map +1 -1
  9. package/dist/components/index.d.ts +0 -1
  10. package/dist/components/index.d.ts.map +1 -1
  11. package/dist/components/index.js +0 -1
  12. package/dist/components/index.js.map +1 -1
  13. package/dist/components/lazy.d.ts.map +1 -1
  14. package/dist/components/lazy.js +7 -6
  15. package/dist/components/lazy.js.map +1 -1
  16. package/dist/components/portal.d.ts.map +1 -1
  17. package/dist/components/portal.js +2 -3
  18. package/dist/components/portal.js.map +1 -1
  19. package/dist/components/transition.d.ts +3 -2
  20. package/dist/components/transition.d.ts.map +1 -1
  21. package/dist/components/transition.js +29 -30
  22. package/dist/components/transition.js.map +1 -1
  23. package/dist/constants.d.ts +1 -5
  24. package/dist/constants.d.ts.map +1 -1
  25. package/dist/constants.js +1 -5
  26. package/dist/constants.js.map +1 -1
  27. package/dist/context.d.ts +1 -1
  28. package/dist/context.d.ts.map +1 -1
  29. package/dist/context.js +25 -19
  30. package/dist/context.js.map +1 -1
  31. package/dist/devtools.d.ts +7 -0
  32. package/dist/devtools.d.ts.map +1 -0
  33. package/dist/devtools.js +19 -0
  34. package/dist/devtools.js.map +1 -0
  35. package/dist/dom/commit.d.ts +5 -0
  36. package/dist/dom/commit.d.ts.map +1 -0
  37. package/dist/dom/commit.js +94 -0
  38. package/dist/dom/commit.js.map +1 -0
  39. package/dist/dom/focus.d.ts +4 -0
  40. package/dist/dom/focus.d.ts.map +1 -0
  41. package/dist/dom/focus.js +32 -0
  42. package/dist/dom/focus.js.map +1 -0
  43. package/dist/dom/index.d.ts +4 -0
  44. package/dist/dom/index.d.ts.map +1 -0
  45. package/dist/dom/index.js +4 -0
  46. package/dist/dom/index.js.map +1 -0
  47. package/dist/dom/nodes.d.ts +12 -0
  48. package/dist/dom/nodes.d.ts.map +1 -0
  49. package/dist/dom/nodes.js +165 -0
  50. package/dist/dom/nodes.js.map +1 -0
  51. package/dist/dom/props.d.ts +8 -0
  52. package/dist/dom/props.d.ts.map +1 -0
  53. package/dist/dom/props.js +675 -0
  54. package/dist/dom/props.js.map +1 -0
  55. package/dist/env.d.ts +2 -0
  56. package/dist/env.d.ts.map +1 -1
  57. package/dist/env.js +2 -0
  58. package/dist/env.js.map +1 -1
  59. package/dist/globalContext.d.ts +17 -23
  60. package/dist/globalContext.d.ts.map +1 -1
  61. package/dist/globalContext.js +31 -53
  62. package/dist/globalContext.js.map +1 -1
  63. package/dist/globals.d.ts +21 -4
  64. package/dist/globals.d.ts.map +1 -1
  65. package/dist/globals.js +22 -5
  66. package/dist/globals.js.map +1 -1
  67. package/dist/headlessRender.d.ts +6 -0
  68. package/dist/headlessRender.d.ts.map +1 -0
  69. package/dist/{recursiveRender.js → headlessRender.js} +17 -16
  70. package/dist/headlessRender.js.map +1 -0
  71. package/dist/hmr.d.ts +21 -8
  72. package/dist/hmr.d.ts.map +1 -1
  73. package/dist/hmr.js +58 -37
  74. package/dist/hmr.js.map +1 -1
  75. package/dist/hooks/index.d.ts +4 -14
  76. package/dist/hooks/index.d.ts.map +1 -1
  77. package/dist/hooks/index.js +4 -14
  78. package/dist/hooks/index.js.map +1 -1
  79. package/dist/hooks/onBeforeMount.d.ts +9 -0
  80. package/dist/hooks/onBeforeMount.d.ts.map +1 -0
  81. package/dist/hooks/onBeforeMount.js +19 -0
  82. package/dist/hooks/onBeforeMount.js.map +1 -0
  83. package/dist/hooks/onCleanup.d.ts +8 -0
  84. package/dist/hooks/onCleanup.d.ts.map +1 -0
  85. package/dist/hooks/onCleanup.js +18 -0
  86. package/dist/hooks/onCleanup.js.map +1 -0
  87. package/dist/hooks/onMount.d.ts +9 -0
  88. package/dist/hooks/onMount.d.ts.map +1 -0
  89. package/dist/hooks/onMount.js +19 -0
  90. package/dist/hooks/onMount.js.map +1 -0
  91. package/dist/hooks/setup.d.ts +13 -0
  92. package/dist/hooks/setup.d.ts.map +1 -0
  93. package/dist/hooks/setup.js +54 -0
  94. package/dist/hooks/setup.js.map +1 -0
  95. package/dist/hooks/utils.d.ts +2 -63
  96. package/dist/hooks/utils.d.ts.map +1 -1
  97. package/dist/hooks/utils.js +17 -144
  98. package/dist/hooks/utils.js.map +1 -1
  99. package/dist/index.d.ts +9 -4
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +11 -8
  102. package/dist/index.js.map +1 -1
  103. package/dist/profiling.d.ts +15 -14
  104. package/dist/profiling.d.ts.map +1 -1
  105. package/dist/profiling.js +9 -4
  106. package/dist/profiling.js.map +1 -1
  107. package/dist/reconciler.d.ts.map +1 -1
  108. package/dist/reconciler.js +15 -28
  109. package/dist/reconciler.js.map +1 -1
  110. package/dist/ref.d.ts +4 -0
  111. package/dist/ref.d.ts.map +1 -0
  112. package/dist/ref.js +4 -0
  113. package/dist/ref.js.map +1 -0
  114. package/dist/renderToString.js +1 -1
  115. package/dist/renderToString.js.map +1 -1
  116. package/dist/router/context.d.ts.map +1 -1
  117. package/dist/router/context.js +1 -2
  118. package/dist/router/context.js.map +1 -1
  119. package/dist/router/fileRouter.d.ts +1 -1
  120. package/dist/router/fileRouter.d.ts.map +1 -1
  121. package/dist/router/fileRouter.js +17 -11
  122. package/dist/router/fileRouter.js.map +1 -1
  123. package/dist/router/fileRouterController.d.ts.map +1 -1
  124. package/dist/router/fileRouterController.js +68 -55
  125. package/dist/router/fileRouterController.js.map +1 -1
  126. package/dist/router/head.js +2 -2
  127. package/dist/router/head.js.map +1 -1
  128. package/dist/router/link.d.ts.map +1 -1
  129. package/dist/router/link.js +19 -23
  130. package/dist/router/link.js.map +1 -1
  131. package/dist/router/pageConfig.js +2 -2
  132. package/dist/router/pageConfig.js.map +1 -1
  133. package/dist/router/server/index.d.ts.map +1 -1
  134. package/dist/router/server/index.js +14 -11
  135. package/dist/router/server/index.js.map +1 -1
  136. package/dist/router/types.d.ts +11 -6
  137. package/dist/router/types.d.ts.map +1 -1
  138. package/dist/scheduler.d.ts +1 -0
  139. package/dist/scheduler.d.ts.map +1 -1
  140. package/dist/scheduler.js +91 -73
  141. package/dist/scheduler.js.map +1 -1
  142. package/dist/signals/base.d.ts +0 -1
  143. package/dist/signals/base.d.ts.map +1 -1
  144. package/dist/signals/base.js +14 -37
  145. package/dist/signals/base.js.map +1 -1
  146. package/dist/signals/computed.d.ts +0 -2
  147. package/dist/signals/computed.d.ts.map +1 -1
  148. package/dist/signals/computed.js +1 -40
  149. package/dist/signals/computed.js.map +1 -1
  150. package/dist/signals/effect.d.ts +15 -14
  151. package/dist/signals/effect.d.ts.map +1 -1
  152. package/dist/signals/effect.js +65 -37
  153. package/dist/signals/effect.js.map +1 -1
  154. package/dist/signals/globals.d.ts +0 -5
  155. package/dist/signals/globals.d.ts.map +1 -1
  156. package/dist/signals/globals.js +0 -6
  157. package/dist/signals/globals.js.map +1 -1
  158. package/dist/signals/index.d.ts +4 -4
  159. package/dist/signals/index.d.ts.map +1 -1
  160. package/dist/signals/index.js +4 -4
  161. package/dist/signals/index.js.map +1 -1
  162. package/dist/signals/{for.d.ts → jsx.d.ts} +8 -1
  163. package/dist/signals/jsx.d.ts.map +1 -0
  164. package/dist/signals/{for.js → jsx.js} +4 -1
  165. package/dist/signals/jsx.js.map +1 -0
  166. package/dist/signals/tracking.d.ts +24 -0
  167. package/dist/signals/tracking.d.ts.map +1 -0
  168. package/dist/signals/tracking.js +51 -0
  169. package/dist/signals/tracking.js.map +1 -0
  170. package/dist/signals/types.d.ts +1 -1
  171. package/dist/signals/types.d.ts.map +1 -1
  172. package/dist/signals/utils.d.ts +2 -1
  173. package/dist/signals/utils.d.ts.map +1 -1
  174. package/dist/signals/utils.js +9 -2
  175. package/dist/signals/utils.js.map +1 -1
  176. package/dist/ssr/client.d.ts +3 -3
  177. package/dist/ssr/client.d.ts.map +1 -1
  178. package/dist/ssr/client.js.map +1 -1
  179. package/dist/ssr/server.js +1 -1
  180. package/dist/ssr/server.js.map +1 -1
  181. package/dist/statefulPromise.d.ts +22 -0
  182. package/dist/statefulPromise.d.ts.map +1 -0
  183. package/dist/statefulPromise.js +94 -0
  184. package/dist/statefulPromise.js.map +1 -0
  185. package/dist/types.d.ts +40 -50
  186. package/dist/types.d.ts.map +1 -1
  187. package/dist/types.dom.d.ts +5 -8
  188. package/dist/types.dom.d.ts.map +1 -1
  189. package/dist/types.utils.d.ts +3 -4
  190. package/dist/types.utils.d.ts.map +1 -1
  191. package/dist/utils/format.d.ts.map +1 -1
  192. package/dist/utils/format.js +4 -1
  193. package/dist/utils/format.js.map +1 -1
  194. package/dist/utils/vdom.d.ts +8 -6
  195. package/dist/utils/vdom.d.ts.map +1 -1
  196. package/dist/utils/vdom.js +32 -9
  197. package/dist/utils/vdom.js.map +1 -1
  198. package/dist/viewTransitions.d.ts +7 -0
  199. package/dist/viewTransitions.d.ts.map +1 -0
  200. package/dist/viewTransitions.js +72 -0
  201. package/dist/viewTransitions.js.map +1 -0
  202. package/package.json +1 -1
  203. package/src/{appContext.ts → appHandle.ts} +22 -17
  204. package/src/components/derive.ts +74 -69
  205. package/src/components/index.ts +0 -1
  206. package/src/components/lazy.ts +10 -10
  207. package/src/components/portal.ts +2 -3
  208. package/src/components/transition.ts +33 -39
  209. package/src/constants.ts +0 -8
  210. package/src/context.ts +30 -23
  211. package/src/devtools.ts +18 -0
  212. package/src/dom/commit.ts +133 -0
  213. package/src/dom/focus.ts +34 -0
  214. package/src/dom/index.ts +3 -0
  215. package/src/dom/nodes.ts +204 -0
  216. package/src/dom/props.ts +818 -0
  217. package/src/env.ts +3 -0
  218. package/src/globalContext.ts +51 -85
  219. package/src/globals.ts +25 -6
  220. package/src/{recursiveRender.ts → headlessRender.ts} +18 -18
  221. package/src/hmr.ts +60 -42
  222. package/src/hooks/index.ts +4 -14
  223. package/src/hooks/onBeforeMount.ts +18 -0
  224. package/src/hooks/onCleanup.ts +21 -0
  225. package/src/hooks/onMount.ts +18 -0
  226. package/src/hooks/setup.ts +70 -0
  227. package/src/hooks/utils.ts +24 -239
  228. package/src/index.ts +17 -7
  229. package/src/profiling.ts +22 -20
  230. package/src/reconciler.ts +21 -33
  231. package/src/ref.ts +6 -0
  232. package/src/renderToString.ts +1 -1
  233. package/src/router/context.ts +1 -2
  234. package/src/router/fileRouter.ts +23 -13
  235. package/src/router/fileRouterController.ts +72 -64
  236. package/src/router/head.ts +2 -2
  237. package/src/router/link.ts +11 -25
  238. package/src/router/pageConfig.ts +2 -2
  239. package/src/router/server/index.ts +24 -13
  240. package/src/router/types.ts +15 -8
  241. package/src/scheduler.ts +116 -98
  242. package/src/signals/base.ts +13 -42
  243. package/src/signals/computed.ts +1 -62
  244. package/src/signals/effect.ts +93 -48
  245. package/src/signals/globals.ts +0 -7
  246. package/src/signals/index.ts +4 -4
  247. package/src/signals/{for.ts → jsx.ts} +10 -0
  248. package/src/signals/tracking.ts +70 -0
  249. package/src/signals/types.ts +1 -1
  250. package/src/signals/utils.ts +9 -1
  251. package/src/ssr/client.ts +4 -4
  252. package/src/ssr/server.ts +2 -2
  253. package/src/statefulPromise.ts +136 -0
  254. package/src/types.dom.ts +6 -10
  255. package/src/types.ts +51 -60
  256. package/src/types.utils.ts +3 -4
  257. package/src/utils/format.ts +3 -1
  258. package/src/utils/vdom.ts +44 -15
  259. package/src/viewTransitions.ts +89 -0
  260. package/dist/appContext.d.ts.map +0 -1
  261. package/dist/appContext.js.map +0 -1
  262. package/dist/components/memo.d.ts +0 -10
  263. package/dist/components/memo.d.ts.map +0 -1
  264. package/dist/components/memo.js +0 -23
  265. package/dist/components/memo.js.map +0 -1
  266. package/dist/dom.d.ts +0 -10
  267. package/dist/dom.d.ts.map +0 -1
  268. package/dist/dom.js +0 -634
  269. package/dist/dom.js.map +0 -1
  270. package/dist/form/index.d.ts +0 -4
  271. package/dist/form/index.d.ts.map +0 -1
  272. package/dist/form/index.js +0 -518
  273. package/dist/form/index.js.map +0 -1
  274. package/dist/form/types.d.ts +0 -122
  275. package/dist/form/types.d.ts.map +0 -1
  276. package/dist/form/types.js +0 -2
  277. package/dist/form/types.js.map +0 -1
  278. package/dist/form/utils.d.ts +0 -3
  279. package/dist/form/utils.d.ts.map +0 -1
  280. package/dist/form/utils.js +0 -16
  281. package/dist/form/utils.js.map +0 -1
  282. package/dist/hooks/useAsync.d.ts +0 -18
  283. package/dist/hooks/useAsync.d.ts.map +0 -1
  284. package/dist/hooks/useAsync.js +0 -96
  285. package/dist/hooks/useAsync.js.map +0 -1
  286. package/dist/hooks/useCallback.d.ts +0 -7
  287. package/dist/hooks/useCallback.d.ts.map +0 -1
  288. package/dist/hooks/useCallback.js +0 -30
  289. package/dist/hooks/useCallback.js.map +0 -1
  290. package/dist/hooks/useContext.d.ts +0 -7
  291. package/dist/hooks/useContext.d.ts.map +0 -1
  292. package/dist/hooks/useContext.js +0 -59
  293. package/dist/hooks/useContext.js.map +0 -1
  294. package/dist/hooks/useEffect.d.ts +0 -8
  295. package/dist/hooks/useEffect.d.ts.map +0 -1
  296. package/dist/hooks/useEffect.js +0 -34
  297. package/dist/hooks/useEffect.js.map +0 -1
  298. package/dist/hooks/useEffectEvent.d.ts +0 -8
  299. package/dist/hooks/useEffectEvent.d.ts.map +0 -1
  300. package/dist/hooks/useEffectEvent.js +0 -23
  301. package/dist/hooks/useEffectEvent.js.map +0 -1
  302. package/dist/hooks/useId.d.ts +0 -8
  303. package/dist/hooks/useId.d.ts.map +0 -1
  304. package/dist/hooks/useId.js +0 -35
  305. package/dist/hooks/useId.js.map +0 -1
  306. package/dist/hooks/useLayoutEffect.d.ts +0 -8
  307. package/dist/hooks/useLayoutEffect.d.ts.map +0 -1
  308. package/dist/hooks/useLayoutEffect.js +0 -34
  309. package/dist/hooks/useLayoutEffect.js.map +0 -1
  310. package/dist/hooks/useMemo.d.ts +0 -8
  311. package/dist/hooks/useMemo.d.ts.map +0 -1
  312. package/dist/hooks/useMemo.js +0 -31
  313. package/dist/hooks/useMemo.js.map +0 -1
  314. package/dist/hooks/usePromise.d.ts +0 -8
  315. package/dist/hooks/usePromise.d.ts.map +0 -1
  316. package/dist/hooks/usePromise.js +0 -90
  317. package/dist/hooks/usePromise.js.map +0 -1
  318. package/dist/hooks/useReducer.d.ts +0 -7
  319. package/dist/hooks/useReducer.d.ts.map +0 -1
  320. package/dist/hooks/useReducer.js +0 -44
  321. package/dist/hooks/useReducer.js.map +0 -1
  322. package/dist/hooks/useRef.d.ts +0 -10
  323. package/dist/hooks/useRef.d.ts.map +0 -1
  324. package/dist/hooks/useRef.js +0 -29
  325. package/dist/hooks/useRef.js.map +0 -1
  326. package/dist/hooks/useState.d.ts +0 -7
  327. package/dist/hooks/useState.d.ts.map +0 -1
  328. package/dist/hooks/useState.js +0 -54
  329. package/dist/hooks/useState.js.map +0 -1
  330. package/dist/hooks/useSyncExternalStore.d.ts +0 -8
  331. package/dist/hooks/useSyncExternalStore.d.ts.map +0 -1
  332. package/dist/hooks/useSyncExternalStore.js +0 -50
  333. package/dist/hooks/useSyncExternalStore.js.map +0 -1
  334. package/dist/hooks/useViewTransition.d.ts +0 -10
  335. package/dist/hooks/useViewTransition.d.ts.map +0 -1
  336. package/dist/hooks/useViewTransition.js +0 -27
  337. package/dist/hooks/useViewTransition.js.map +0 -1
  338. package/dist/recursiveRender.d.ts +0 -7
  339. package/dist/recursiveRender.d.ts.map +0 -1
  340. package/dist/recursiveRender.js.map +0 -1
  341. package/dist/signals/for.d.ts.map +0 -1
  342. package/dist/signals/for.js.map +0 -1
  343. package/dist/signals/watch.d.ts +0 -21
  344. package/dist/signals/watch.d.ts.map +0 -1
  345. package/dist/signals/watch.js +0 -86
  346. package/dist/signals/watch.js.map +0 -1
  347. package/dist/store.d.ts +0 -28
  348. package/dist/store.d.ts.map +0 -1
  349. package/dist/store.js +0 -166
  350. package/dist/store.js.map +0 -1
  351. package/dist/swr.d.ts +0 -63
  352. package/dist/swr.d.ts.map +0 -1
  353. package/dist/swr.js +0 -236
  354. package/dist/swr.js.map +0 -1
  355. package/dist/utils/promise.d.ts +0 -16
  356. package/dist/utils/promise.d.ts.map +0 -1
  357. package/dist/utils/promise.js +0 -14
  358. package/dist/utils/promise.js.map +0 -1
  359. package/src/components/memo.ts +0 -39
  360. package/src/dom.ts +0 -809
  361. package/src/form/index.ts +0 -676
  362. package/src/form/types.ts +0 -262
  363. package/src/form/utils.ts +0 -19
  364. package/src/hooks/useAsync.ts +0 -121
  365. package/src/hooks/useCallback.ts +0 -32
  366. package/src/hooks/useContext.ts +0 -79
  367. package/src/hooks/useEffect.ts +0 -40
  368. package/src/hooks/useEffectEvent.ts +0 -24
  369. package/src/hooks/useId.ts +0 -42
  370. package/src/hooks/useLayoutEffect.ts +0 -43
  371. package/src/hooks/useMemo.ts +0 -34
  372. package/src/hooks/usePromise.ts +0 -126
  373. package/src/hooks/useReducer.ts +0 -50
  374. package/src/hooks/useRef.ts +0 -40
  375. package/src/hooks/useState.ts +0 -62
  376. package/src/hooks/useSyncExternalStore.ts +0 -59
  377. package/src/hooks/useViewTransition.ts +0 -25
  378. package/src/signals/watch.ts +0 -139
  379. package/src/store.ts +0 -245
  380. package/src/swr.ts +0 -351
  381. package/src/utils/promise.ts +0 -26
@@ -1,12 +1,11 @@
1
- import { useCallback } from "../hooks/useCallback.js"
2
- import { useEffect } from "../hooks/useEffect.js"
3
- import { useLayoutEffect } from "../hooks/useLayoutEffect.js"
4
- import { useRef } from "../hooks/useRef.js"
5
- import { useState } from "../hooks/useState.js"
1
+ import { onCleanup } from "../hooks/onCleanup.js"
2
+ import { signal, Signal } from "../signals/base.js"
3
+ import { effect } from "../signals/effect.js"
4
+ import { unwrap } from "../signals/utils.js"
6
5
 
7
6
  export type TransitionState = "entering" | "entered" | "exiting" | "exited"
8
7
  interface TransitionProps {
9
- in: boolean
8
+ in: boolean | Signal<boolean>
10
9
  /**
11
10
  * Initial state of the transition
12
11
  * @default "exited"
@@ -22,43 +21,42 @@ interface TransitionProps {
22
21
  onTransitionEnd?: (state: "entered" | "exited") => void
23
22
  }
24
23
 
25
- export function Transition(props: TransitionProps) {
26
- const [tState, setTState] = useState<TransitionState>(
27
- props.initialState || "exited"
28
- )
29
- const timeoutRef = useRef<number | null>(null)
24
+ export const Transition: Kiru.FC<TransitionProps> = (props) => {
25
+ const tState = signal<TransitionState>(props.initialState || "exited")
26
+ let timeoutRef: number | undefined
30
27
 
31
- useLayoutEffect(() => {
32
- if (props.in && tState !== "entered" && tState !== "entering") {
28
+ const setTransitionState = (transitionState: TransitionState) => {
29
+ clearTimeout(timeoutRef)
30
+ tState.value = transitionState
31
+ if (transitionState === "entered" || transitionState === "exited") {
32
+ if (props.onTransitionEnd) props.onTransitionEnd(transitionState)
33
+ }
34
+ }
35
+
36
+ const queueStateChange = (transitionState: "entered" | "exited") => {
37
+ timeoutRef = window.setTimeout(
38
+ () => setTransitionState(transitionState),
39
+ getTiming(transitionState, props.duration)
40
+ )
41
+ }
42
+
43
+ effect(() => {
44
+ const newIn = unwrap(props.in, true)
45
+ const current = tState.peek()
46
+ if (newIn && current !== "entered" && current !== "entering") {
33
47
  setTransitionState("entering")
34
48
  queueStateChange("entered")
35
- } else if (!props.in && tState !== "exited" && tState !== "exiting") {
49
+ } else if (!newIn && current !== "exited" && current !== "exiting") {
36
50
  setTransitionState("exiting")
37
51
  queueStateChange("exited")
38
52
  }
39
- }, [props.in, tState])
53
+ })
40
54
 
41
- useEffect(() => () => clearTimeout(timeoutRef.current), [])
55
+ onCleanup(() => clearTimeout(timeoutRef))
42
56
 
43
- const setTransitionState = useCallback((transitionState: TransitionState) => {
44
- clearTimeout(timeoutRef.current)
45
- setTState(transitionState)
46
- if (transitionState === "entered" || transitionState === "exited") {
47
- if (props.onTransitionEnd) props.onTransitionEnd(transitionState)
48
- }
49
- }, [])
50
-
51
- const queueStateChange = useCallback(
52
- (transitionState: "entered" | "exited") => {
53
- timeoutRef.current = window.setTimeout(
54
- () => setTransitionState(transitionState),
55
- getTiming(transitionState, props.duration)
56
- )
57
- },
58
- [props.duration]
59
- )
60
-
61
- return props.element(tState)
57
+ return (newProps) => {
58
+ return newProps.element(tState.value)
59
+ }
62
60
  }
63
61
 
64
62
  const defaultDuration = 150
@@ -74,7 +72,3 @@ function getTiming(
74
72
  return duration?.out ?? defaultDuration
75
73
  }
76
74
  }
77
-
78
- function clearTimeout(id: number | null) {
79
- if (id != null) window.clearTimeout(id)
80
- }
package/src/constants.ts CHANGED
@@ -1,11 +1,9 @@
1
1
  export {
2
2
  $SIGNAL,
3
3
  $CONTEXT,
4
- $CONTEXT_PROVIDER,
5
4
  $FRAGMENT,
6
5
  $KIRU_ERROR,
7
6
  $HMR_ACCEPT,
8
- $MEMO,
9
7
  $ERROR_BOUNDARY,
10
8
  $STREAM_DATA,
11
9
  $DEV_FILE_LINK,
@@ -16,8 +14,6 @@ export {
16
14
  FLAG_PLACEMENT,
17
15
  FLAG_DELETION,
18
16
  FLAG_STATIC_DOM,
19
- FLAG_MEMO,
20
- FLAG_NOOP,
21
17
  FLAG_DIRTY,
22
18
  }
23
19
 
@@ -25,11 +21,9 @@ export { voidElements, svgTags, booleanAttributes, snakeCaseAttributes }
25
21
 
26
22
  const $SIGNAL = Symbol.for("kiru.signal")
27
23
  const $CONTEXT = Symbol.for("kiru.context")
28
- const $CONTEXT_PROVIDER = Symbol.for("kiru.contextProvider")
29
24
  const $FRAGMENT = Symbol.for("kiru.fragment")
30
25
  const $KIRU_ERROR = Symbol.for("kiru.error")
31
26
  const $HMR_ACCEPT = Symbol.for("kiru.hmrAccept")
32
- const $MEMO = Symbol.for("kiru.memo")
33
27
  const $ERROR_BOUNDARY = Symbol.for("kiru.errorBoundary")
34
28
  const $STREAM_DATA = Symbol.for("kiru.streamData")
35
29
  const $DEV_FILE_LINK = Symbol.for("kiru.devFileLink")
@@ -41,8 +35,6 @@ const FLAG_UPDATE = 1 << 1
41
35
  const FLAG_PLACEMENT = 1 << 2
42
36
  const FLAG_DELETION = 1 << 3
43
37
  const FLAG_STATIC_DOM = 1 << 4
44
- const FLAG_MEMO = 1 << 5
45
- const FLAG_NOOP = 1 << 6
46
38
  const FLAG_DIRTY = 1 << 7
47
39
 
48
40
  const EVENT_PREFIX_REGEX = /^on:?/
package/src/context.ts CHANGED
@@ -1,30 +1,37 @@
1
- import { $CONTEXT, $CONTEXT_PROVIDER } from "./constants.js"
1
+ import { $CONTEXT } from "./constants.js"
2
2
  import { createElement } from "./element.js"
3
- import { useState } from "./hooks/useState.js"
3
+ import type { ContextNode } from "./types.utils.js"
4
+ import { node } from "./globals.js"
4
5
 
5
6
  export function createContext<T>(defaultValue: T): Kiru.Context<T> {
6
- const ctx: Kiru.Context<T> = {
7
- [$CONTEXT]: true,
8
- Provider: ({ value, children }: Kiru.ProviderProps<T>) => {
9
- const [dependents] = useState(() => new Set<Kiru.VNode>())
10
- return createElement(
11
- $CONTEXT_PROVIDER,
12
- { value, ctx, dependents },
13
- typeof children === "function" ? children(value) : children
14
- )
15
- },
16
- default: () => defaultValue,
17
- set displayName(name: string) {
18
- this.Provider.displayName = name
19
- },
20
- get displayName() {
21
- return this.Provider.displayName || "Anonymous Context"
22
- },
23
- }
7
+ const Context: Kiru.Context<T> = Object.assign(
8
+ ({ value, children }: Kiru.ContextProps<T>) =>
9
+ createElement($CONTEXT, { value, ctx: Context }, children),
10
+ { [$CONTEXT]: () => defaultValue }
11
+ )
12
+ Context.displayName = "Anonymous Context"
13
+ return Context
14
+ }
24
15
 
25
- return ctx
16
+ function getContextValue<T>(vNode: Kiru.VNode, context: Kiru.Context<T>): T {
17
+ let n = vNode.parent
18
+ while (n) {
19
+ if (n.type === $CONTEXT) {
20
+ const provider = n as ContextNode<unknown>
21
+ const { ctx, value } = provider.props
22
+ if (ctx === context) {
23
+ return value as T
24
+ }
25
+ }
26
+ n = n.parent
27
+ }
28
+ return context[$CONTEXT]()
26
29
  }
27
30
 
28
- export function isContext<T>(thing: unknown): thing is Kiru.Context<T> {
29
- return typeof thing === "object" && !!thing && $CONTEXT in thing
31
+ export function useContext<T>(context: Kiru.Context<T>): T {
32
+ const n = node.current
33
+ if (!n) {
34
+ throw new Error("useContext must be called inside a Kiru component")
35
+ }
36
+ return getContextValue(n, context)
30
37
  }
@@ -0,0 +1,18 @@
1
+ import type { DebuggerEntry } from "./globalContext"
2
+
3
+ export namespace DevTools {
4
+ export const track = (signal: Kiru.Signal<unknown>, label?: string) => {
5
+ if (!("window" in globalThis)) return
6
+ window.__kiru.devtools?.track(signal, label)
7
+ }
8
+ export const untrack = (signal: Kiru.Signal<unknown>) => {
9
+ if (!("window" in globalThis)) return
10
+ window.__kiru.devtools?.untrack(signal)
11
+ }
12
+ export const subscribe = (
13
+ callback: (entries: Set<DebuggerEntry>) => void
14
+ ) => {
15
+ if (!("window" in globalThis) || !window.__kiru.devtools) return () => {}
16
+ return window.__kiru.devtools.subscribe(callback)
17
+ }
18
+ }
@@ -0,0 +1,133 @@
1
+ import {
2
+ traverseApply,
3
+ commitSnapshot,
4
+ getVNodeApp,
5
+ setRef,
6
+ call,
7
+ } from "../utils/index.js"
8
+ import { FLAG_PLACEMENT, FLAG_STATIC_DOM, FLAG_UPDATE } from "../constants.js"
9
+ import { __DEV__ } from "../env.js"
10
+ import { postEffectCleanups, renderMode } from "../globals.js"
11
+ import { isHmrUpdate } from "../hmr.js"
12
+ import { unmountDomProps, updateDomProps } from "./props.js"
13
+ import { HostNode, getDomParent, placeDom } from "./nodes.js"
14
+ import type { AppHandle } from "../appHandle.js"
15
+ import type { DomVNode, ElementVNode } from "../types.utils"
16
+
17
+ export { commitWork, commitDeletion }
18
+
19
+ type VNode = Kiru.VNode
20
+
21
+ function commitWork(vNode: VNode) {
22
+ if (renderMode.current === "hydrate") {
23
+ return traverseApply(vNode, commitSnapshot)
24
+ }
25
+
26
+ const host: HostNode = {
27
+ node: vNode.dom ? (vNode as ElementVNode) : getDomParent(vNode),
28
+ }
29
+ commitWork_impl(vNode, host, (vNode.flags & FLAG_PLACEMENT) > 0)
30
+ if (vNode.dom && !(vNode.flags & FLAG_STATIC_DOM)) {
31
+ commitDom(vNode as DomVNode, host, false)
32
+ }
33
+ commitSnapshot(vNode)
34
+ }
35
+
36
+ function commitWork_impl(
37
+ vNode: VNode,
38
+ currentHostNode: HostNode,
39
+ inheritsPlacement: boolean
40
+ ) {
41
+ let child: VNode | null = vNode.child
42
+ while (child) {
43
+ if (child.dom) {
44
+ commitWork_impl(child, { node: child as ElementVNode }, false)
45
+ if (!(child.flags & FLAG_STATIC_DOM)) {
46
+ commitDom(child as DomVNode, currentHostNode, inheritsPlacement)
47
+ }
48
+ } else {
49
+ commitWork_impl(
50
+ child,
51
+ currentHostNode,
52
+ (child.flags & FLAG_PLACEMENT) > 0 || inheritsPlacement
53
+ )
54
+ }
55
+
56
+ commitSnapshot(child)
57
+ child = child.sibling
58
+ }
59
+ }
60
+
61
+ function commitDom(
62
+ vNode: DomVNode,
63
+ hostNode: HostNode,
64
+ inheritsPlacement: boolean
65
+ ) {
66
+ if (
67
+ inheritsPlacement ||
68
+ !vNode.dom.isConnected ||
69
+ vNode.flags & FLAG_PLACEMENT
70
+ ) {
71
+ placeDom(vNode, hostNode)
72
+ }
73
+ // During HMR we want to fully unmount previous props (events, signal
74
+ // subscriptions, style listeners, refs, etc.) before applying the new ones,
75
+ // so that we don't merge stale props with the new shape.
76
+ if (__DEV__ && vNode.prev && isHmrUpdate()) {
77
+ const { dom, prev, cleanups } = vNode
78
+ unmountDomProps(vNode, dom, prev.props, cleanups)
79
+ vNode.prev = null
80
+ }
81
+ if (!vNode.prev || vNode.flags & FLAG_UPDATE) {
82
+ updateDomProps(vNode)
83
+ }
84
+ hostNode.lastChild = vNode.dom
85
+ }
86
+
87
+ function commitDeletion(vNode: VNode) {
88
+ if (vNode === vNode.parent?.child) {
89
+ vNode.parent.child = vNode.sibling
90
+ }
91
+ let app: AppHandle
92
+ if (__DEV__) {
93
+ app = getVNodeApp(vNode)!
94
+ }
95
+ traverseApply(vNode, (node) => {
96
+ const {
97
+ subs,
98
+ cleanups,
99
+ dom,
100
+ props: { ref },
101
+ hooks,
102
+ } = node
103
+
104
+ subs?.forEach((unsub) => unsub())
105
+ if (cleanups) Object.values(cleanups).forEach((c) => c())
106
+ if (hooks) {
107
+ const { preCleanups, postCleanups } = hooks
108
+
109
+ postEffectCleanups.push(...postCleanups)
110
+ preCleanups.forEach(call)
111
+ preCleanups.length = postCleanups.length = 0
112
+ }
113
+
114
+ if (__DEV__) {
115
+ window.__kiru.profilingContext?.emit("removeNode", app)
116
+ if (dom instanceof Element) {
117
+ delete dom.__kiruNode
118
+ }
119
+ }
120
+
121
+ if (dom) {
122
+ if (dom.isConnected && !(node.flags & FLAG_STATIC_DOM)) {
123
+ dom.remove()
124
+ }
125
+ if (ref) {
126
+ setRef(ref, null)
127
+ }
128
+ delete node.dom
129
+ }
130
+ })
131
+
132
+ vNode.parent = null
133
+ }
@@ -0,0 +1,34 @@
1
+ let focussedElement: HTMLElement | null = null
2
+
3
+ export function captureFocus() {
4
+ const el = document.activeElement
5
+ if (el === document.body || !(el instanceof HTMLElement)) {
6
+ return
7
+ }
8
+ el.addEventListener("blur", placementBlurHandler)
9
+ focussedElement = el
10
+ }
11
+
12
+ export function reinstateFocus() {
13
+ if (focussedElement) {
14
+ focussedElement.removeEventListener("blur", placementBlurHandler)
15
+ if (focussedElement.isConnected) focussedElement.focus()
16
+ focussedElement = null
17
+ }
18
+ }
19
+
20
+ export function wrapFocusEventHandler(callback: (event: FocusEvent) => void) {
21
+ return (event: FocusEvent) => {
22
+ if (focussedElement) {
23
+ event.preventDefault()
24
+ event.stopPropagation()
25
+ return
26
+ }
27
+ callback(event)
28
+ }
29
+ }
30
+
31
+ function placementBlurHandler(event: FocusEvent) {
32
+ event.preventDefault()
33
+ event.stopPropagation()
34
+ }
@@ -0,0 +1,3 @@
1
+ export { commitDeletion, commitWork } from "./commit.js"
2
+ export { reinstateFocus, captureFocus } from "./focus.js"
3
+ export { createDom, hydrateDom } from "./nodes.js"
@@ -0,0 +1,204 @@
1
+ import { svgTags, FLAG_PLACEMENT, FLAG_STATIC_DOM } from "../constants.js"
2
+ import { Signal } from "../signals/base.js"
3
+ import { unwrap } from "../signals/utils.js"
4
+ import { hydrationStack } from "../hydration.js"
5
+ import {
6
+ getVNodeApp,
7
+ isValidTextChild,
8
+ registerVNodeCleanup,
9
+ } from "../utils/index.js"
10
+ import { KiruError } from "../error.js"
11
+ import { __DEV__, isBrowser } from "../env.js"
12
+ import type { DomVNode, ElementVNode, MaybeDom, SomeDom } from "../types.utils"
13
+
14
+ export { createDom, hydrateDom, getDomParent, placeDom }
15
+
16
+ type VNode = Kiru.VNode
17
+
18
+ export type HostNode = {
19
+ node: ElementVNode
20
+ lastChild?: SomeDom
21
+ }
22
+
23
+ function createDom(vNode: DomVNode): SomeDom {
24
+ const t = vNode.type
25
+ const dom =
26
+ t == "#text"
27
+ ? createTextNode(vNode)
28
+ : svgTags.has(t)
29
+ ? document.createElementNS("http://www.w3.org/2000/svg", t)
30
+ : document.createElement(t)
31
+
32
+ return dom
33
+ }
34
+
35
+ function hydrateDom(vNode: VNode) {
36
+ const dom =
37
+ vNode.type === "#text"
38
+ ? getOrCreateTextNode(vNode)
39
+ : hydrationStack.getCurrentChild()
40
+
41
+ hydrationStack.bumpChildIndex()
42
+
43
+ if (!dom) {
44
+ throw new KiruError({
45
+ message: `Hydration mismatch - no node found`,
46
+ vNode,
47
+ })
48
+ }
49
+ let nodeName = dom.nodeName
50
+ if (!svgTags.has(nodeName)) {
51
+ nodeName = nodeName.toLowerCase()
52
+ }
53
+ if ((vNode.type as string) !== nodeName) {
54
+ throw new KiruError({
55
+ message: `Hydration mismatch - expected node of type ${vNode.type.toString()} but received ${nodeName}`,
56
+ vNode,
57
+ })
58
+ }
59
+ vNode.dom = dom
60
+ if (vNode.type !== "#text" && !(vNode.flags & FLAG_STATIC_DOM)) {
61
+ // updateDom is called later during commit phase
62
+ return
63
+ }
64
+ if (Signal.isSignal(vNode.props.nodeValue)) {
65
+ subTextNode(vNode, dom as Text, vNode.props.nodeValue)
66
+ }
67
+
68
+ let prev = vNode
69
+ let sibling = vNode.sibling
70
+ while (sibling && sibling.type === "#text") {
71
+ const sib = sibling
72
+ hydrationStack.bumpChildIndex()
73
+ const prevText = String(unwrap(prev.props.nodeValue) ?? "")
74
+ const dom = (prev.dom as Text).splitText(prevText.length)
75
+ sib.dom = dom
76
+ if (Signal.isSignal(sib.props.nodeValue)) {
77
+ subTextNode(sib, dom, sib.props.nodeValue)
78
+ }
79
+ prev = sibling
80
+ sibling = sibling.sibling
81
+ }
82
+ }
83
+
84
+ function getDomParent(vNode: VNode): ElementVNode {
85
+ let parentNode: VNode | null = vNode.parent
86
+ let parentNodeElement = parentNode?.dom
87
+ while (parentNode && !parentNodeElement) {
88
+ parentNode = parentNode.parent
89
+ parentNodeElement = parentNode?.dom
90
+ }
91
+
92
+ if (!parentNodeElement || !parentNode) {
93
+ if (!vNode.parent && vNode.dom) {
94
+ return vNode as ElementVNode
95
+ }
96
+
97
+ throw new KiruError({
98
+ message: "No DOM parent found while attempting to place node.",
99
+ vNode: vNode,
100
+ })
101
+ }
102
+ return parentNode as ElementVNode
103
+ }
104
+
105
+ function placeDom(vNode: DomVNode, hostNode: HostNode) {
106
+ const { node: parentVNodeWithDom, lastChild } = hostNode
107
+ const dom = vNode.dom
108
+ if (lastChild) {
109
+ lastChild.after(dom)
110
+ return
111
+ }
112
+ const nextSiblingDom = getNextSiblingDom(vNode, parentVNodeWithDom)
113
+ if (nextSiblingDom) {
114
+ parentVNodeWithDom.dom.insertBefore(dom, nextSiblingDom)
115
+ return
116
+ }
117
+
118
+ parentVNodeWithDom.dom.appendChild(dom)
119
+ }
120
+
121
+ function getNextSiblingDom(vNode: VNode, parent: ElementVNode): MaybeDom {
122
+ let node: VNode | null = vNode
123
+
124
+ while (node) {
125
+ let sibling = node.sibling
126
+
127
+ while (sibling) {
128
+ if (!(sibling.flags & (FLAG_PLACEMENT | FLAG_STATIC_DOM))) {
129
+ const dom = findFirstHostDom(sibling)
130
+ if (dom?.isConnected) return dom
131
+ }
132
+ sibling = sibling.sibling
133
+ }
134
+
135
+ node = node.parent
136
+ if (!node || node.flags & FLAG_STATIC_DOM || node === parent) {
137
+ return
138
+ }
139
+ }
140
+
141
+ return
142
+ }
143
+
144
+ function findFirstHostDom(vNode: VNode): MaybeDom {
145
+ let node: VNode | null = vNode
146
+ while (node) {
147
+ if (node.dom) return node.dom
148
+ if (node.flags & FLAG_STATIC_DOM) return
149
+ node = node.child
150
+ }
151
+ return
152
+ }
153
+
154
+ function getOrCreateTextNode(vNode: VNode): MaybeDom {
155
+ const sig = vNode.props.nodeValue
156
+ if (!Signal.isSignal(sig)) {
157
+ return hydrationStack.getCurrentChild()
158
+ }
159
+
160
+ const value = sig.peek()
161
+ if (isValidTextChild(value)) {
162
+ return hydrationStack.getCurrentChild()
163
+ }
164
+
165
+ const dom = createSignalTextNode(vNode, sig)
166
+ const currentChild = hydrationStack.getCurrentChild()
167
+
168
+ if (!currentChild) {
169
+ return hydrationStack.getCurrentParent().appendChild(dom)
170
+ }
171
+
172
+ currentChild.before(dom)
173
+ return dom
174
+ }
175
+
176
+ function subTextNode(vNode: VNode, textNode: Text, signal: Signal<string>) {
177
+ const cleanup = signal.subscribe((value, prev) => {
178
+ if (value === prev) return
179
+ textNode.nodeValue = value
180
+ if (__DEV__ && isBrowser) {
181
+ window.__kiru?.profilingContext?.emit(
182
+ "signalTextUpdate",
183
+ getVNodeApp(vNode)!
184
+ )
185
+ }
186
+ })
187
+ registerVNodeCleanup(vNode, "nodeValue", cleanup)
188
+ }
189
+
190
+ function createTextNode(vNode: VNode): Text {
191
+ const { nodeValue } = vNode.props
192
+ if (Signal.isSignal(nodeValue)) {
193
+ return createSignalTextNode(vNode, nodeValue)
194
+ }
195
+
196
+ return document.createTextNode(nodeValue)
197
+ }
198
+
199
+ function createSignalTextNode(vNode: VNode, nodeValue: Signal<string>): Text {
200
+ const value = nodeValue.peek() ?? ""
201
+ const textNode = document.createTextNode(value)
202
+ subTextNode(vNode, textNode, nodeValue)
203
+ return textNode
204
+ }