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,11 +1,4 @@
1
- import type { Signal } from "./base.js"
2
1
  import type { SignalSubscriber } from "./types.js"
3
2
 
4
- export const tracking = {
5
- stack: new Array<Map<string, Signal<unknown>>>(),
6
- current: function (): Map<string, Signal<unknown>> | undefined {
7
- return this.stack[this.stack.length - 1]
8
- },
9
- }
10
3
  export const effectQueue = new Map<string, Function>()
11
4
  export const signalSubsMap: Map<string, Set<SignalSubscriber<any>>> = new Map()
@@ -4,9 +4,9 @@
4
4
  * 2. global computed will lose its vNode subscription on HMR
5
5
  * */
6
6
 
7
- export { Signal, signal, useSignal } from "./base.js"
8
- export { ComputedSignal, computed, useComputed } from "./computed.js"
9
- export { WatchEffect, watch, useWatch } from "./watch.js"
7
+ export { Signal, signal } from "./base.js"
8
+ export { ComputedSignal, computed } from "./computed.js"
9
+ export { Effect, effect } from "./effect.js"
10
10
  export { unwrap, tick } from "./utils.js"
11
- export * from "./for.js"
11
+ export * from "./jsx.js"
12
12
  export * from "./types.js"
@@ -1,3 +1,4 @@
1
+ import { Signalable } from "../types.js"
1
2
  import type { Signal } from "./base.js"
2
3
  import { unwrap } from "./utils.js"
3
4
 
@@ -28,3 +29,12 @@ export function For<T extends Signal<any[]> | unknown[]>({
28
29
  if (items.length === 0) return fallback
29
30
  return items.map(children)
30
31
  }
32
+
33
+ export interface ShowProps {
34
+ children: JSX.Element
35
+ when: Signalable<unknown>
36
+ fallback?: JSX.Element
37
+ }
38
+ export function Show({ children, when, fallback }: ShowProps): JSX.Element {
39
+ return !!unwrap(when, true) ? children : fallback
40
+ }
@@ -0,0 +1,70 @@
1
+ import { node } from "../globals.js"
2
+ import { sideEffectsEnabled } from "../utils/index.js"
3
+ import { effectQueue } from "./globals.js"
4
+ import { tick } from "./utils.js"
5
+ import type { Signal } from "./base.js"
6
+ import type { SignalValues } from "./types.js"
7
+
8
+ export type TrackingStackObservations = Map<string, Signal<unknown>>
9
+ export const tracking = {
10
+ enabled: true,
11
+ stack: new Array<TrackingStackObservations>(),
12
+ current: function (): TrackingStackObservations | undefined {
13
+ return this.stack[this.stack.length - 1]
14
+ },
15
+ }
16
+
17
+ type TrackedExecutionContext<T, Deps extends readonly Signal<unknown>[]> = {
18
+ id: string
19
+ subs: Map<string, Function>
20
+ fn: (...values: SignalValues<Deps>) => T
21
+ deps?: Deps
22
+ onDepChanged: () => void
23
+ }
24
+
25
+ /**
26
+ * Executes an effect function with dependency tracking enabled, and manages
27
+ * the effect's subscriptions.
28
+ * @param ctx - The execution context
29
+ * @returns The result of the effect function
30
+ */
31
+ export function executeWithTracking<T, Deps extends readonly Signal<unknown>[]>(
32
+ ctx: TrackedExecutionContext<T, Deps>
33
+ ): T {
34
+ const { id, subs, fn, deps = [], onDepChanged } = ctx
35
+ let observations: Map<string, Signal<unknown>> | undefined
36
+
37
+ effectQueue.delete(id)
38
+ const isServer = !!node.current && !sideEffectsEnabled()
39
+
40
+ if (!isServer) {
41
+ observations = new Map<string, Signal<unknown>>()
42
+ tracking.stack.push(observations)
43
+ }
44
+
45
+ const result = fn(...(deps.map((s) => s.value) as SignalValues<Deps>))
46
+
47
+ if (!isServer) {
48
+ for (const [id, unsub] of subs) {
49
+ if (observations!.has(id)) continue
50
+ unsub()
51
+ subs.delete(id)
52
+ }
53
+
54
+ const effect = () => {
55
+ if (!effectQueue.size) {
56
+ queueMicrotask(tick)
57
+ }
58
+ effectQueue.set(id, onDepChanged)
59
+ }
60
+
61
+ for (const [id, sig] of observations!) {
62
+ if (subs.has(id)) continue
63
+ const unsub = sig.subscribe(effect)
64
+ subs.set(id, unsub)
65
+ }
66
+ tracking.stack.pop()
67
+ }
68
+
69
+ return result
70
+ }
@@ -7,7 +7,7 @@ export type SignalSubscriber<T = unknown> = (value: T, prevValue?: T) => void
7
7
 
8
8
  export type SignalValues<T extends readonly Signal<unknown>[]> = {
9
9
  [I in keyof T]: T[I] extends Signal<infer V>
10
- ? V extends Kiru.StatefulPromise<infer P>
10
+ ? V extends Kiru.StatefulPromiseBase<infer P>
11
11
  ? P
12
12
  : V
13
13
  : never
@@ -1,13 +1,21 @@
1
1
  import { call } from "../utils/index.js"
2
2
  import { Signal } from "./base.js"
3
3
  import { effectQueue } from "./globals.js"
4
+ import { tracking } from "./tracking.js"
4
5
 
5
6
  export function unwrap<T>(value: T | Signal<T>, reactive = false): T {
6
7
  if (!Signal.isSignal(value)) return value
7
8
  return reactive ? value.value : value.peek()
8
9
  }
9
10
 
10
- export const tick = () => {
11
+ export function tick() {
11
12
  effectQueue.forEach(call)
12
13
  effectQueue.clear()
13
14
  }
15
+
16
+ export function untrack<T>(fn: () => T) {
17
+ tracking.enabled = false
18
+ const result = fn()
19
+ tracking.enabled = true
20
+ return result
21
+ }
package/src/ssr/client.ts CHANGED
@@ -1,9 +1,9 @@
1
- import type { AppContext, AppContextOptions } from "../appContext"
1
+ import type { AppHandle, AppHandleOptions } from "../appHandle"
2
2
  import { hydrationStack } from "../hydration.js"
3
3
  import { hydrationMode, renderMode } from "../globals.js"
4
4
  import { mount } from "../index.js"
5
5
 
6
- interface HydrationAppContextOptions extends AppContextOptions {
6
+ interface AppHandleHydrationOptions extends AppHandleOptions {
7
7
  /**
8
8
  * Configures the hydration mode
9
9
  * - "static": SSG
@@ -16,8 +16,8 @@ interface HydrationAppContextOptions extends AppContextOptions {
16
16
  export function hydrate(
17
17
  children: JSX.Element,
18
18
  container: HTMLElement,
19
- options?: HydrationAppContextOptions
20
- ): AppContext {
19
+ options?: AppHandleHydrationOptions
20
+ ): AppHandle {
21
21
  hydrationStack.clear()
22
22
 
23
23
  const prevRenderMode = renderMode.current
package/src/ssr/server.ts CHANGED
@@ -2,7 +2,7 @@ import { Readable } from "node:stream"
2
2
  import { Fragment } from "../element.js"
3
3
  import { renderMode } from "../globals.js"
4
4
  import { STREAMED_DATA_EVENT } from "../constants.js"
5
- import { headlessRender, HeadlessRenderContext } from "../recursiveRender.js"
5
+ import { headlessRender, HeadlessRenderContext } from "../headlessRender.js"
6
6
 
7
7
  const STREAMED_DATA_SETUP = `
8
8
  <script type="text/javascript">
@@ -26,7 +26,7 @@ export function renderToReadableStream(element: JSX.Element): {
26
26
  } {
27
27
  const stream = new Readable({ read() {} })
28
28
  const rootNode = Fragment({ children: element })
29
- const streamPromises = new Set<Kiru.StatefulPromise<unknown>>()
29
+ const streamPromises = new Set<Kiru.StatefulPromiseBase<unknown>>()
30
30
  const pendingWritePromises: Promise<void>[] = []
31
31
 
32
32
  let immediate = ""
@@ -0,0 +1,136 @@
1
+ import { $STREAM_DATA, STREAMED_DATA_EVENT } from "./constants.js"
2
+ import { hydrationMode, node, renderMode } from "./globals.js"
3
+ import { Signal, signal } from "./signals/base.js"
4
+ import { createVNodeId } from "./utils/vdom.js"
5
+ import { onCleanup } from "./hooks/onCleanup.js"
6
+
7
+ export interface StreamDataThrowValue {
8
+ [$STREAM_DATA]: {
9
+ fallback?: JSX.Element
10
+ data: Kiru.StatefulPromiseBase<unknown>[]
11
+ }
12
+ }
13
+
14
+ /**
15
+ * Returns true if the value is a {@link StreamDataThrowValue}
16
+ */
17
+ export function isStreamDataThrowValue(
18
+ value: unknown
19
+ ): value is StreamDataThrowValue {
20
+ return typeof value === "object" && !!value && $STREAM_DATA in value
21
+ }
22
+
23
+ /**
24
+ * Returns true if the value is a {@link Kiru.StatefulPromiseBase}
25
+ */
26
+ export function isStatefulPromise(
27
+ thing: unknown
28
+ ): thing is Kiru.StatefulPromiseBase<unknown> {
29
+ return thing instanceof Promise && "id" in thing && "state" in thing
30
+ }
31
+
32
+ const nodeToPromiseIndex = new WeakMap<Kiru.VNode, number>()
33
+
34
+ type StatefulPromise<T> = Kiru.StatefulPromiseBase<T> & {
35
+ isPending: Signal<boolean>
36
+ }
37
+
38
+ export function statefulPromise<T>(
39
+ callback: (signal: AbortSignal) => Promise<T>
40
+ ): StatefulPromise<T> {
41
+ const vNode = node.current!
42
+ if (!vNode) {
43
+ throw new Error("statefulPromise must be called inside a Kiru component")
44
+ }
45
+ const id = createVNodeId(vNode)
46
+ const isPending = signal(true)
47
+
48
+ isPending.value = true
49
+
50
+ const controller = new AbortController()
51
+ onCleanup(() => controller.abort())
52
+
53
+ const index = nodeToPromiseIndex.get(vNode) ?? 0
54
+ nodeToPromiseIndex.set(vNode, index + 1)
55
+
56
+ const promiseId = `${id}:data:${index}`
57
+
58
+ let promise: Promise<T>
59
+ if (renderMode.current === "string") {
60
+ // if we're rendering to a string, there's no need to fire the callback
61
+ promise = Promise.resolve() as Promise<T>
62
+ } else if (
63
+ renderMode.current === "hydrate" &&
64
+ hydrationMode.current === "dynamic"
65
+ ) {
66
+ // if we're hydrating and the hydration mode is not static,
67
+ // we need to resolve the promise from cache/event
68
+ promise = resolveDeferredPromise<T>(promiseId, controller.signal)
69
+ } else {
70
+ // dom / stream / (hydrate + static)
71
+ promise = callback(controller.signal)
72
+ }
73
+
74
+ const state: Kiru.PromiseState<T> = {
75
+ id: promiseId,
76
+ state: "pending",
77
+ }
78
+ const statefulPromise: Kiru.StatefulPromiseBase<T> = Object.assign(
79
+ promise,
80
+ state
81
+ )
82
+
83
+ statefulPromise
84
+ .then((value) => {
85
+ statefulPromise.state = "fulfilled"
86
+ statefulPromise.value = value
87
+ isPending.value = false
88
+ })
89
+ .catch((error) => {
90
+ statefulPromise.state = "rejected"
91
+ statefulPromise.error = error instanceof Error ? error : new Error(error)
92
+ })
93
+
94
+ return Object.assign(statefulPromise, { isPending })
95
+ }
96
+
97
+ interface DeferredPromiseEventDetail<T> {
98
+ id: string
99
+ data?: T
100
+ error?: string
101
+ }
102
+
103
+ function resolveDeferredPromise<T>(
104
+ id: string,
105
+ signal: AbortSignal
106
+ ): Promise<T> {
107
+ return new Promise<T>((resolve, reject) => {
108
+ const deferralCache: Map<string, { data?: T; error?: string }> = // @ts-ignore
109
+ (window[STREAMED_DATA_EVENT] ??= new Map())
110
+
111
+ const existing = deferralCache.get(id)
112
+ if (existing) {
113
+ const { data, error } = existing
114
+ deferralCache.delete(id)
115
+ if (error) return reject(error)
116
+ return resolve(data!)
117
+ }
118
+
119
+ const onDataEvent = (event: Event) => {
120
+ const { detail } = event as CustomEvent<DeferredPromiseEventDetail<T>>
121
+ if (detail.id === id) {
122
+ deferralCache.delete(id)
123
+ window.removeEventListener(STREAMED_DATA_EVENT, onDataEvent)
124
+ const { data, error } = detail
125
+ if (error) return reject(error)
126
+ resolve(data!)
127
+ }
128
+ }
129
+
130
+ window.addEventListener(STREAMED_DATA_EVENT, onDataEvent)
131
+ signal.addEventListener("abort", () => {
132
+ window.removeEventListener(STREAMED_DATA_EVENT, onDataEvent)
133
+ reject()
134
+ })
135
+ })
136
+ }
package/src/types.dom.ts CHANGED
@@ -153,8 +153,8 @@ type AllStyleRules = Omit<
153
153
  type StyleObject = Prettify<
154
154
  Partial<{
155
155
  [Key in keyof AllStyleRules & string]: Key extends NumericStyleKeys
156
- ? number | string
157
- : AllStyleRules[Key]
156
+ ? Signalable<number | string | undefined>
157
+ : Signalable<AllStyleRules[Key] | undefined>
158
158
  }>
159
159
  >
160
160
 
@@ -598,17 +598,13 @@ interface PopoverControlAttributes {
598
598
  popoverTargetAction?: "show" | "hide" | "toggle"
599
599
  }
600
600
 
601
- declare class DoNotUseBindWithPlainError extends Error {
602
- $brand: "DoNotUseBindWithPlainError"
603
- }
604
-
605
601
  type BindableProp<K extends string, V> =
606
602
  | ({
607
- [k in K]?: Signalable<V>
608
- } & { [k in `bind:${K}`]?: DoNotUseBindWithPlainError })
603
+ [k in K]?: Signalable<V | undefined>
604
+ } & { [k in `bind:${K}`]?: never })
609
605
  | ({
610
- [k in `bind:${K}`]?: Signal<V>
611
- } & { [k in K]?: DoNotUseBindWithPlainError })
606
+ [k in `bind:${K}`]?: Signal<V | undefined>
607
+ } & { [k in K]?: never })
612
608
 
613
609
  type MediaElementBindableProps = BindableProp<"volume", number> &
614
610
  BindableProp<"playbackRate", number> &
package/src/types.ts CHANGED
@@ -1,10 +1,5 @@
1
1
  import type { ReadonlySignal, Signal as SignalClass } from "./signals"
2
- import type {
3
- $CONTEXT,
4
- $CONTEXT_PROVIDER,
5
- $ERROR_BOUNDARY,
6
- $FRAGMENT,
7
- } from "./constants"
2
+ import type { $CONTEXT, $ERROR_BOUNDARY, $FRAGMENT } from "./constants"
8
3
  import type { KiruGlobalContext } from "./globalContext"
9
4
  import type {
10
5
  GlobalAttributes,
@@ -22,7 +17,7 @@ import type {
22
17
  Signalable,
23
18
  SomeDom,
24
19
  } from "./types.utils"
25
- import type { AppContext } from "./appContext"
20
+ import type { AppHandle } from "./appHandle"
26
21
 
27
22
  export type { AsyncTaskState, ElementProps, Prettify, Signalable, StyleObject }
28
23
 
@@ -32,24 +27,26 @@ type ElementProps<T extends keyof JSX.IntrinsicElements> =
32
27
  type SignalableHtmlElementAttributes<Tag extends keyof HtmlElementAttributes> =
33
28
  {
34
29
  [K in keyof HtmlElementAttributes[Tag]]: Signalable<
35
- HtmlElementAttributes[Tag][K]
30
+ HtmlElementAttributes[Tag][K] | undefined
36
31
  >
37
32
  } & (Tag extends keyof HtmlElementBindableProps
38
33
  ? HtmlElementBindableProps[Tag]
39
34
  : {})
40
35
  type SignalableSvgElementAttributes<Tag extends keyof SvgElementAttributes> = {
41
36
  [K in keyof SvgElementAttributes[Tag]]: Signalable<
42
- SvgElementAttributes[Tag][K]
37
+ SvgElementAttributes[Tag][K] | undefined
43
38
  >
44
39
  }
45
40
  type SignalableAriaProps = {
46
- [K in keyof ARIAMixin]?: Signalable<ARIAMixin[K]>
41
+ [K in keyof ARIAMixin]?: Signalable<ARIAMixin[K] | undefined>
47
42
  }
48
43
  type SignalableGlobalAttributes = {
49
- [K in keyof GlobalAttributes]: Signalable<GlobalAttributes[K]>
44
+ [K in keyof GlobalAttributes]: Signalable<GlobalAttributes[K] | undefined>
50
45
  }
51
46
  type SignalableSvgGlobalAttributes = {
52
- [K in keyof SvgGlobalAttributes]: Signalable<SvgGlobalAttributes[K]>
47
+ [K in keyof SvgGlobalAttributes]: Signalable<
48
+ SvgGlobalAttributes[K] | undefined
49
+ >
53
50
  }
54
51
 
55
52
  type ElementMap = {
@@ -58,10 +55,7 @@ type ElementMap = {
58
55
  SignalableAriaProps &
59
56
  Kiru.EventAttributes<HTMLTagToElement<Tag>> &
60
57
  JSX.ElementAttributes & {
61
- ref?:
62
- | Kiru.Ref<HTMLTagToElement<Tag> | null>
63
- | SignalClass<HTMLTagToElement<Tag> | null>
64
- | null
58
+ ref?: Kiru.Ref<Element | null> | SignalClass<Element | null> | null
65
59
  }
66
60
  } & {
67
61
  [Tag in keyof SvgElementAttributes]: SignalableSvgElementAttributes<Tag> &
@@ -70,10 +64,7 @@ type ElementMap = {
70
64
  SignalableAriaProps &
71
65
  Kiru.EventAttributes<SVGTagToElement<Tag>> &
72
66
  JSX.ElementAttributes & {
73
- ref?:
74
- | Kiru.Ref<SVGTagToElement<Tag> | null>
75
- | SignalClass<SVGTagToElement<Tag> | null>
76
- | null
67
+ ref?: Kiru.Ref<Element | null> | SignalClass<Element | null> | null
77
68
  }
78
69
  } & {
79
70
  [Tag in `${string}-${string}`]: Record<string, any>
@@ -108,6 +99,7 @@ declare global {
108
99
  | Kiru.Element
109
100
  | PrimitiveChild
110
101
  | Kiru.Signal<PrimitiveChild>
102
+ | Kiru.FC<any>
111
103
 
112
104
  interface ElementAttributes {
113
105
  key?: JSX.ElementKey
@@ -121,42 +113,25 @@ declare global {
121
113
  namespace Kiru {
122
114
  interface CustomEvents {}
123
115
 
124
- interface ProviderProps<T> {
116
+ interface ContextProps<T> {
125
117
  value: T
126
- children?: JSX.Children | ((value: T) => JSX.Element)
118
+ children?: JSX.Children
127
119
  }
128
- interface Context<T> {
129
- [$CONTEXT]: true
130
- Provider: (({ value, children }: ProviderProps<T>) => JSX.Element) & {
131
- displayName?: string
132
- }
133
- default: () => T
134
- /** Used to display the name of the context in devtools */
135
- displayName?: string
120
+
121
+ interface Context<T> extends Kiru.FC<ContextProps<T>> {
122
+ [$CONTEXT]: () => T
136
123
  }
137
124
 
138
- interface FC<T = {}> {
139
- (props: FCProps<T>): JSX.Element
125
+ export interface FC<T = {}> {
126
+ (props: T):
127
+ | Exclude<JSX.Element, Kiru.FC<any>>
128
+ | ((props: T) => JSX.Element)
140
129
  /** Used to display the name of the component in devtools */
141
130
  displayName?: string
142
131
  }
143
132
 
144
- type FCProps<T = {}> = T & { children?: JSX.Children }
145
133
  type InferProps<T> = T extends Kiru.FC<infer P> ? P : never
146
134
 
147
- interface HookDevtoolsProvisions<T extends Record<string, any>> {
148
- get: () => T
149
- set?: (value: T) => void
150
- }
151
- type Hook<T> = T & {
152
- cleanup?: () => void
153
- name?: string
154
- dev?: {
155
- /** Used to perform invalidation during HMR when the hook's arguments have changed */
156
- initialArgs?: any
157
- devtools?: HookDevtoolsProvisions<any>
158
- }
159
- }
160
135
  interface RefObject<T> {
161
136
  current: T
162
137
  }
@@ -173,7 +148,7 @@ declare global {
173
148
  error?: Error
174
149
  }
175
150
 
176
- interface StatefulPromise<T> extends Promise<T>, PromiseState<T> {}
151
+ interface StatefulPromiseBase<T> extends Promise<T>, PromiseState<T> {}
177
152
 
178
153
  type RenderMode = "dom" | "hydrate" | "string" | "stream"
179
154
 
@@ -183,11 +158,15 @@ declare global {
183
158
 
184
159
  type ExoticSymbol =
185
160
  | typeof $FRAGMENT
186
- | typeof $CONTEXT_PROVIDER
161
+ | typeof $CONTEXT
187
162
  | typeof $ERROR_BOUNDARY
188
163
 
189
164
  interface Element {
190
- type: Function | ExoticSymbol | "#text" | (string & {})
165
+ type:
166
+ | (Function & { displayName?: string })
167
+ | ExoticSymbol
168
+ | "#text"
169
+ | (string & {})
191
170
  key: JSX.ElementKey | null
192
171
  props: {
193
172
  [key: string]: any
@@ -196,8 +175,10 @@ declare global {
196
175
  }
197
176
  }
198
177
 
178
+ type LifecycleHookCallback = () => (() => void) | void
179
+
199
180
  interface VNode extends Element {
200
- app?: AppContext
181
+ app?: AppHandle
201
182
  dom?: SomeDom
202
183
  index: number
203
184
  depth: number
@@ -207,22 +188,32 @@ declare global {
207
188
  sibling: VNode | null
208
189
  prev: VNodeSnapshot | null
209
190
  deletions: VNode[] | null
210
- hooks?: Hook<unknown>[]
211
191
  subs?: Set<Function>
212
192
  cleanups?: Record<string, Function>
213
- effects?: Array<Function>
214
- immediateEffects?: Array<Function>
215
- // dev-mode only
216
- hookSig?: string[]
193
+
194
+ hooks?: {
195
+ pre: LifecycleHookCallback[]
196
+ preCleanups: (() => void)[]
197
+ post: LifecycleHookCallback[]
198
+ postCleanups: (() => void)[]
199
+ }
200
+ /** Run before each render with current props to sync prop-derived signals */
201
+ propSyncs?: ((props: VNode["props"]) => void)[]
202
+ render?: (props: VNode["props"]) => unknown
217
203
  }
218
- }
219
- interface VNodeSnapshot {
220
- props: Kiru.VNode["props"]
221
- key: Kiru.VNode["key"]
222
- index: number
204
+ interface VNodeSnapshot {
205
+ props: Kiru.VNode["props"]
206
+ key: Kiru.VNode["key"]
207
+ index: number
208
+ }
209
+
210
+ type ContainerElement = HTMLElement | ShadowRoot
223
211
  }
224
212
 
225
213
  interface Element {
226
214
  __kiruNode?: Kiru.VNode
227
215
  }
216
+ interface ShadowRoot {
217
+ __kiruNode?: Kiru.VNode
218
+ }
228
219
  }
@@ -1,4 +1,4 @@
1
- import type { $CONTEXT_PROVIDER, $ERROR_BOUNDARY, $FRAGMENT } from "./constants"
1
+ import type { $CONTEXT, $ERROR_BOUNDARY, $FRAGMENT } from "./constants"
2
2
  import type { Signal } from "./signals"
3
3
  import type { ErrorBoundaryProps } from "./components/errorBoundary"
4
4
 
@@ -20,12 +20,11 @@ export interface DomVNode extends Kiru.VNode {
20
20
  type: "#text" | (string & {})
21
21
  }
22
22
 
23
- export interface ContextProviderNode<T> extends Kiru.VNode {
24
- type: typeof $CONTEXT_PROVIDER
23
+ export interface ContextNode<T> extends Kiru.VNode {
24
+ type: typeof $CONTEXT
25
25
  props: Kiru.VNode["props"] & {
26
26
  value: T
27
27
  ctx: Kiru.Context<T>
28
- dependents: Set<Kiru.VNode>
29
28
  }
30
29
  }
31
30
 
@@ -84,8 +84,10 @@ function propToHtmlAttr(key: string): string {
84
84
  function styleObjectToString(obj: Partial<CSSStyleDeclaration>): string {
85
85
  let cssString = ""
86
86
  for (const key in obj) {
87
+ const val = unwrap((obj as Record<string, unknown>)[key])
88
+ if (val === null || val === undefined) continue
87
89
  const cssKey = key.replace(REGEX_ALPHA_UPPER, "-$&").toLowerCase()
88
- cssString += `${cssKey}:${obj[key]};`
90
+ cssString += `${cssKey}:${val};`
89
91
  }
90
92
  return cssString
91
93
  }