@zaly/tui 0.0.12 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/assets/schemas/shiki-language.schema.json +352 -0
  2. package/assets/schemas/shiki-theme.schema.json +71 -0
  3. package/assets/schemas/theme.schema.json +226 -1046
  4. package/assets/themes/andromeeda.json +97 -0
  5. package/assets/themes/ayu-dark.json +31 -25
  6. package/assets/themes/ayu-light.json +106 -0
  7. package/assets/themes/ayu-mirage.json +106 -0
  8. package/assets/themes/catppuccin-frappe.json +43 -40
  9. package/assets/themes/catppuccin-latte.json +43 -40
  10. package/assets/themes/catppuccin-macchiato.json +43 -40
  11. package/assets/themes/catppuccin-mocha.json +43 -40
  12. package/assets/themes/dark-plus.json +99 -0
  13. package/assets/themes/dracula.json +47 -47
  14. package/assets/themes/everforest-dark.json +28 -26
  15. package/assets/themes/everforest-light.json +28 -26
  16. package/assets/themes/github-dark-default.json +107 -0
  17. package/assets/themes/github-dark-dimmed.json +107 -0
  18. package/assets/themes/github-light-default.json +107 -0
  19. package/assets/themes/gruvbox-dark-hard.json +98 -0
  20. package/assets/themes/gruvbox-dark-medium.json +34 -29
  21. package/assets/themes/gruvbox-light-medium.json +98 -0
  22. package/assets/themes/horizon-bright.json +101 -0
  23. package/assets/themes/horizon.json +101 -0
  24. package/assets/themes/iterm2/LICENSE +25 -0
  25. package/assets/themes/iterm2/README.md +28 -0
  26. package/assets/themes/iterm2/catppuccin-latte.json +140 -0
  27. package/assets/themes/iterm2/catppuccin-mocha.json +140 -0
  28. package/assets/themes/iterm2/github-dark.json +140 -0
  29. package/assets/themes/iterm2/github.json +140 -0
  30. package/assets/themes/iterm2/gruvbox-dark.json +140 -0
  31. package/assets/themes/iterm2/gruvbox-light.json +140 -0
  32. package/assets/themes/iterm2/nord.json +140 -0
  33. package/assets/themes/iterm2/tokyonight-day.json +140 -0
  34. package/assets/themes/iterm2/tokyonight-moon.json +140 -0
  35. package/assets/themes/kanagawa-dragon.json +55 -49
  36. package/assets/themes/kanagawa-lotus.json +105 -0
  37. package/assets/themes/kanagawa-wave.json +56 -50
  38. package/assets/themes/light-plus.json +99 -0
  39. package/assets/themes/material-theme-lighter.json +102 -0
  40. package/assets/themes/material-theme-palenight.json +52 -45
  41. package/assets/themes/material-theme.json +102 -0
  42. package/assets/themes/min-dark.json +69 -14
  43. package/assets/themes/min-light.json +68 -17
  44. package/assets/themes/monokai.json +54 -47
  45. package/assets/themes/night-owl-light.json +105 -0
  46. package/assets/themes/night-owl.json +57 -49
  47. package/assets/themes/nord.json +53 -39
  48. package/assets/themes/one-dark-pro.json +46 -38
  49. package/assets/themes/one-light.json +52 -41
  50. package/assets/themes/poimandres.json +51 -49
  51. package/assets/themes/rose-pine-dawn.json +99 -0
  52. package/assets/themes/rose-pine-moon.json +99 -0
  53. package/assets/themes/rose-pine.json +50 -33
  54. package/assets/themes/solarized-dark.json +38 -31
  55. package/assets/themes/solarized-light.json +40 -33
  56. package/assets/themes/synthwave-84.json +47 -30
  57. package/assets/themes/tokyonight-day.json +3 -3
  58. package/assets/themes/tokyonight-moon.json +3 -2
  59. package/assets/themes/tokyonight-night.json +3 -2
  60. package/assets/themes/tokyonight-storm.json +3 -2
  61. package/assets/themes/vesper.json +50 -42
  62. package/assets/themes/vitesse-black.json +103 -0
  63. package/assets/themes/vitesse-dark.json +26 -30
  64. package/assets/themes/vitesse-light.json +26 -30
  65. package/dist/{actions-DEIKF2ts.mjs → actions-AY6avfEV.mjs} +2 -3
  66. package/dist/{actions-DEIKF2ts.mjs.map → actions-AY6avfEV.mjs.map} +1 -1
  67. package/dist/{actions-Dc4D4uSf.d.mts → actions-B0yyZ-Ww.d.mts} +4 -6
  68. package/dist/actions-B0yyZ-Ww.d.mts.map +1 -0
  69. package/dist/{ansi-DZlXaItJ.mjs → ansi-CxgRPLA2.mjs} +4 -33
  70. package/dist/ansi-CxgRPLA2.mjs.map +1 -0
  71. package/dist/ansi.d.mts +1 -3
  72. package/dist/ansi.d.mts.map +1 -1
  73. package/dist/ansi.mjs +1 -1
  74. package/dist/{autocomplete-StW1QJZJ.d.mts → autocomplete-wgceuhLr.d.mts} +5 -7
  75. package/dist/autocomplete-wgceuhLr.d.mts.map +1 -0
  76. package/dist/{box-BkP4MF82.mjs → box-DToDoXlU.mjs} +8 -10
  77. package/dist/{box-BkP4MF82.mjs.map → box-DToDoXlU.mjs.map} +1 -1
  78. package/dist/builder-BdYlK1Ew.mjs +195 -0
  79. package/dist/builder-BdYlK1Ew.mjs.map +1 -0
  80. package/dist/{callbacks-BwWTCqPJ.mjs → callbacks-DW8XKYKy.mjs} +9 -13
  81. package/dist/{callbacks-BwWTCqPJ.mjs.map → callbacks-DW8XKYKy.mjs.map} +1 -1
  82. package/dist/{client-C2GXKfJ1.mjs → client-BWm6dNZF.mjs} +9 -6
  83. package/dist/client-BWm6dNZF.mjs.map +1 -0
  84. package/dist/client-C69qWhMG.mjs +1 -0
  85. package/dist/{clipboard-CNPBTX7j.mjs → clipboard-UEoX9sup.mjs} +2 -3
  86. package/dist/{clipboard-CNPBTX7j.mjs.map → clipboard-UEoX9sup.mjs.map} +1 -1
  87. package/dist/clipboard.d.mts +0 -2
  88. package/dist/clipboard.d.mts.map +1 -1
  89. package/dist/clipboard.mjs +1 -1
  90. package/dist/color-Cr1VoL49.mjs +36 -0
  91. package/dist/color-Cr1VoL49.mjs.map +1 -0
  92. package/dist/ctx-CYEzzH-7.mjs +1 -0
  93. package/dist/{ctx-B7BmPUCD.mjs → ctx-DBeFcZt6.mjs} +4 -5
  94. package/dist/{ctx-B7BmPUCD.mjs.map → ctx-DBeFcZt6.mjs.map} +1 -1
  95. package/dist/{divider-TSx9NhI_.mjs → divider-qEj5prKE.mjs} +3 -4
  96. package/dist/{divider-TSx9NhI_.mjs.map → divider-qEj5prKE.mjs.map} +1 -1
  97. package/dist/{files-BvThQpOf.mjs → files-C3ZnFpvq.mjs} +3 -4
  98. package/dist/{files-BvThQpOf.mjs.map → files-C3ZnFpvq.mjs.map} +1 -1
  99. package/dist/{files-7DUYSeNc.d.mts → files-CdiDnwA_.d.mts} +3 -5
  100. package/dist/files-CdiDnwA_.d.mts.map +1 -0
  101. package/dist/{flex-Bguo-fUe.mjs → flex-CYp4etqn.mjs} +3 -4
  102. package/dist/{flex-Bguo-fUe.mjs.map → flex-CYp4etqn.mjs.map} +1 -1
  103. package/dist/{github-Cy2hfWJ7.mjs → github-CLveT9mq.mjs} +2 -3
  104. package/dist/{github-Cy2hfWJ7.mjs.map → github-CLveT9mq.mjs.map} +1 -1
  105. package/dist/{github-C1KfXk98.d.mts → github-DC0XemKa.d.mts} +3 -5
  106. package/dist/github-DC0XemKa.d.mts.map +1 -0
  107. package/dist/{image-VaT7AN-S.d.mts → image-DdRDv7q6.d.mts} +2 -4
  108. package/dist/image-DdRDv7q6.d.mts.map +1 -0
  109. package/dist/image-M--Bw4bs.mjs +177 -0
  110. package/dist/image-M--Bw4bs.mjs.map +1 -0
  111. package/dist/image.d.mts +1 -3
  112. package/dist/image.d.mts.map +1 -1
  113. package/dist/image.mjs +1 -1
  114. package/dist/index.d.mts +11 -14
  115. package/dist/index.d.mts.map +1 -1
  116. package/dist/index.mjs +12 -14
  117. package/dist/index.mjs.map +1 -1
  118. package/dist/{input-BGTTujDN.mjs → input-BkE4EpBw.mjs} +6 -7
  119. package/dist/{input-BGTTujDN.mjs.map → input-BkE4EpBw.mjs.map} +1 -1
  120. package/dist/{input-BAYux7qo.d.mts → input-C3kfYoEJ.d.mts} +3 -5
  121. package/dist/input-C3kfYoEJ.d.mts.map +1 -0
  122. package/dist/{inspect-jG_W4njH.mjs → inspect-Cli1beu8.mjs} +3 -4
  123. package/dist/{inspect-jG_W4njH.mjs.map → inspect-Cli1beu8.mjs.map} +1 -1
  124. package/dist/{inspect-CfNydMgO.d.mts → inspect-hSl3U2BD.d.mts} +2 -6
  125. package/dist/inspect-hSl3U2BD.d.mts.map +1 -0
  126. package/dist/kitty-0sJ8axU_.mjs +1 -0
  127. package/dist/{kitty-JbCJC0iQ.mjs → kitty-BH_eK6lz.mjs} +2 -3
  128. package/dist/{kitty-JbCJC0iQ.mjs.map → kitty-BH_eK6lz.mjs.map} +1 -1
  129. package/dist/{log-ByKlM4iI.mjs → log-96b1_J6G.mjs} +6 -7
  130. package/dist/{log-ByKlM4iI.mjs.map → log-96b1_J6G.mjs.map} +1 -1
  131. package/dist/{logger-DSQb0sLP.mjs → logger-DwfXp8LF.mjs} +5 -6
  132. package/dist/{logger-DSQb0sLP.mjs.map → logger-DwfXp8LF.mjs.map} +1 -1
  133. package/dist/{markdown-CwRmWuU6.mjs → markdown-CgRZBhIX.mjs} +12 -12
  134. package/dist/markdown-CgRZBhIX.mjs.map +1 -0
  135. package/dist/markdown.d.mts +2 -4
  136. package/dist/markdown.d.mts.map +1 -1
  137. package/dist/markdown.mjs +1 -1
  138. package/dist/math-Dk8hxbmz.mjs +1 -0
  139. package/dist/math-VPuwFCid.mjs +205 -0
  140. package/dist/math-VPuwFCid.mjs.map +1 -0
  141. package/dist/md.bun.d.mts +1 -3
  142. package/dist/md.bun.d.mts.map +1 -1
  143. package/dist/md.bun.mjs +2 -3
  144. package/dist/md.node.d.mts +1 -3
  145. package/dist/md.node.d.mts.map +1 -1
  146. package/dist/md.node.mjs +2 -3
  147. package/dist/{node-BZ7f6HzU.mjs → node-CXNobGaP.mjs} +3 -4
  148. package/dist/{node-BZ7f6HzU.mjs.map → node-CXNobGaP.mjs.map} +1 -1
  149. package/dist/oklch-Boh4YHEc.mjs +98 -0
  150. package/dist/oklch-Boh4YHEc.mjs.map +1 -0
  151. package/dist/{overlay-BnvOKtGT.mjs → overlay-CevDWgSF.mjs} +3 -4
  152. package/dist/{overlay-BnvOKtGT.mjs.map → overlay-CevDWgSF.mjs.map} +1 -1
  153. package/dist/{picker-Dh5IUrTk.mjs → picker-D9WrE3zF.mjs} +11 -16
  154. package/dist/{picker-Dh5IUrTk.mjs.map → picker-D9WrE3zF.mjs.map} +1 -1
  155. package/dist/{picker-DQs_IW77.d.mts → picker-DsB6--GN.d.mts} +6 -8
  156. package/dist/picker-DsB6--GN.d.mts.map +1 -0
  157. package/dist/{queries-B_lOwEiE.mjs → queries-BIniKnLL.mjs} +68 -7
  158. package/dist/queries-BIniKnLL.mjs.map +1 -0
  159. package/dist/{queries-BDX8mcl5.d.mts → queries-Dmd3IjSd.d.mts} +19 -52
  160. package/dist/queries-Dmd3IjSd.d.mts.map +1 -0
  161. package/dist/{reactive-f7NpAi69.mjs → reactive-DkP75TPk.mjs} +2 -3
  162. package/dist/{reactive-f7NpAi69.mjs.map → reactive-DkP75TPk.mjs.map} +1 -1
  163. package/dist/{registry-D-suU3g0.mjs → registry-CQU0VwpM.mjs} +205 -65
  164. package/dist/registry-CQU0VwpM.mjs.map +1 -0
  165. package/dist/{render-DEIUNLkh.mjs → render-Bp2N2i6J.mjs} +4 -5
  166. package/dist/{render-DEIUNLkh.mjs.map → render-Bp2N2i6J.mjs.map} +1 -1
  167. package/dist/{renderer-zDNlAovy.mjs → renderer-B9sAMA10.mjs} +123 -40
  168. package/dist/renderer-B9sAMA10.mjs.map +1 -0
  169. package/dist/{renderer-MQue4Da5.mjs → renderer-BYl2pbdx.mjs} +9 -9
  170. package/dist/renderer-BYl2pbdx.mjs.map +1 -0
  171. package/dist/renderer-Ctz0hv5o.mjs +1 -0
  172. package/dist/{search-FvGnswRl.d.mts → search-DsHzamic.d.mts} +1 -9
  173. package/dist/search-DsHzamic.d.mts.map +1 -0
  174. package/dist/{select-J2KtwxyK.d.mts → select-BZCFXdjp.d.mts} +3 -5
  175. package/dist/select-BZCFXdjp.d.mts.map +1 -0
  176. package/dist/{select-m7NE6Rwa.mjs → select-CUmAFKJh.mjs} +5 -6
  177. package/dist/{select-m7NE6Rwa.mjs.map → select-CUmAFKJh.mjs.map} +1 -1
  178. package/dist/services/logger.d.mts +1 -1
  179. package/dist/services/logger.mjs +1 -1
  180. package/dist/services/notifier.d.mts +1 -3
  181. package/dist/services/notifier.d.mts.map +1 -1
  182. package/dist/services/notifier.mjs +3 -4
  183. package/dist/services/picker.d.mts +5 -7
  184. package/dist/services/picker.d.mts.map +1 -1
  185. package/dist/services/picker.mjs +8 -9
  186. package/dist/services/prompt.d.mts +4 -6
  187. package/dist/services/prompt.d.mts.map +1 -1
  188. package/dist/services/prompt.mjs +7 -8
  189. package/dist/shiki/server.mjs +40 -19
  190. package/dist/shiki/server.mjs.map +1 -1
  191. package/dist/shiki-BAf9PdIc.mjs +19 -0
  192. package/dist/shiki-BAf9PdIc.mjs.map +1 -0
  193. package/dist/shiki-DUUAIE6f.mjs +632 -0
  194. package/dist/shiki-DUUAIE6f.mjs.map +1 -0
  195. package/dist/{show-DR2x1YFc.mjs → show-D5XNXgZf.mjs} +4 -5
  196. package/dist/{show-DR2x1YFc.mjs.map → show-D5XNXgZf.mjs.map} +1 -1
  197. package/dist/{size-D8JogYLy.mjs → size-BHRJuRk9.mjs} +2 -3
  198. package/dist/{size-D8JogYLy.mjs.map → size-BHRJuRk9.mjs.map} +1 -1
  199. package/dist/style-Cw_EuszU.mjs +108 -0
  200. package/dist/style-Cw_EuszU.mjs.map +1 -0
  201. package/dist/style.d.mts +4 -5
  202. package/dist/style.d.mts.map +1 -1
  203. package/dist/style.mjs +4 -4
  204. package/dist/{text-CkQ7Irmt.mjs → text-4arC3odI.mjs} +3 -4
  205. package/dist/{text-CkQ7Irmt.mjs.map → text-4arC3odI.mjs.map} +1 -1
  206. package/dist/{text-XvPfweeg.mjs → text-BArwVVkg.mjs} +5 -6
  207. package/dist/{text-XvPfweeg.mjs.map → text-BArwVVkg.mjs.map} +1 -1
  208. package/dist/{text-CCYs9RB2.d.mts → text-DdkJXgoC.d.mts} +3 -5
  209. package/dist/text-DdkJXgoC.d.mts.map +1 -0
  210. package/dist/text.d.mts +1 -1
  211. package/dist/text.mjs +1 -1
  212. package/dist/theme-B8hb1lPU.mjs +60 -0
  213. package/dist/theme-B8hb1lPU.mjs.map +1 -0
  214. package/dist/theme-BeSaXGNY.mjs +1792 -0
  215. package/dist/theme-BeSaXGNY.mjs.map +1 -0
  216. package/dist/themes.d.mts +211 -77
  217. package/dist/themes.d.mts.map +1 -1
  218. package/dist/themes.mjs +1 -1
  219. package/dist/{tree-DJl5W_B7.d.mts → tree-Berzv8Rz.d.mts} +3 -5
  220. package/dist/tree-Berzv8Rz.d.mts.map +1 -0
  221. package/dist/{tree-Bo1afYhe.mjs → tree-D6NvMQx8.mjs} +5 -6
  222. package/dist/{tree-Bo1afYhe.mjs.map → tree-D6NvMQx8.mjs.map} +1 -1
  223. package/dist/{types-D2EYlzmK.d.mts → types-ByMHEdCF.d.mts} +133 -131
  224. package/dist/types-ByMHEdCF.d.mts.map +1 -0
  225. package/dist/{types-D3jk1rtk.d.mts → types-CUVUJPz6.d.mts} +1 -3
  226. package/dist/types-CUVUJPz6.d.mts.map +1 -0
  227. package/dist/{utils-3M4D_AXZ.mjs → utils-DHXAegVW.mjs} +1 -2
  228. package/dist/{utils-3M4D_AXZ.mjs.map → utils-DHXAegVW.mjs.map} +1 -1
  229. package/dist/{widget-BkMwhY2p.mjs → widget-sFveyrZE.mjs} +3 -4
  230. package/dist/{widget-BkMwhY2p.mjs.map → widget-sFveyrZE.mjs.map} +1 -1
  231. package/dist/{widget-DPqBbB57.d.mts → widget-sPJaKVU2.d.mts} +2 -4
  232. package/dist/widget-sPJaKVU2.d.mts.map +1 -0
  233. package/dist/widgets/autocomplete.d.mts +1 -1
  234. package/dist/widgets/autocomplete.mjs +5 -6
  235. package/dist/widgets/box.d.mts +1 -1
  236. package/dist/widgets/box.mjs +1 -1
  237. package/dist/widgets/code.d.mts +4 -4
  238. package/dist/widgets/code.d.mts.map +1 -1
  239. package/dist/widgets/code.mjs +12 -12
  240. package/dist/widgets/code.mjs.map +1 -1
  241. package/dist/widgets/completions/actions.d.mts +1 -1
  242. package/dist/widgets/completions/actions.mjs +1 -1
  243. package/dist/widgets/completions/files.d.mts +1 -1
  244. package/dist/widgets/completions/files.mjs +1 -1
  245. package/dist/widgets/completions/github.d.mts +1 -1
  246. package/dist/widgets/completions/github.mjs +1 -1
  247. package/dist/widgets/completions/index.d.mts +3 -3
  248. package/dist/widgets/completions/index.mjs +3 -3
  249. package/dist/widgets/diff.d.mts +2 -4
  250. package/dist/widgets/diff.d.mts.map +1 -1
  251. package/dist/widgets/diff.mjs +38 -16
  252. package/dist/widgets/diff.mjs.map +1 -1
  253. package/dist/widgets/divider.d.mts +2 -4
  254. package/dist/widgets/divider.d.mts.map +1 -1
  255. package/dist/widgets/divider.mjs +1 -1
  256. package/dist/widgets/image.d.mts +1 -1
  257. package/dist/widgets/image.mjs +8 -9
  258. package/dist/widgets/image.mjs.map +1 -1
  259. package/dist/widgets/input.d.mts +1 -1
  260. package/dist/widgets/input.mjs +1 -1
  261. package/dist/widgets/log.d.mts +1 -1
  262. package/dist/widgets/log.mjs +1 -1
  263. package/dist/widgets/markdown.d.mts +5 -7
  264. package/dist/widgets/markdown.d.mts.map +1 -1
  265. package/dist/widgets/markdown.mjs +1 -1
  266. package/dist/widgets/overlay.d.mts +1 -1
  267. package/dist/widgets/overlay.mjs +1 -1
  268. package/dist/widgets/picker.d.mts +1 -1
  269. package/dist/widgets/picker.mjs +1 -1
  270. package/dist/widgets/progress.d.mts +2 -4
  271. package/dist/widgets/progress.d.mts.map +1 -1
  272. package/dist/widgets/progress.mjs +4 -5
  273. package/dist/widgets/select.d.mts +1 -1
  274. package/dist/widgets/select.mjs +1 -1
  275. package/dist/widgets/show.d.mts +1 -3
  276. package/dist/widgets/show.d.mts.map +1 -1
  277. package/dist/widgets/show.mjs +1 -1
  278. package/dist/widgets/spinner.d.mts +2 -4
  279. package/dist/widgets/spinner.d.mts.map +1 -1
  280. package/dist/widgets/spinner.mjs +3 -4
  281. package/dist/widgets/text.d.mts +1 -1
  282. package/dist/widgets/text.mjs +1 -1
  283. package/dist/widgets/tree.d.mts +1 -1
  284. package/dist/widgets/tree.mjs +1 -1
  285. package/dist/widgets/widget.d.mts +1 -1
  286. package/dist/widgets/widget.mjs +1 -1
  287. package/dist/{worker-T6SdPzUH.mjs → worker-CtEowucz.mjs} +2 -3
  288. package/dist/{worker-T6SdPzUH.mjs.map → worker-CtEowucz.mjs.map} +1 -1
  289. package/dist/worker-Mqi380Et.mjs +1 -0
  290. package/package.json +5 -7
  291. package/assets/themes/dracula-soft.json +0 -100
  292. package/assets/themes/github-dark.json +0 -104
  293. package/assets/themes/github-light.json +0 -104
  294. package/dist/actions-Dc4D4uSf.d.mts.map +0 -1
  295. package/dist/ansi-DZlXaItJ.mjs.map +0 -1
  296. package/dist/autocomplete-StW1QJZJ.d.mts.map +0 -1
  297. package/dist/builder-1z5ewEWK.mjs +0 -386
  298. package/dist/builder-1z5ewEWK.mjs.map +0 -1
  299. package/dist/client-C2GXKfJ1.mjs.map +0 -1
  300. package/dist/client-bzdHIDL2.mjs +0 -1
  301. package/dist/ctx-D_JgJ8Eo.mjs +0 -1
  302. package/dist/files-7DUYSeNc.d.mts.map +0 -1
  303. package/dist/github-C1KfXk98.d.mts.map +0 -1
  304. package/dist/image-Cm5T-uw-.mjs +0 -108
  305. package/dist/image-Cm5T-uw-.mjs.map +0 -1
  306. package/dist/image-VaT7AN-S.d.mts.map +0 -1
  307. package/dist/input-BAYux7qo.d.mts.map +0 -1
  308. package/dist/inspect-CfNydMgO.d.mts.map +0 -1
  309. package/dist/markdown-CwRmWuU6.mjs.map +0 -1
  310. package/dist/picker-DQs_IW77.d.mts.map +0 -1
  311. package/dist/queries-BDX8mcl5.d.mts.map +0 -1
  312. package/dist/queries-B_lOwEiE.mjs.map +0 -1
  313. package/dist/registry-D-suU3g0.mjs.map +0 -1
  314. package/dist/renderer-DhqbEVVR.mjs +0 -1
  315. package/dist/renderer-MQue4Da5.mjs.map +0 -1
  316. package/dist/renderer-zDNlAovy.mjs.map +0 -1
  317. package/dist/search-FvGnswRl.d.mts.map +0 -1
  318. package/dist/select-J2KtwxyK.d.mts.map +0 -1
  319. package/dist/shiki--ASSYv4_.mjs +0 -12
  320. package/dist/shiki--ASSYv4_.mjs.map +0 -1
  321. package/dist/shiki-D7l5--zz.mjs +0 -432
  322. package/dist/shiki-D7l5--zz.mjs.map +0 -1
  323. package/dist/text-CCYs9RB2.d.mts.map +0 -1
  324. package/dist/theme.config-B3Yx--C2.mjs +0 -855
  325. package/dist/theme.config-B3Yx--C2.mjs.map +0 -1
  326. package/dist/tree-DJl5W_B7.d.mts.map +0 -1
  327. package/dist/types-D2EYlzmK.d.mts.map +0 -1
  328. package/dist/types-D3jk1rtk.d.mts.map +0 -1
  329. package/dist/widget-DPqBbB57.d.mts.map +0 -1
  330. package/dist/worker-C01jK2Ip.mjs +0 -1
@@ -1,9 +1,8 @@
1
- import { c as Color, f as Style, o as AnyStyle, t as Theme } from "./types-D2EYlzmK.mjs";
2
- import { a as StyleBuilder, t as InspectOpts } from "./inspect-CfNydMgO.mjs";
1
+ import { c as HexColor, f as Theme, i as AnyStyle, o as Color, u as Style, x as ShikiSelection } from "./types-ByMHEdCF.mjs";
2
+ import { a as StyleBuilder, t as InspectOpts } from "./inspect-hSl3U2BD.mjs";
3
3
  import { Emitter, MaybePromise } from "@zaly/shared";
4
4
  import { LogEntry, LogLevel, LogReporter, Logger, TryResult } from "@zaly/shared/logger";
5
5
  import { ArgsOpts, ArgsResult } from "@zaly/shared/args";
6
- //#region src/input/keys.d.ts
7
6
  /**
8
7
  * Keyboard event shape + pattern-based matcher.
9
8
  *
@@ -76,8 +75,6 @@ declare function canonical(patternOrEvent: string | KeyEvent): KeyPattern;
76
75
  * (no ctrl/alt/etc.).
77
76
  */
78
77
  declare function keyMatches(ev: KeyEvent, pattern: string | readonly string[]): boolean;
79
- //#endregion
80
- //#region src/input/decoder.d.ts
81
78
  /**
82
79
  * Decoder — bytes (as a string, after the caller UTF-8 decodes them) in,
83
80
  * structured `InputEvent`s out. Holds partial state across `feed()` calls
@@ -126,8 +123,6 @@ type InputEvent = {
126
123
  type: "focus";
127
124
  gained: boolean;
128
125
  } | TerminalResponseEvent | MouseEvent;
129
- //#endregion
130
- //#region src/input/actions.d.ts
131
126
  /**
132
127
  * Context handed to every action handler. Whether the action was
133
128
  * fired by a key, programmatic dispatch, command palette, or a plugin,
@@ -276,8 +271,6 @@ declare class Actions extends Emitter<ActionEvents> {
276
271
  keys: string[];
277
272
  })[];
278
273
  }
279
- //#endregion
280
- //#region src/layout/size.d.ts
281
274
  /** Percentage string like `'50%'`, resolved against the parent's content axis. */
282
275
  type Pct = `${number}%`;
283
276
  /**
@@ -290,8 +283,6 @@ type Pct = `${number}%`;
290
283
  * with `'fill'` — `fill` grows, `fit` shrinks.
291
284
  */
292
285
  type Size = number | Pct | "fill" | "fit";
293
- //#endregion
294
- //#region src/core/reactive.d.ts
295
286
  /** Run `fn` outside any tracking scope. Signal reads inside don't
296
287
  * subscribe the surrounding render, and async work started inside
297
288
  * (timers, promises, intervals) doesn't capture the current ctx —
@@ -749,8 +740,6 @@ interface Ref<T> {
749
740
  declare function createRef<T>(value?: T, opts?: {
750
741
  onSet?: (value: T, prev: T | undefined) => void | (() => void);
751
742
  }): Ref<T>;
752
- //#endregion
753
- //#region src/core/state.d.ts
754
743
  /**
755
744
  * Fields every Node reads off its state. Widget state types should
756
745
  * extend this (directly or transitively via `Style`, which extends
@@ -806,8 +795,6 @@ interface Layout {
806
795
  width: number;
807
796
  minWidth: number;
808
797
  }
809
- //#endregion
810
- //#region src/layout/border.d.ts
811
798
  /**
812
799
  * Border-character glyphs for drawing a box outline. Any single-cell string
813
800
  * is allowed (including multi-byte glyphs like rounded corners).
@@ -822,8 +809,6 @@ interface BorderChars {
822
809
  }
823
810
  type BorderSpec = boolean | "single" | "double" | "rounded" | BorderChars;
824
811
  type TitleAlign = "left" | "center" | "right";
825
- //#endregion
826
- //#region src/widgets/text.d.ts
827
812
  /**
828
813
  * Text content — three forms, resolved at render time:
829
814
  *
@@ -867,8 +852,6 @@ declare function textContent(content: TextContent | undefined, ctx: RenderCtx):
867
852
  */
868
853
  declare function text(content: TextContent, style?: Omit<State<TextStyle>, "content">): Text;
869
854
  declare function text(style: State<TextStyle>): Text;
870
- //#endregion
871
- //#region src/widgets/box.d.ts
872
855
  type Padding = number | readonly [v: number, h: number] | readonly [t: number, r: number, b: number, l: number];
873
856
  interface BoxStyle extends Style {
874
857
  flexDirection?: "row" | "column";
@@ -939,8 +922,6 @@ type Child = Node | false | null | undefined;
939
922
  * conditional JSX-like composition: `box({}, cond && child)`.
940
923
  */
941
924
  declare function box(style: State<BoxStyle>, ...children: Child[]): Box;
942
- //#endregion
943
- //#region src/widgets/overlay.d.ts
944
925
  interface OverlayState {
945
926
  /** Absolute column (1-based) of the overlay's left edge. */
946
927
  x: number;
@@ -963,8 +944,6 @@ type Overlay<T extends Node[] = Node[]> = Box<OverlayState> & {
963
944
  children: T;
964
945
  } & Emitter<OverlayEvents>;
965
946
  declare function overlay<T extends Node[] = Node[]>(state: State<OverlayState & BoxStyle>, ...children: T): Overlay<T>;
966
- //#endregion
967
- //#region src/core/ctx.d.ts
968
947
  /**
969
948
  * Passed to every `render(ctx)` call. Width flows in; height emerges from
970
949
  * the returned row count. Theme is ambient — children share the parent's.
@@ -1036,8 +1015,6 @@ interface MountCtx {
1036
1015
  readonly findNode: (match: string | ((n: Node) => boolean)) => Node[];
1037
1016
  logger: Logger;
1038
1017
  }
1039
- //#endregion
1040
- //#region src/widgets/log.d.ts
1041
1018
  type LogStyle = "badge" | "icon" | "prompt" | "title" | "text" | "notif";
1042
1019
  interface LogState {
1043
1020
  level: LogLevel;
@@ -1066,8 +1043,6 @@ interface LogState {
1066
1043
  * ```
1067
1044
  */
1068
1045
  declare const log: (state: State<LogState>, ...children: Node[]) => Box<{}>;
1069
- //#endregion
1070
- //#region src/services/logger.d.ts
1071
1046
  /** Minimal stream surface the logger needs. Stream satisfies this. */
1072
1047
  interface LoggerStream {
1073
1048
  append: (node: () => Node) => unknown;
@@ -1094,8 +1069,6 @@ declare class TuiReporter implements LogReporter {
1094
1069
  detach(): this;
1095
1070
  $log({ level, msg }: LogEntry): void;
1096
1071
  }
1097
- //#endregion
1098
- //#region src/renderer/terminal.d.ts
1099
1072
  /**
1100
1073
  * Terminal primitive — owns stdin raw mode, stdout writes, and the
1101
1074
  * standard set of control modes we flip for a direct-mode renderer:
@@ -1210,8 +1183,6 @@ declare class Terminal {
1210
1183
  sync(fn: () => void): void;
1211
1184
  onResize(fn: ResizeListener): () => void;
1212
1185
  }
1213
- //#endregion
1214
- //#region src/renderer/frame.d.ts
1215
1186
  type FrameOp = (terminal: Terminal) => void;
1216
1187
  type LineSlice = {
1217
1188
  from: number;
@@ -1257,8 +1228,6 @@ declare class RenderFrame {
1257
1228
  ops: number;
1258
1229
  };
1259
1230
  }
1260
- //#endregion
1261
- //#region src/renderer/surface.d.ts
1262
1231
  /**
1263
1232
  * Base event map for renderer surfaces. Surfaces usually schedule work
1264
1233
  * through their owning `Renderer`; subclasses may extend this with their
@@ -1322,8 +1291,6 @@ declare abstract class Surface<E extends {} = never> extends Emitter<SurfaceEven
1322
1291
  abstract _render(frame: RenderFrame): Promise<void>;
1323
1292
  render(frame?: RenderFrame): Promise<void>;
1324
1293
  }
1325
- //#endregion
1326
- //#region src/renderer/overlay.d.ts
1327
1294
  type OverlayRenderState = {
1328
1295
  x: number;
1329
1296
  y: number;
@@ -1384,8 +1351,6 @@ declare class OverlaySurface extends Surface<OverlaySurfaceEvents> {
1384
1351
  */
1385
1352
  _render(frame: RenderFrame): Promise<void>;
1386
1353
  }
1387
- //#endregion
1388
- //#region src/renderer/selection.d.ts
1389
1354
  type SelectionSurface = "stream" | "screen";
1390
1355
  type Selection = {
1391
1356
  dragging: boolean;
@@ -1419,8 +1384,6 @@ declare class SelectionLayer extends Emitter<SelectionEvents> {
1419
1384
  renderScreen(frame: RenderFrame, ctx: RenderCtx): void;
1420
1385
  render(frame: RenderFrame, ctx: RenderCtx): void;
1421
1386
  }
1422
- //#endregion
1423
- //#region src/renderer/stream.d.ts
1424
1387
  type StreamEvents = {
1425
1388
  idle: void;
1426
1389
  scroll: {
@@ -1504,8 +1467,6 @@ declare class Stream extends Surface<StreamEvents> {
1504
1467
  protected mountAll(ctx: MountCtx): void;
1505
1468
  protected unmountAll(): void;
1506
1469
  }
1507
- //#endregion
1508
- //#region src/renderer/ui.d.ts
1509
1470
  /**
1510
1471
  * UI surface — the sticky footer. Renders a single Box tree at the
1511
1472
  * bottom of the terminal, inside the rows reserved by `Terminal`'s
@@ -1570,13 +1531,13 @@ declare class UI extends Surface {
1570
1531
  bottom: number;
1571
1532
  };
1572
1533
  }
1573
- //#endregion
1574
- //#region src/renderer/renderer.d.ts
1575
1534
  interface RendererOptions {
1576
1535
  stdin?: TerminalReader;
1577
1536
  stdout?: TerminalWriter;
1578
1537
  images?: Reactive<boolean>;
1579
1538
  theme?: Theme;
1539
+ /** Syntax highlighting selection, independent of the UI theme. */
1540
+ shiki?: ShikiSelection;
1580
1541
  transparent?: Reactive<boolean>;
1581
1542
  /** Base colors for painted rows and cleared cells, resolved against the theme. */
1582
1543
  defaultStyle?: Pick<Style, "fg" | "bg">;
@@ -1714,8 +1675,6 @@ declare class Renderer extends Emitter<RenderEvents> {
1714
1675
  * paints are queued. */
1715
1676
  render(): Promise<void>;
1716
1677
  }
1717
- //#endregion
1718
- //#region src/core/node.d.ts
1719
1678
  /** Minimum event map every node carries. Custom event maps intersect
1720
1679
  * this with their own events via `&`. */
1721
1680
  type BaseEvents = {
@@ -1851,8 +1810,6 @@ declare abstract class Node<T extends object = object, E extends {} = {}> extend
1851
1810
  *
1852
1811
  * @internal*/
1853
1812
  declare function isNode(x: unknown): x is Node;
1854
- //#endregion
1855
- //#region src/input/router.d.ts
1856
1813
  type KeyPatterns = KeyPattern | readonly KeyPattern[];
1857
1814
  type KeyHandler = (ev: KeyEvent) => boolean | void;
1858
1815
  /** A keymap entry is either an action id (string) or a direct key
@@ -1945,13 +1902,12 @@ declare class InputRouter extends Emitter<InputRouterEvents> {
1945
1902
  */
1946
1903
  dispatch(ev: InputEvent): boolean;
1947
1904
  }
1948
- //#endregion
1949
- //#region src/input/queries.d.ts
1950
1905
  type TerminalQuery<T = TerminalResponseEvent> = TerminalQueryOpts & {
1951
1906
  request: string;
1952
1907
  match: (event: TerminalResponseEvent) => T | undefined;
1953
1908
  };
1954
1909
  type TerminalQueryOpts = {
1910
+ signal?: AbortSignal;
1955
1911
  timeout?: number;
1956
1912
  wrap?: (seq: string) => string;
1957
1913
  };
@@ -1962,6 +1918,9 @@ declare class TerminalQueries {
1962
1918
  #private;
1963
1919
  constructor(router: InputRouter, terminal: TerminalQueryWriter);
1964
1920
  query<T>(query: TerminalQuery<T>): Promise<T | undefined>;
1921
+ color(index: number | "fg" | "bg" | "selectionBg" | "selectionFg", opts?: TerminalQueryOpts): Promise<`#${string}` | undefined>;
1922
+ colorScheme(opts?: TerminalQueryOpts): Promise<"dark" | "light" | undefined>;
1923
+ palette(opts?: TerminalQueryOpts): Promise<TerminalPaletteSnapshot>;
1965
1924
  primaryDeviceAttributes(opts?: TerminalQueryOpts): Promise<(TerminalResponseEvent & {
1966
1925
  attrs: number[];
1967
1926
  }) | undefined>;
@@ -1973,7 +1932,15 @@ declare class TerminalQueries {
1973
1932
  version?: string;
1974
1933
  }) | undefined>;
1975
1934
  }
1935
+ interface TerminalPaletteSnapshot {
1936
+ ansi: (HexColor | undefined)[];
1937
+ bg?: HexColor;
1938
+ fg?: HexColor;
1939
+ selectionBg?: HexColor;
1940
+ selectionFg?: HexColor;
1941
+ }
1942
+ /** OSC replies use X11 rgb components, with one to four hex digits per channel. */
1943
+ declare function parseTerminalColor(value: string): HexColor | undefined;
1976
1944
  declare function parseAttrs(params: string): number[];
1977
- //#endregion
1978
- export { Context as $, LogState as A, useContext as At, Padding as B, Actions as Bt, OverlaySurface as C, peek as Ct, LoggerStream as D, untrack as Dt, LogStyleOverride as E, toAccessor as Et, Overlay as F, ActionCtx as Ft, text as G, KeyModifier as Gt, Text as H, NodeAction as Ht, OverlayState as I, ActionDef as It, Layout as J, SpecialKeyName as Jt, textContent as K, KeyPattern as Kt, overlay as L, ActionFilter as Lt, log as M, withOwner as Mt, MountCtx as N, Size as Nt, TuiReporter as O, unwrap as Ot, RenderCtx as P, Action as Pt, Accessor as Q, Box as R, ActionFn as Rt, Stream as S, onCleanup as St, LogEntryFactory as T, signal as Tt, TextContent as U, NodeActionMap as Ut, box as V, KeyBinding as Vt, TextStyle as W, KeyEvent as Wt, State as X, isKeyPattern as Xt, LayoutState as Y, canonical as Yt, StyleState as Z, keyMatches as Zt, RenderStats as _, createSuspenseBoundary as _t, InputRouter as a, Signal as at, SurfaceType as b, isAccessor as bt, KeyPatterns as c, SuspenseContext as ct, RoutedPaste as d, createIterable as dt, Owner as et, BaseEvents as f, createNode as ft, RenderEvents as g, createStore as gt, NodeVisitor as h, createRoot as ht, parseAttrs as i, Setter as it, LogStyle as j, withActiveNode as jt, TuiReporterOpts as k, useActiveOwner as kt, KeymapEntry as l, createAsync as lt, isNode as m, createRef as mt, TerminalQuery as n, Reactive as nt, InputRouterEvents as o, SignalStore as ot, Node as p, createProgressive as pt, FlexState as q, KeyPatternError as qt, TerminalQueryOpts as r, Ref as rt, KeyHandler as s, SuspenseBoundary as st, TerminalQueries as t, Progressive as tt, RoutedKey as u, createContext as ut, Renderer as v, effect as vt, Terminal as w, provideContext as wt, UI as x, memo as xt, RendererOptions as y, inRenderContextOf as yt, BoxStyle as z, ActionMap as zt };
1979
- //# sourceMappingURL=queries-BDX8mcl5.d.mts.map
1945
+ export { StyleState as $, keyMatches as $t, TuiReporter as A, unwrap as At, Box as B, ActionFn as Bt, UI as C, memo as Ct, LogEntryFactory as D, signal as Dt, Terminal as E, provideContext as Et, MountCtx as F, Size as Ft, TextContent as G, NodeActionMap as Gt, Padding as H, Actions as Ht, RenderCtx as I, Action as It, textContent as J, KeyPattern as Jt, TextStyle as K, KeyEvent as Kt, Overlay as L, ActionCtx as Lt, LogState as M, useContext as Mt, LogStyle as N, withActiveNode as Nt, LogStyleOverride as O, toAccessor as Ot, log as P, withOwner as Pt, State as Q, isKeyPattern as Qt, OverlayState as R, ActionDef as Rt, SurfaceType as S, isAccessor as St, OverlaySurface as T, peek as Tt, box as U, KeyBinding as Ut, BoxStyle as V, ActionMap as Vt, Text as W, NodeAction as Wt, Layout as X, SpecialKeyName as Xt, FlexState as Y, KeyPatternError as Yt, LayoutState as Z, canonical as Zt, NodeVisitor as _, createRoot as _t, parseAttrs as a, Ref as at, Renderer as b, effect as bt, InputRouterEvents as c, SignalStore as ct, KeymapEntry as d, createAsync as dt, Accessor as et, RoutedKey as f, createContext as ft, isNode as g, createRef as gt, Node as h, createProgressive as ht, TerminalQueryOpts as i, Reactive as it, TuiReporterOpts as j, useActiveOwner as jt, LoggerStream as k, untrack as kt, KeyHandler as l, SuspenseBoundary as lt, BaseEvents as m, createNode as mt, TerminalQueries as n, Owner as nt, parseTerminalColor as o, Setter as ot, RoutedPaste as p, createIterable as pt, text as q, KeyModifier as qt, TerminalQuery as r, Progressive as rt, InputRouter as s, Signal as st, TerminalPaletteSnapshot as t, Context as tt, KeyPatterns as u, SuspenseContext as ut, RenderEvents as v, createStore as vt, Stream as w, onCleanup as wt, RendererOptions as x, inRenderContextOf as xt, RenderStats as y, createSuspenseBoundary as yt, overlay as z, ActionFilter as zt };
1946
+ //# sourceMappingURL=queries-Dmd3IjSd.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries-Dmd3IjSd.d.mts","names":["_$___core_state_ts0.Layout","_$__box_ts0.Box","_$__terminal_ts0.Terminal"],"sources":["../src/input/keys.ts","../src/input/decoder.ts","../src/input/actions.ts","../src/layout/size.ts","../src/core/reactive.ts","../src/core/state.ts","../src/layout/border.ts","../src/widgets/text.ts","../src/widgets/box.ts","../src/widgets/overlay.ts","../src/core/ctx.ts","../src/widgets/log.ts","../src/services/logger.ts","../src/renderer/terminal.ts","../src/renderer/frame.ts","../src/renderer/surface.ts","../src/renderer/overlay.ts","../src/renderer/selection.ts","../src/renderer/stream.ts","../src/renderer/ui.ts","../src/renderer/renderer.ts","../src/core/node.ts","../src/input/router.ts","../src/input/queries.ts"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
- //#region src/core/reactive.ts
2
+ // src/core/reactive.ts
3
3
  const activeCtx = new AsyncLocalStorage();
4
4
  function withTracking(ctx, fn) {
5
5
  return activeCtx.run(ctx, fn);
@@ -617,7 +617,6 @@ function createRef(value, opts = {}) {
617
617
  });
618
618
  return get;
619
619
  }
620
- //#endregion
621
620
  export { useActiveOwner as C, withOwner as E, unwrap as S, withActiveNode as T, peek as _, createIterable as a, toAccessor as b, createRef as c, createSuspenseBoundary as d, effect as f, onCleanup as g, memo as h, createContext as i, createRoot as l, isAccessor as m, SuspenseContext as n, createNode as o, inRenderContextOf as p, createAsync as r, createProgressive as s, Owner as t, createStore as u, provideContext as v, useContext as w, untrack as x, signal as y };
622
621
 
623
- //# sourceMappingURL=reactive-f7NpAi69.mjs.map
622
+ //# sourceMappingURL=reactive-DkP75TPk.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"reactive-f7NpAi69.mjs","names":[],"sources":["../src/core/reactive.ts"],"sourcesContent":["import type { MaybePromise } from \"@zaly/shared\"\nimport type { Node } from \"./node.ts\"\n\nimport { AsyncLocalStorage } from \"node:async_hooks\"\n\n/**\n * Solid-style fine-grained reactivity.\n *\n * `signal(initial)` → `[read, write]` tuple. Reads inside a\n * tracking context (node render, effect, memo) auto-subscribe;\n * writes invalidate every subscriber. Cross-async-boundary tracking\n * uses `AsyncLocalStorage` so reads after an `await` still subscribe\n * the correct context.\n *\n * ```ts\n * const [status, setStatus] = signal(\"streaming\")\n * text(({ style }) => style.success(status())) // auto-subscribes\n * setStatus(\"done\")\n * ```\n *\n * Builds on three primitives:\n * - `signal` — reactive value.\n * - `memo` — cached derived signal.\n * - `effect` — imperative side-effect that re-runs on dep change.\n *\n * Widgets expose `Reactive<T>` props and call `unwrap()` inside\n * `_render` to resolve them — that's the bridge from app-level\n * signals into the render tree.\n */\n\n// ---- tracking context ------------------------------------------------\n\n/** Context carried through a tracking scope. Subscribers that want to\n * be signal-aware implement this; signals read the current context\n * during `read()` and add `notify` to their subscriber set. `register`\n * lets the context remember the cleanup closure so it can\n * unsubscribe later (on unmount / dispose / re-run). */\ninterface TrackingCtx {\n notify: () => void\n register: (cleanup: () => void) => void\n}\n\nconst activeCtx = new AsyncLocalStorage<TrackingCtx | undefined>()\n\nfunction withTracking<T>(ctx: TrackingCtx, fn: () => T): T {\n return activeCtx.run(ctx, fn)\n}\n\n/** Run `fn` outside any tracking scope. Signal reads inside don't\n * subscribe the surrounding render, and async work started inside\n * (timers, promises, intervals) doesn't capture the current ctx —\n * callbacks fire with `getStore() === undefined`.\n *\n * Use this when starting persistent async work from inside a render\n * pass: a `setInterval` set up during `_render` would otherwise\n * inherit the render's ALS context, and every timer tick would look\n * like it's \"inside\" that render — its invalidates would be silently\n * suppressed.\n *\n * ```ts\n * // inside _render() or a render-driven reconcile():\n * untracked(() => {\n * this.#timer = setInterval(() => this.invalidate(), speed)\n * })\n * ```\n *\n * Equivalent to Solid's `untrack`. */\nexport function untrack<T>(fn: () => T): T {\n return activeCtx.run(undefined, fn)\n}\n\n/** Resolve a `Reactive<T>` to its current `T` without subscribing to\n * any tracking context. */\nexport function peek<T>(s: Reactive<T>): T {\n return untrack(() => unwrap(s))\n}\n\n// ---- context ---------------------------------------------------------\n\n/**\n * Solid-style context for sharing values down the owner chain without\n * prop-drilling. Widgets publish values via `provideContext` (in setup\n * or `_render`); descendants read via `useContext`.\n *\n * ```ts\n * const ThemeOverride = createContext<Theme | undefined>(undefined)\n *\n * // provider (in a widget body / setup / _render):\n * provideContext(ThemeOverride, customTheme)\n *\n * // consumer (anywhere with an active node or owner chain):\n * const theme = useContext(ThemeOverride) ?? defaultTheme\n * ```\n *\n * Implementation: each `Node` carries an optional `#contexts` map keyed\n * by context id. Lookups walk the *owner frame chain* (`OwnerFrame.owner`\n * pointers), reading the live `#contexts` of each frame's node and\n * falling back to the context's default if no ancestor provides it.\n *\n * The owner chain is the render-call ancestry captured at frame push\n * (via `withActiveNode`) — independent of mount status. Effects/memos\n * capture their creation frame and re-establish it on re-fire, so\n * detached re-runs walk the same chain they would have at creation.\n */\nexport interface Context<T> {\n readonly id: symbol\n readonly defaultValue: T\n}\n\nexport function createContext<T>(): Context<T | undefined>\nexport function createContext<T>(defaultValue: T): Context<T>\nexport function createContext<T>(defaultValue?: T): Context<T | undefined> {\n return { defaultValue, id: Symbol(\"@zaly/tui/context\") }\n}\n\n/** Publish `value` for `ctx` on the active Owner. Persistent for the\n * Owner's lifetime. Descendants (in the render-call sense) that read\n * via `useContext` walk up the Owner chain and find it. */\nexport function provideContext<T>(ctx: Context<T>, value: T): void {\n const owner = activeOwnerStore.getStore()\n if (owner === undefined) {\n throw new Error(\"provideContext: no active Owner — call from a widget body / _render\")\n }\n owner.setContext(ctx.id, value)\n}\n\n/** Read the current value of `ctx`. Walks the Owner chain\n * (render-call ancestry, not mount tree). Returns the context's\n * default when no ancestor has provided a value. */\nexport function useContext<T>(ctx: Context<T>): T {\n for (let o = activeOwnerStore.getStore(); o !== undefined; o = o.parent) {\n const map = o.contexts\n if (map?.has(ctx.id)) return map.get(ctx.id) as T\n }\n return ctx.defaultValue\n}\n\n// ---- public types ----------------------------------------------------\n\n/** Brand tag: every accessor / setter returned by `signal` / `memo`\n * carries this symbol so `unwrap` can tell a reactive source from a\n * plain function-valued prop (label formatter, text callback, etc.). */\nconst REACTIVE = Symbol.for(\"@zaly/tui/reactive\")\n\nexport type Signal<T> = readonly [get: Accessor<T>, set: Setter<T>] & {\n readonly get: Accessor<T>\n readonly set: Setter<T>\n}\n\n/** A read-only reactive source. Branded so `isAccessor` can detect it\n * without false positives on arbitrary callables. */\nexport type Accessor<T> = (() => T) & { readonly [REACTIVE]: \"get\" }\n\n/** A signal setter. Same branding as `Accessor` (different tag) so a\n * setter isn't mistaken for an accessor by `unwrap`. */\nexport type Setter<T> = ((next: T | ((prev: T) => T)) => void) & { readonly [REACTIVE]: \"set\" }\n\n/** A widget prop that's either a literal value or a reactive accessor. */\nexport type Reactive<T> = T | Accessor<T>\n\n/** Runtime check: `true` when `v` was produced by `signal` / `memo`.\n * False for plain callables (text-content functions, label formatters).\n *\n * @internal */\nexport function isAccessor<T>(v: unknown): v is Accessor<T> {\n return typeof v === \"function\" && (v as { [REACTIVE]?: string })[REACTIVE] === \"get\"\n}\n\n/** Resolve a `Reactive<T>` to its current `T`. Call inside `_render`\n * so accessor reads subscribe the rendering node. Only brand-tagged\n * accessors are invoked — other function values pass through\n * untouched, so widgets whose `T` is itself a function type (label\n * formatters etc.) don't need a hand-rolled guard. */\nexport function unwrap<T>(v: Reactive<T>): T {\n return isAccessor<T>(v) ? v() : v\n}\n\nfunction brand<F extends (...args: any[]) => any>(fn: F, tag: \"get\"): Accessor<ReturnType<F>>\nfunction brand<F extends (...args: any[]) => any>(fn: F, tag: \"set\"): Setter<Parameters<F>[0]>\nfunction brand<F extends (...args: any[]) => any>(fn: F, tag: \"get\" | \"set\"): F {\n Object.defineProperty(fn, REACTIVE, {\n configurable: false,\n enumerable: false,\n value: tag,\n writable: false,\n })\n return fn\n}\n\n// ---- Owner -----------------------------------------------------------\n\n/**\n * Reactive ownership scope — bundles cleanups + provided contexts\n * scoped to a single widget body (or a `createRoot` headless scope).\n *\n * Owners form a chain via `parent` mirroring the call-time widget\n * nesting: when `widget()` is invoked inside another widget's body,\n * `createNode` creates the inner Owner with `parent =\n * activeOwnerStore.getStore()` (the outer widget's Owner). That chain\n * is what `useContext` walks.\n *\n * Owners are **not** bound to Nodes anymore — a widget's `createNode`\n * pairs the Owner with the constructed Node only through\n * `Node.once(\"unmount\", () => owner.dispose())`. Primitive Nodes\n * (`text`, `box`, …) don't get their own Owner; they share whatever\n * Owner created them.\n *\n * Use `onCleanup(cb)` to register cleanups against the active Owner.\n * Disposing the Owner runs them in reverse-registration order.\n *\n * @internal\n */\nexport class Owner {\n parent?: Owner\n #cleanups: (() => void)[] = []\n #contexts?: Map<symbol, unknown>\n #disposed = false\n\n constructor(parent?: Owner) {\n this.parent = parent\n }\n\n get disposed(): boolean {\n return this.#disposed\n }\n\n /** Live view of this Owner's provided contexts. Populated by\n * `provideContext`. Walked upward via `parent` by `useContext`. */\n get contexts(): ReadonlyMap<symbol, unknown> | undefined {\n return this.#contexts\n }\n\n setContext(id: symbol, value: unknown): void {\n ;(this.#contexts ??= new Map()).set(id, value)\n }\n\n /** Register a cleanup. Runs on `dispose()`. */\n addCleanup(fn: () => void): void {\n if (this.#disposed) {\n fn()\n return\n }\n this.#cleanups.push(fn)\n }\n\n /** Fire cleanups in reverse-registration order. Idempotent. */\n dispose(): void {\n if (this.#disposed) return\n this.#disposed = true\n for (let i = this.#cleanups.length - 1; i >= 0; i--) {\n try {\n this.#cleanups[i]()\n } catch (error) {\n // Don't let one bad cleanup poison the rest.\n // oxlint-disable-next-line no-console\n console.error(\"Owner cleanup threw:\", error)\n }\n }\n this.#cleanups = []\n this.#contexts = undefined\n }\n}\n\nconst activeOwnerStore = new AsyncLocalStorage<Owner | undefined>()\n\n/** Run `fn` as the `node`'s render pass. Signal reads inside subscribe\n * the node's tracking ctx; the ctx's `notify` is `node.invalidate`,\n * so any signal write that this render depended on invalidates the\n * node and clears its cache. Cleanups are registered against the\n * Node's `unmount` event.\n *\n * Does **not** push an Owner — primitive Nodes share whatever Owner\n * was active in their caller. Widget bodies install their own Owner\n * via `createNode` at construction time, which is when `useContext`\n * / `provideContext` / `effect` / `memo` care about the active scope.\n *\n * @internal */\nexport function withActiveNode<T>(node: Node, fn: () => T): T {\n return withTracking(getNodeTrackingCtx(node), fn)\n}\n\n/** Run `fn` with a pre-existing Owner restored. Used by `effect` /\n * `memo` to re-establish their creation-time owner chain on re-fire,\n * so `useContext` walks the same ancestry regardless of whether the\n * re-fire was triggered from inside or outside a render.\n *\n * @internal */\nexport function withOwner<T>(owner: Owner, fn: () => T): T {\n return activeOwnerStore.run(owner, fn)\n}\n\nfunction getNodeTrackingCtx(node: Node): TrackingCtx {\n let ctx = nodeCtx.get(node)\n if (ctx === undefined) {\n ctx = {\n notify: () => node.invalidate(),\n register: (cleanup) => {\n node.once(\"unmount\", cleanup)\n },\n }\n nodeCtx.set(node, ctx)\n }\n return ctx\n}\n\n/** Create a fresh Owner scope and run `fn` inside it. Returns\n * whatever `fn` returns. The Owner's parent is whatever was active at\n * the call site (or `undefined` at module top).\n *\n * The Owner is *not* auto-disposed — callers manage its lifetime via\n * the Owner returned alongside the result, or (more commonly) by\n * binding the Owner to a Node and disposing it on that Node's\n * unmount.\n *\n * Typical use is via a surface's function-shape `add(fn)` API which\n * wraps this internally:\n *\n * ```ts\n * ui.add(() => {\n * const [count, setCount] = signal(0)\n * onCleanup(() => console.log(\"gone\"))\n * return text(() => `count: ${count()}`)\n * })\n * ```\n *\n * For headless reactive scopes (tests, programmatic effects), call\n * `createRoot` directly:\n *\n * ```ts\n * const { result, owner } = createRoot(() => signal(0))\n * // ... use result ...\n * owner.dispose()\n * ```\n */\nexport function createRoot<T>(fn: (dispose: () => void) => T): T {\n const parent = activeOwnerStore.getStore()\n const owner = new Owner(parent)\n return withOwner(owner, () => fn(() => owner.dispose()))\n}\n\n/** Run `fn` inside a fresh Owner scope and bind the returned Node to\n * that scope — when the Node unmounts, the Owner disposes (firing\n * every `onCleanup`, tearing down every `effect` / `memo` /\n * `createAsync` registered in the body).\n *\n * This is what `widget()` calls under the hood: it's the per-instance\n * scope boundary. Surfaces also call it directly at their `add` /\n * `append` entry points so each appended subtree gets its own root.\n *\n * ```ts\n * ui.add(() => {\n * const [c, setC] = signal(0)\n * onCleanup(() => clearInterval(timer))\n * const timer = setInterval(() => setC(x => x + 1), 1000)\n * return text(() => `count: ${c()}`)\n * })\n * ```\n */\nexport function createNode<T extends Node>(fn: () => T): T {\n return createRoot((dispose) => fn().once(\"unmount\", dispose))\n}\n\n/** Register a cleanup against the active Owner. Fires when the Owner\n * disposes — i.e. when the widget body's `createNode` Node unmounts,\n * or when the surrounding `createRoot` is disposed.\n *\n * ```ts\n * function widgetBody() {\n * const id = setInterval(() => tick(), 1000)\n * onCleanup(() => clearInterval(id))\n * return box(…)\n * }\n * ```\n *\n * Throws if called outside any active Owner — the cleanup would\n * never fire and the caller is almost certainly mistaken. */\nexport function onCleanup(fn: () => void): void {\n const owner = activeOwnerStore.getStore()\n if (owner === undefined) {\n throw new Error(\"onCleanup: no active Owner — call from inside a widget body / createRoot\")\n }\n owner.addCleanup(fn)\n}\n\n/** Current Owner, or `undefined` outside any render. Captured by\n * effects/memos at creation time and restored on re-fire.\n *\n * @internal */\nexport function useActiveOwner(): Owner | undefined {\n return activeOwnerStore.getStore()\n}\n\n/** Whether we're currently executing inside `node`'s own render call\n * stack — i.e. this code path was reached synchronously (or via an\n * await preserved by `AsyncLocalStorage`) from `node`'s `withActiveNode`.\n *\n * Used by `invalidate()` to suppress *internal* cascades — e.g.\n * Markdown mutating its child Text inside its own `_render`. External\n * mutations (network callbacks, event handlers) run outside any\n * render's ALS scope, so this returns `false` for them and they emit\n * normally even when a render is in flight.\n *\n * @internal */\nexport function inRenderContextOf(node: Node): boolean {\n const active = activeCtx.getStore()\n return active !== undefined && active === nodeCtx.get(node)\n}\n\nconst nodeCtx = new WeakMap<Node, TrackingCtx>()\n\n// ---- signal ----------------------------------------------------------\n\n/**\n * Reactive value. Returns a `[get, set]` tuple that's also accessible\n * as `.get` / `.set` for destructure-skipping callers. Reads inside a\n * tracking context (node render, effect, memo) auto-subscribe; writes\n * notify every subscriber synchronously.\n *\n * ```ts\n * const [count, setCount] = signal(0)\n * setCount(1) // value form\n * setCount((prev) => prev + 1) // updater form\n * ```\n *\n * **Storing a function as a value — gotcha**: `set` interprets any\n * function argument as the *updater* form `(prev) => next`, calls it\n * with the current value, and stores the result. To store a function\n * value (e.g. a callable `StyleBuilder` or a handler ref), wrap with\n * the updater form so the call resolves to the function you wanted:\n *\n * ```ts\n * const [style, setStyle] = signal<StyleBuilder | undefined>(undefined)\n * setStyle(ctx.style) // ✗ stored as `ctx.style(undefined)` — a string\n * setStyle(() => ctx.style) // ✓ stored as the StyleBuilder itself\n * ```\n *\n * Same trap exists in Solid and React's `useState`. If you find\n * yourself reaching for it, also consider whether storing a *plain*\n * value (the underlying data, not the chain/builder) and recomputing\n * the function-y derivative inside a `memo` is cleaner — usually it\n * is.\n *\n * Equality is reference-based: `set(v)` where `v === current` skips\n * the notify. Wrap mutable values you want to \"publish\" in a fresh\n * object/array, or use a counter signal to force fan-out.\n */\nexport function signal<T>(\n initial: T,\n opts: { equals?: false | ((prev: T, next: T) => boolean) } = {}\n): Signal<T> {\n let value = initial\n const subs = new Set<() => void>()\n const equals = opts.equals === false ? () => false : (opts.equals ?? ((a, b) => a === b))\n\n const get = brand((): T => {\n const ctx = activeCtx.getStore()\n if (ctx && !subs.has(ctx.notify)) {\n subs.add(ctx.notify)\n ctx.register(() => subs.delete(ctx.notify))\n }\n return value\n }, \"get\")\n\n const set = brand((next: T | ((prev: T) => T)): void => {\n const resolved = typeof next === \"function\" ? (next as (prev: T) => T)(value) : next\n if (equals(value, resolved)) return\n value = resolved\n // Snapshot — subscribers may mutate the set while running.\n const snapshot = [...subs]\n for (const notify of snapshot) notify()\n }, \"set\")\n\n return Object.assign([get, set] as const, { get, set }) as Signal<T>\n}\n\n/**\n * Lift a plain value to an `Accessor<T>`. The returned function always\n * returns `value`, never tracks, never notifies — useful at the boundary\n * where a static value enters a tree that otherwise expects `Accessor<T>`.\n *\n * Branded so `isAccessor` reports `true` and downstream `unwrap` calls\n * resolve to a stable function call rather than treating the value as\n * a ctx-aware thunk.\n *\n * ```ts\n * // Component expects `Accessor<Theme>` deep in the tree:\n * <CodeBlock theme={toAccessor(myStaticTheme)} />\n * ```\n */\nexport function toAccessor<T>(fn: () => T): Accessor<T> {\n return brand(() => fn(), \"get\")\n}\n\n// ---- effect ----------------------------------------------------------\n\n/**\n * Run `fn` immediately, then re-run whenever a signal it read writes.\n * Returns a disposer that stops the effect and drops all tracked\n * subscriptions. Unlike node render, effect dependencies are re-tracked\n * from scratch on every run — reads that disappear from `fn` stop\n * triggering re-runs.\n *\n * ```ts\n * const dispose = effect(() => {\n * console.log(\"status is\", status())\n * })\n * // ...\n * dispose()\n * ```\n *\n * **Footgun**: don't write a signal from inside an effect that reads\n * the same signal — you'll loop. Writing unrelated signals is fine.\n */\nexport function effect(fn: () => void | (() => void)): () => void {\n let cleanups: (() => void)[] = []\n let disposed = false\n\n // Capture the Owner at creation time. Re-fires triggered by signal\n // writes run in the *writer's* ALS context, which has nothing to do\n // with where the effect was created. Restoring the captured Owner on\n // each run keeps `useContext` walking the same ancestry regardless\n // of who triggered the re-fire.\n const owner = useActiveOwner()\n\n const ctx: TrackingCtx = {\n notify: () => {\n if (disposed) return\n run()\n },\n register: (cleanup) => {\n cleanups.push(cleanup)\n },\n }\n\n const run = (): void => {\n // Fresh deps each run — unsubscribe from everything we saw last time.\n const old = cleanups\n cleanups = []\n for (const c of old) c()\n // oxlint-disable-next-line unicorn/consistent-function-scoping\n const tracked = (): void | (() => void) => withTracking(ctx, fn)\n const cleanup = owner !== undefined ? withOwner(owner, tracked) : tracked()\n if (typeof cleanup === \"function\") cleanups.push(cleanup)\n }\n\n // Auto-dispose on owner teardown. If there's no owner, the caller\n // owns the returned dispose function and is responsible for cleanup.\n const dispose = (): void => {\n if (disposed) return\n disposed = true\n for (const c of cleanups) c()\n cleanups = []\n }\n owner?.addCleanup(dispose)\n\n run()\n\n return dispose\n}\n\n// ---- memo ------------------------------------------------------------\n\n/**\n * Derived, cached signal. `fn` runs once eagerly; the cached value is\n * returned from the accessor. When any signal `fn` reads writes, the\n * memo recomputes and notifies its own subscribers — but only if the\n * new value differs from the cached one (reference equality).\n *\n * ```ts\n * const [value, setValue] = signal(0)\n * const pct = memo(() => Math.round(value() * 100))\n * text(({ style }) => `${pct()}%`) // subscribes to pct, not value\n * ```\n *\n * Returns an `Accessor<T>`, not a `[read, write]` tuple — memos are\n * read-only by construction.\n */\nexport function memo<T>(fn: () => T): Accessor<T> {\n const [get, set] = signal<T>(undefined as T)\n effect(() => {\n // Wrap in the updater form so `signal.set`'s `typeof === \"function\"`\n // detection always picks the outer closure, never `fn()`'s return\n // value. Without this, memoizing a callable `T` (e.g. a chainable\n // `StyleBuilder`) would cause `set` to invoke it as an updater and\n // cache the call result instead of the value itself.\n set(() => fn())\n })\n return get\n}\n\n// ---- signal store ----------------------------------------------------\n\n/**\n * Reactive struct with fine-grained, lazy per-field tracking.\n *\n * Reads:\n * - `store.foo` — tracked when called inside a tracking ctx; allocates\n * a signal for `foo` on first read.\n *\n * Writes:\n * - `store.foo = x` — direct assignment.\n * - `store({ foo: x, bar: y })` — partial patch (merge).\n * - `store(current => ({ foo: current.foo + 1 }))` — updater form;\n * the function receives the current plain state (untracked) and\n * returns a partial patch which is then merged.\n *\n * All writes are value-equality (`===`) gated; setting a field to its\n * current value is a no-op. The function-form updater receives the\n * underlying state object directly so reads inside it are NOT tracked\n * — exactly what an updater wants (\"compute next from current\").\n *\n * Spread (`{ ...store }`) yields the current values of every field via\n * the proxy's `ownKeys` + `getOwnPropertyDescriptor` traps. Be aware:\n * spreading inside a tracking ctx subscribes that ctx to every field\n * (one signal allocation per field). Outside a tracking ctx, spread is\n * cheap (no signal allocation).\n *\n * Implementation: an inner `state` object is the source of truth for\n * plain reads / spreads / the updater's `current`. A `sigs` map is a\n * lazy tracking layer; a key only gets a signal once it's read inside\n * a tracking ctx. Writes update `state` and notify the signal *if it\n * exists* — fields nobody subscribed to never allocate.\n */\nexport type SignalStore<T extends object> = T & {\n /** Apply a partial patch (merge), or call with an updater that\n * receives the current plain state (untracked) and returns a\n * partial to merge. Each field's signal short-circuits on value-\n * equality, so unchanged fields don't notify subscribers. */\n set: (patch: Partial<T> | ((current: T) => Partial<T>)) => void\n}\n\nexport function createStore<T extends object>(initial: T): SignalStore<T> {\n const state = { ...initial }\n const sigs = {} as { [K in keyof T]?: Signal<T[K]> }\n\n const ensure = <K extends keyof T>(key: K): Signal<T[K]> => (sigs[key] ??= signal(state[key]))\n\n const setKey = <K extends keyof T>(key: K, value: T[K]): void => {\n if (state[key] === value) return\n state[key] = value\n // Wrap in updater form so `signal.set`'s `typeof === \"function\"`\n // detection always picks the outer closure — necessary for storing\n // function-typed fields without `set` invoking them as updaters.\n sigs[key]?.set(() => value)\n }\n\n const set = (patch: Partial<T> | ((c: T) => Partial<T>)): void => {\n const p = typeof patch === \"function\" ? patch(state) : patch\n for (const k of Object.keys(p) as (keyof T)[]) {\n const v = p[k]\n setKey(k, v as T[typeof k])\n }\n }\n\n return new Proxy({} as object, {\n get(_, key) {\n if (key === \"set\") return set\n return ensure(key as keyof T).get()\n },\n getOwnPropertyDescriptor(_, key) {\n if (!Object.hasOwn(state, key)) return undefined\n return {\n configurable: true,\n enumerable: true,\n value: state[key as keyof T],\n }\n },\n has(_, key) {\n return key === \"set\" || (key as keyof T) in state\n },\n ownKeys() {\n return Reflect.ownKeys(state)\n },\n set(_, key, value) {\n setKey(key as keyof T, value as T[keyof T])\n return true\n },\n }) as SignalStore<T>\n}\n\n// ---- suspense --------------------------------------------------------\n\n/**\n * Suspense boundary handle — the value of `SuspenseContext`. Consumers\n * (`createAsync`) call `increment` / `decrement` around in-flight work\n * so providers (Stream's append, a `suspense()` widget) can observe\n * \"is anything pending below me\".\n *\n * Boundaries chain: when a `suspense()` body installs its own boundary,\n * its `parent` is the nearest ancestor boundary. Count flips at the\n * 0→1 and 1→0 transitions propagate to the parent, so the outermost\n * boundary's count is `> 0` iff *any* descendant has pending work —\n * a single integer, no walks.\n *\n * `whenIdle` resolves when count returns to 0. Used by Stream to gate\n * paint on resolved async; could be used by any other \"wait for\n * subtree to settle\" caller.\n */\nexport type SuspenseBoundary = {\n increment: () => void\n decrement: () => void\n active: () => boolean\n whenIdle: () => Promise<void>\n}\n\n/** Nearest Suspense provider in the Owner chain. `undefined` when no\n * boundary is installed — `createAsync` runs fire-and-forget in that\n * case (signal resolves later, normal invalidation re-renders). */\nexport const SuspenseContext = createContext<SuspenseBoundary | undefined>(undefined)\n\n/**\n * Build a boundary whose count flips propagate to `parent` on the 0→1\n * and 1→0 transitions. Used by Stream's `append` and the `suspense()`\n * widget. Internal-ish — most callers shouldn't construct boundaries\n * directly.\n *\n * @internal\n */\nexport function createSuspenseBoundary(parent?: SuspenseBoundary): SuspenseBoundary {\n let count = 0\n let idle: { promise: Promise<void>; resolve: () => void } | undefined\n return {\n active: () => count > 0,\n decrement: () => {\n if (count === 0) return\n count--\n if (count === 0) {\n parent?.decrement()\n idle?.resolve()\n idle = undefined\n }\n },\n increment: () => {\n count++\n if (count === 1) parent?.increment()\n },\n whenIdle: () => {\n if (count === 0) return Promise.resolve()\n if (idle === undefined) {\n const { promise, resolve } = Promise.withResolvers<void>()\n idle = { promise, resolve }\n }\n return idle.promise\n },\n }\n}\n\n// ---- async -----------------------------------------------------------\n\n/**\n * Resource-style async accessor. `fn` reads signals (tracked); the\n * effect re-fires when any of them change. Each run notifies the\n * nearest `SuspenseContext` so a surrounding boundary (Stream's\n * append, a `suspense()` widget) can observe pending work.\n *\n * ```ts\n * const highlighted = createAsync(\n * async (prev) => highlight(unwrap(props.code)),\n * { initialValue: unwrap(props.code) },\n * )\n * text(highlighted)\n * ```\n *\n * **Stale-write protection**: each run bumps a generation counter;\n * late `.then` callbacks check it and skip `setValue` if a newer run\n * has already fired. The boundary is decremented exactly once per\n * increment (in the settle callback, regardless of staleness).\n *\n * **`prev`** is the previously resolved value (or `initialValue`) —\n * useful for diff-based fetches. Reading it does *not* track, so\n * resolving the new value won't re-fire the effect.\n *\n * **No active boundary** → increment/decrement no-op, work is\n * fire-and-forget. Right for UI surface widgets that re-render\n * cheaply on signal change. The Stream surface installs a boundary\n * per appended subtree so committed-to-scrollback rows always reflect\n * resolved values.\n */\nexport function createAsync<T>(\n fn: (prev: T | undefined) => Promise<T>,\n opts: { initialValue: T }\n): Accessor<T>\nexport function createAsync<T>(\n fn: (prev: T | undefined) => Promise<T>,\n opts?: { initialValue?: T }\n): Accessor<T | undefined>\nexport function createAsync<T>(\n fn: (prev: T | undefined) => Promise<T>,\n opts?: { initialValue?: T }\n): Accessor<T | undefined> {\n const [value, setValue] = signal<T | undefined>(opts?.initialValue)\n const suspense = useContext(SuspenseContext)\n let gen = 0\n effect(() => {\n const my = ++gen\n let p: Promise<T>\n try {\n p = fn(untrack(value))\n } catch (error) {\n // Sync throw inside `fn` — surface as a rejected promise so the\n // boundary increment / decrement path stays uniform.\n p = Promise.reject(error as Error)\n }\n suspense?.increment()\n p.then(\n (v) => {\n if (my === gen) setValue(() => v)\n },\n () => {\n // Swallow — async failures leave the previous (or initial)\n // value in place.\n }\n ).finally(() => suspense?.decrement())\n })\n return value\n}\n\nexport type Progressive<T> = Accessor<T> & {\n readonly loading: Accessor<boolean>\n whenIdle: () => Promise<void>\n}\n\nexport function createProgressive<T>(\n fn: (ctx: { signal: AbortSignal; set: (value: T) => void }) => MaybePromise<T>,\n opts: { throttle?: number; initialValue: T }\n): Progressive<T>\nexport function createProgressive<T>(\n fn: (ctx: { signal: AbortSignal; set: (value: T) => void }) => MaybePromise<T>,\n opts: { throttle?: number; initialValue?: T }\n): Progressive<T | undefined>\nexport function createProgressive<T>(\n fn: (ctx: { signal: AbortSignal; set: (value: T) => void }) => MaybePromise<T>,\n opts: { throttle?: number; initialValue?: T } = {}\n): Progressive<T | undefined> {\n const throttle = opts.throttle ?? 16\n const [loading, setLoading] = signal(true)\n const [state, setState] = signal<T | undefined>(opts.initialValue, { equals: false })\n\n const ret: Progressive<T | undefined> = Object.assign(state, {\n get loading() {\n return loading\n },\n whenIdle: () => {\n if (!loading()) return Promise.resolve()\n idle ??= Promise.withResolvers<void>()\n return idle.promise\n },\n })\n\n let gen = 0\n let idle: ReturnType<typeof Promise.withResolvers<void>> | undefined\n\n effect(() => {\n const my = ++gen\n const ac = new AbortController()\n\n void (async () => {\n try {\n setLoading(true)\n let prev = 0\n const result = await fn({\n set: (value: T) => {\n if (ac.signal.aborted || my !== gen) return\n const now = performance.now()\n if (now - prev >= throttle) {\n prev = now\n setState(() => value)\n }\n },\n signal: ac.signal,\n })\n if (my === gen) {\n setState(() => result)\n setLoading(false)\n idle?.resolve()\n idle = undefined\n }\n } catch (error) {\n if (my === gen) {\n setLoading(false)\n idle?.reject(error)\n idle = undefined\n }\n } finally {\n ac.abort()\n }\n })()\n\n return () => {\n ac.abort()\n }\n })\n\n return ret\n}\n\nexport function createIterable<T>(\n fn: (ctx: { signal: AbortSignal }) => AsyncIterable<T | readonly T[]>,\n opts: { throttle?: number; initialValue?: readonly T[] } = {}\n): Progressive<readonly T[]> {\n return createProgressive(\n async ({ signal: s, set }) => {\n const results: T[] = []\n for await (const item of fn({ signal: s })) {\n if (s.aborted) return results\n results.push(...(Array.isArray(item) ? item : [item]))\n set(results)\n }\n return results\n },\n { ...opts, initialValue: opts.initialValue ?? [] }\n )\n}\n\nexport interface Ref<T> {\n (): T\n get value(): T | undefined\n set value(value: T)\n}\n\nexport function createRef<T>(\n value?: T,\n opts: { onSet?: (value: T, prev: T | undefined) => void | (() => void) } = {}\n): Ref<T> {\n let current = value\n let cleanup: (() => void) | undefined\n\n const get = (): T => {\n if (current === undefined) throw new Error(\"Ref value accessed before initialization\")\n return current\n }\n\n Object.defineProperty(get, \"value\", {\n get: () => current,\n set: (v: T) => {\n if (current === v) return\n cleanup?.()\n cleanup = undefined\n const prev = current\n current = v\n cleanup = opts.onSet?.(v, prev) ?? undefined\n },\n })\n\n return get as Ref<T>\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"reactive-DkP75TPk.mjs","names":[],"sources":["../src/core/reactive.ts"],"sourcesContent":["import type { MaybePromise } from \"@zaly/shared\"\nimport type { Node } from \"./node.ts\"\n\nimport { AsyncLocalStorage } from \"node:async_hooks\"\n\n/**\n * Solid-style fine-grained reactivity.\n *\n * `signal(initial)` → `[read, write]` tuple. Reads inside a\n * tracking context (node render, effect, memo) auto-subscribe;\n * writes invalidate every subscriber. Cross-async-boundary tracking\n * uses `AsyncLocalStorage` so reads after an `await` still subscribe\n * the correct context.\n *\n * ```ts\n * const [status, setStatus] = signal(\"streaming\")\n * text(({ style }) => style.success(status())) // auto-subscribes\n * setStatus(\"done\")\n * ```\n *\n * Builds on three primitives:\n * - `signal` — reactive value.\n * - `memo` — cached derived signal.\n * - `effect` — imperative side-effect that re-runs on dep change.\n *\n * Widgets expose `Reactive<T>` props and call `unwrap()` inside\n * `_render` to resolve them — that's the bridge from app-level\n * signals into the render tree.\n */\n\n// ---- tracking context ------------------------------------------------\n\n/** Context carried through a tracking scope. Subscribers that want to\n * be signal-aware implement this; signals read the current context\n * during `read()` and add `notify` to their subscriber set. `register`\n * lets the context remember the cleanup closure so it can\n * unsubscribe later (on unmount / dispose / re-run). */\ninterface TrackingCtx {\n notify: () => void\n register: (cleanup: () => void) => void\n}\n\nconst activeCtx = new AsyncLocalStorage<TrackingCtx | undefined>()\n\nfunction withTracking<T>(ctx: TrackingCtx, fn: () => T): T {\n return activeCtx.run(ctx, fn)\n}\n\n/** Run `fn` outside any tracking scope. Signal reads inside don't\n * subscribe the surrounding render, and async work started inside\n * (timers, promises, intervals) doesn't capture the current ctx —\n * callbacks fire with `getStore() === undefined`.\n *\n * Use this when starting persistent async work from inside a render\n * pass: a `setInterval` set up during `_render` would otherwise\n * inherit the render's ALS context, and every timer tick would look\n * like it's \"inside\" that render — its invalidates would be silently\n * suppressed.\n *\n * ```ts\n * // inside _render() or a render-driven reconcile():\n * untracked(() => {\n * this.#timer = setInterval(() => this.invalidate(), speed)\n * })\n * ```\n *\n * Equivalent to Solid's `untrack`. */\nexport function untrack<T>(fn: () => T): T {\n return activeCtx.run(undefined, fn)\n}\n\n/** Resolve a `Reactive<T>` to its current `T` without subscribing to\n * any tracking context. */\nexport function peek<T>(s: Reactive<T>): T {\n return untrack(() => unwrap(s))\n}\n\n// ---- context ---------------------------------------------------------\n\n/**\n * Solid-style context for sharing values down the owner chain without\n * prop-drilling. Widgets publish values via `provideContext` (in setup\n * or `_render`); descendants read via `useContext`.\n *\n * ```ts\n * const ThemeOverride = createContext<Theme | undefined>(undefined)\n *\n * // provider (in a widget body / setup / _render):\n * provideContext(ThemeOverride, customTheme)\n *\n * // consumer (anywhere with an active node or owner chain):\n * const theme = useContext(ThemeOverride) ?? defaultTheme\n * ```\n *\n * Implementation: each `Node` carries an optional `#contexts` map keyed\n * by context id. Lookups walk the *owner frame chain* (`OwnerFrame.owner`\n * pointers), reading the live `#contexts` of each frame's node and\n * falling back to the context's default if no ancestor provides it.\n *\n * The owner chain is the render-call ancestry captured at frame push\n * (via `withActiveNode`) — independent of mount status. Effects/memos\n * capture their creation frame and re-establish it on re-fire, so\n * detached re-runs walk the same chain they would have at creation.\n */\nexport interface Context<T> {\n readonly id: symbol\n readonly defaultValue: T\n}\n\nexport function createContext<T>(): Context<T | undefined>\nexport function createContext<T>(defaultValue: T): Context<T>\nexport function createContext<T>(defaultValue?: T): Context<T | undefined> {\n return { defaultValue, id: Symbol(\"@zaly/tui/context\") }\n}\n\n/** Publish `value` for `ctx` on the active Owner. Persistent for the\n * Owner's lifetime. Descendants (in the render-call sense) that read\n * via `useContext` walk up the Owner chain and find it. */\nexport function provideContext<T>(ctx: Context<T>, value: T): void {\n const owner = activeOwnerStore.getStore()\n if (owner === undefined) {\n throw new Error(\"provideContext: no active Owner — call from a widget body / _render\")\n }\n owner.setContext(ctx.id, value)\n}\n\n/** Read the current value of `ctx`. Walks the Owner chain\n * (render-call ancestry, not mount tree). Returns the context's\n * default when no ancestor has provided a value. */\nexport function useContext<T>(ctx: Context<T>): T {\n for (let o = activeOwnerStore.getStore(); o !== undefined; o = o.parent) {\n const map = o.contexts\n if (map?.has(ctx.id)) return map.get(ctx.id) as T\n }\n return ctx.defaultValue\n}\n\n// ---- public types ----------------------------------------------------\n\n/** Brand tag: every accessor / setter returned by `signal` / `memo`\n * carries this symbol so `unwrap` can tell a reactive source from a\n * plain function-valued prop (label formatter, text callback, etc.). */\nconst REACTIVE = Symbol.for(\"@zaly/tui/reactive\")\n\nexport type Signal<T> = readonly [get: Accessor<T>, set: Setter<T>] & {\n readonly get: Accessor<T>\n readonly set: Setter<T>\n}\n\n/** A read-only reactive source. Branded so `isAccessor` can detect it\n * without false positives on arbitrary callables. */\nexport type Accessor<T> = (() => T) & { readonly [REACTIVE]: \"get\" }\n\n/** A signal setter. Same branding as `Accessor` (different tag) so a\n * setter isn't mistaken for an accessor by `unwrap`. */\nexport type Setter<T> = ((next: T | ((prev: T) => T)) => void) & { readonly [REACTIVE]: \"set\" }\n\n/** A widget prop that's either a literal value or a reactive accessor. */\nexport type Reactive<T> = T | Accessor<T>\n\n/** Runtime check: `true` when `v` was produced by `signal` / `memo`.\n * False for plain callables (text-content functions, label formatters).\n *\n * @internal */\nexport function isAccessor<T>(v: unknown): v is Accessor<T> {\n return typeof v === \"function\" && (v as { [REACTIVE]?: string })[REACTIVE] === \"get\"\n}\n\n/** Resolve a `Reactive<T>` to its current `T`. Call inside `_render`\n * so accessor reads subscribe the rendering node. Only brand-tagged\n * accessors are invoked — other function values pass through\n * untouched, so widgets whose `T` is itself a function type (label\n * formatters etc.) don't need a hand-rolled guard. */\nexport function unwrap<T>(v: Reactive<T>): T {\n return isAccessor<T>(v) ? v() : v\n}\n\nfunction brand<F extends (...args: any[]) => any>(fn: F, tag: \"get\"): Accessor<ReturnType<F>>\nfunction brand<F extends (...args: any[]) => any>(fn: F, tag: \"set\"): Setter<Parameters<F>[0]>\nfunction brand<F extends (...args: any[]) => any>(fn: F, tag: \"get\" | \"set\"): F {\n Object.defineProperty(fn, REACTIVE, {\n configurable: false,\n enumerable: false,\n value: tag,\n writable: false,\n })\n return fn\n}\n\n// ---- Owner -----------------------------------------------------------\n\n/**\n * Reactive ownership scope — bundles cleanups + provided contexts\n * scoped to a single widget body (or a `createRoot` headless scope).\n *\n * Owners form a chain via `parent` mirroring the call-time widget\n * nesting: when `widget()` is invoked inside another widget's body,\n * `createNode` creates the inner Owner with `parent =\n * activeOwnerStore.getStore()` (the outer widget's Owner). That chain\n * is what `useContext` walks.\n *\n * Owners are **not** bound to Nodes anymore — a widget's `createNode`\n * pairs the Owner with the constructed Node only through\n * `Node.once(\"unmount\", () => owner.dispose())`. Primitive Nodes\n * (`text`, `box`, …) don't get their own Owner; they share whatever\n * Owner created them.\n *\n * Use `onCleanup(cb)` to register cleanups against the active Owner.\n * Disposing the Owner runs them in reverse-registration order.\n *\n * @internal\n */\nexport class Owner {\n parent?: Owner\n #cleanups: (() => void)[] = []\n #contexts?: Map<symbol, unknown>\n #disposed = false\n\n constructor(parent?: Owner) {\n this.parent = parent\n }\n\n get disposed(): boolean {\n return this.#disposed\n }\n\n /** Live view of this Owner's provided contexts. Populated by\n * `provideContext`. Walked upward via `parent` by `useContext`. */\n get contexts(): ReadonlyMap<symbol, unknown> | undefined {\n return this.#contexts\n }\n\n setContext(id: symbol, value: unknown): void {\n ;(this.#contexts ??= new Map()).set(id, value)\n }\n\n /** Register a cleanup. Runs on `dispose()`. */\n addCleanup(fn: () => void): void {\n if (this.#disposed) {\n fn()\n return\n }\n this.#cleanups.push(fn)\n }\n\n /** Fire cleanups in reverse-registration order. Idempotent. */\n dispose(): void {\n if (this.#disposed) return\n this.#disposed = true\n for (let i = this.#cleanups.length - 1; i >= 0; i--) {\n try {\n this.#cleanups[i]()\n } catch (error) {\n // Don't let one bad cleanup poison the rest.\n // oxlint-disable-next-line no-console\n console.error(\"Owner cleanup threw:\", error)\n }\n }\n this.#cleanups = []\n this.#contexts = undefined\n }\n}\n\nconst activeOwnerStore = new AsyncLocalStorage<Owner | undefined>()\n\n/** Run `fn` as the `node`'s render pass. Signal reads inside subscribe\n * the node's tracking ctx; the ctx's `notify` is `node.invalidate`,\n * so any signal write that this render depended on invalidates the\n * node and clears its cache. Cleanups are registered against the\n * Node's `unmount` event.\n *\n * Does **not** push an Owner — primitive Nodes share whatever Owner\n * was active in their caller. Widget bodies install their own Owner\n * via `createNode` at construction time, which is when `useContext`\n * / `provideContext` / `effect` / `memo` care about the active scope.\n *\n * @internal */\nexport function withActiveNode<T>(node: Node, fn: () => T): T {\n return withTracking(getNodeTrackingCtx(node), fn)\n}\n\n/** Run `fn` with a pre-existing Owner restored. Used by `effect` /\n * `memo` to re-establish their creation-time owner chain on re-fire,\n * so `useContext` walks the same ancestry regardless of whether the\n * re-fire was triggered from inside or outside a render.\n *\n * @internal */\nexport function withOwner<T>(owner: Owner, fn: () => T): T {\n return activeOwnerStore.run(owner, fn)\n}\n\nfunction getNodeTrackingCtx(node: Node): TrackingCtx {\n let ctx = nodeCtx.get(node)\n if (ctx === undefined) {\n ctx = {\n notify: () => node.invalidate(),\n register: (cleanup) => {\n node.once(\"unmount\", cleanup)\n },\n }\n nodeCtx.set(node, ctx)\n }\n return ctx\n}\n\n/** Create a fresh Owner scope and run `fn` inside it. Returns\n * whatever `fn` returns. The Owner's parent is whatever was active at\n * the call site (or `undefined` at module top).\n *\n * The Owner is *not* auto-disposed — callers manage its lifetime via\n * the Owner returned alongside the result, or (more commonly) by\n * binding the Owner to a Node and disposing it on that Node's\n * unmount.\n *\n * Typical use is via a surface's function-shape `add(fn)` API which\n * wraps this internally:\n *\n * ```ts\n * ui.add(() => {\n * const [count, setCount] = signal(0)\n * onCleanup(() => console.log(\"gone\"))\n * return text(() => `count: ${count()}`)\n * })\n * ```\n *\n * For headless reactive scopes (tests, programmatic effects), call\n * `createRoot` directly:\n *\n * ```ts\n * const { result, owner } = createRoot(() => signal(0))\n * // ... use result ...\n * owner.dispose()\n * ```\n */\nexport function createRoot<T>(fn: (dispose: () => void) => T): T {\n const parent = activeOwnerStore.getStore()\n const owner = new Owner(parent)\n return withOwner(owner, () => fn(() => owner.dispose()))\n}\n\n/** Run `fn` inside a fresh Owner scope and bind the returned Node to\n * that scope — when the Node unmounts, the Owner disposes (firing\n * every `onCleanup`, tearing down every `effect` / `memo` /\n * `createAsync` registered in the body).\n *\n * This is what `widget()` calls under the hood: it's the per-instance\n * scope boundary. Surfaces also call it directly at their `add` /\n * `append` entry points so each appended subtree gets its own root.\n *\n * ```ts\n * ui.add(() => {\n * const [c, setC] = signal(0)\n * onCleanup(() => clearInterval(timer))\n * const timer = setInterval(() => setC(x => x + 1), 1000)\n * return text(() => `count: ${c()}`)\n * })\n * ```\n */\nexport function createNode<T extends Node>(fn: () => T): T {\n return createRoot((dispose) => fn().once(\"unmount\", dispose))\n}\n\n/** Register a cleanup against the active Owner. Fires when the Owner\n * disposes — i.e. when the widget body's `createNode` Node unmounts,\n * or when the surrounding `createRoot` is disposed.\n *\n * ```ts\n * function widgetBody() {\n * const id = setInterval(() => tick(), 1000)\n * onCleanup(() => clearInterval(id))\n * return box(…)\n * }\n * ```\n *\n * Throws if called outside any active Owner — the cleanup would\n * never fire and the caller is almost certainly mistaken. */\nexport function onCleanup(fn: () => void): void {\n const owner = activeOwnerStore.getStore()\n if (owner === undefined) {\n throw new Error(\"onCleanup: no active Owner — call from inside a widget body / createRoot\")\n }\n owner.addCleanup(fn)\n}\n\n/** Current Owner, or `undefined` outside any render. Captured by\n * effects/memos at creation time and restored on re-fire.\n *\n * @internal */\nexport function useActiveOwner(): Owner | undefined {\n return activeOwnerStore.getStore()\n}\n\n/** Whether we're currently executing inside `node`'s own render call\n * stack — i.e. this code path was reached synchronously (or via an\n * await preserved by `AsyncLocalStorage`) from `node`'s `withActiveNode`.\n *\n * Used by `invalidate()` to suppress *internal* cascades — e.g.\n * Markdown mutating its child Text inside its own `_render`. External\n * mutations (network callbacks, event handlers) run outside any\n * render's ALS scope, so this returns `false` for them and they emit\n * normally even when a render is in flight.\n *\n * @internal */\nexport function inRenderContextOf(node: Node): boolean {\n const active = activeCtx.getStore()\n return active !== undefined && active === nodeCtx.get(node)\n}\n\nconst nodeCtx = new WeakMap<Node, TrackingCtx>()\n\n// ---- signal ----------------------------------------------------------\n\n/**\n * Reactive value. Returns a `[get, set]` tuple that's also accessible\n * as `.get` / `.set` for destructure-skipping callers. Reads inside a\n * tracking context (node render, effect, memo) auto-subscribe; writes\n * notify every subscriber synchronously.\n *\n * ```ts\n * const [count, setCount] = signal(0)\n * setCount(1) // value form\n * setCount((prev) => prev + 1) // updater form\n * ```\n *\n * **Storing a function as a value — gotcha**: `set` interprets any\n * function argument as the *updater* form `(prev) => next`, calls it\n * with the current value, and stores the result. To store a function\n * value (e.g. a callable `StyleBuilder` or a handler ref), wrap with\n * the updater form so the call resolves to the function you wanted:\n *\n * ```ts\n * const [style, setStyle] = signal<StyleBuilder | undefined>(undefined)\n * setStyle(ctx.style) // ✗ stored as `ctx.style(undefined)` — a string\n * setStyle(() => ctx.style) // ✓ stored as the StyleBuilder itself\n * ```\n *\n * Same trap exists in Solid and React's `useState`. If you find\n * yourself reaching for it, also consider whether storing a *plain*\n * value (the underlying data, not the chain/builder) and recomputing\n * the function-y derivative inside a `memo` is cleaner — usually it\n * is.\n *\n * Equality is reference-based: `set(v)` where `v === current` skips\n * the notify. Wrap mutable values you want to \"publish\" in a fresh\n * object/array, or use a counter signal to force fan-out.\n */\nexport function signal<T>(\n initial: T,\n opts: { equals?: false | ((prev: T, next: T) => boolean) } = {}\n): Signal<T> {\n let value = initial\n const subs = new Set<() => void>()\n const equals = opts.equals === false ? () => false : (opts.equals ?? ((a, b) => a === b))\n\n const get = brand((): T => {\n const ctx = activeCtx.getStore()\n if (ctx && !subs.has(ctx.notify)) {\n subs.add(ctx.notify)\n ctx.register(() => subs.delete(ctx.notify))\n }\n return value\n }, \"get\")\n\n const set = brand((next: T | ((prev: T) => T)): void => {\n const resolved = typeof next === \"function\" ? (next as (prev: T) => T)(value) : next\n if (equals(value, resolved)) return\n value = resolved\n // Snapshot — subscribers may mutate the set while running.\n const snapshot = [...subs]\n for (const notify of snapshot) notify()\n }, \"set\")\n\n return Object.assign([get, set] as const, { get, set }) as Signal<T>\n}\n\n/**\n * Lift a plain value to an `Accessor<T>`. The returned function always\n * returns `value`, never tracks, never notifies — useful at the boundary\n * where a static value enters a tree that otherwise expects `Accessor<T>`.\n *\n * Branded so `isAccessor` reports `true` and downstream `unwrap` calls\n * resolve to a stable function call rather than treating the value as\n * a ctx-aware thunk.\n *\n * ```ts\n * // Component expects `Accessor<Theme>` deep in the tree:\n * <CodeBlock theme={toAccessor(myStaticTheme)} />\n * ```\n */\nexport function toAccessor<T>(fn: () => T): Accessor<T> {\n return brand(() => fn(), \"get\")\n}\n\n// ---- effect ----------------------------------------------------------\n\n/**\n * Run `fn` immediately, then re-run whenever a signal it read writes.\n * Returns a disposer that stops the effect and drops all tracked\n * subscriptions. Unlike node render, effect dependencies are re-tracked\n * from scratch on every run — reads that disappear from `fn` stop\n * triggering re-runs.\n *\n * ```ts\n * const dispose = effect(() => {\n * console.log(\"status is\", status())\n * })\n * // ...\n * dispose()\n * ```\n *\n * **Footgun**: don't write a signal from inside an effect that reads\n * the same signal — you'll loop. Writing unrelated signals is fine.\n */\nexport function effect(fn: () => void | (() => void)): () => void {\n let cleanups: (() => void)[] = []\n let disposed = false\n\n // Capture the Owner at creation time. Re-fires triggered by signal\n // writes run in the *writer's* ALS context, which has nothing to do\n // with where the effect was created. Restoring the captured Owner on\n // each run keeps `useContext` walking the same ancestry regardless\n // of who triggered the re-fire.\n const owner = useActiveOwner()\n\n const ctx: TrackingCtx = {\n notify: () => {\n if (disposed) return\n run()\n },\n register: (cleanup) => {\n cleanups.push(cleanup)\n },\n }\n\n const run = (): void => {\n // Fresh deps each run — unsubscribe from everything we saw last time.\n const old = cleanups\n cleanups = []\n for (const c of old) c()\n // oxlint-disable-next-line unicorn/consistent-function-scoping\n const tracked = (): void | (() => void) => withTracking(ctx, fn)\n const cleanup = owner !== undefined ? withOwner(owner, tracked) : tracked()\n if (typeof cleanup === \"function\") cleanups.push(cleanup)\n }\n\n // Auto-dispose on owner teardown. If there's no owner, the caller\n // owns the returned dispose function and is responsible for cleanup.\n const dispose = (): void => {\n if (disposed) return\n disposed = true\n for (const c of cleanups) c()\n cleanups = []\n }\n owner?.addCleanup(dispose)\n\n run()\n\n return dispose\n}\n\n// ---- memo ------------------------------------------------------------\n\n/**\n * Derived, cached signal. `fn` runs once eagerly; the cached value is\n * returned from the accessor. When any signal `fn` reads writes, the\n * memo recomputes and notifies its own subscribers — but only if the\n * new value differs from the cached one (reference equality).\n *\n * ```ts\n * const [value, setValue] = signal(0)\n * const pct = memo(() => Math.round(value() * 100))\n * text(({ style }) => `${pct()}%`) // subscribes to pct, not value\n * ```\n *\n * Returns an `Accessor<T>`, not a `[read, write]` tuple — memos are\n * read-only by construction.\n */\nexport function memo<T>(fn: () => T): Accessor<T> {\n const [get, set] = signal<T>(undefined as T)\n effect(() => {\n // Wrap in the updater form so `signal.set`'s `typeof === \"function\"`\n // detection always picks the outer closure, never `fn()`'s return\n // value. Without this, memoizing a callable `T` (e.g. a chainable\n // `StyleBuilder`) would cause `set` to invoke it as an updater and\n // cache the call result instead of the value itself.\n set(() => fn())\n })\n return get\n}\n\n// ---- signal store ----------------------------------------------------\n\n/**\n * Reactive struct with fine-grained, lazy per-field tracking.\n *\n * Reads:\n * - `store.foo` — tracked when called inside a tracking ctx; allocates\n * a signal for `foo` on first read.\n *\n * Writes:\n * - `store.foo = x` — direct assignment.\n * - `store({ foo: x, bar: y })` — partial patch (merge).\n * - `store(current => ({ foo: current.foo + 1 }))` — updater form;\n * the function receives the current plain state (untracked) and\n * returns a partial patch which is then merged.\n *\n * All writes are value-equality (`===`) gated; setting a field to its\n * current value is a no-op. The function-form updater receives the\n * underlying state object directly so reads inside it are NOT tracked\n * — exactly what an updater wants (\"compute next from current\").\n *\n * Spread (`{ ...store }`) yields the current values of every field via\n * the proxy's `ownKeys` + `getOwnPropertyDescriptor` traps. Be aware:\n * spreading inside a tracking ctx subscribes that ctx to every field\n * (one signal allocation per field). Outside a tracking ctx, spread is\n * cheap (no signal allocation).\n *\n * Implementation: an inner `state` object is the source of truth for\n * plain reads / spreads / the updater's `current`. A `sigs` map is a\n * lazy tracking layer; a key only gets a signal once it's read inside\n * a tracking ctx. Writes update `state` and notify the signal *if it\n * exists* — fields nobody subscribed to never allocate.\n */\nexport type SignalStore<T extends object> = T & {\n /** Apply a partial patch (merge), or call with an updater that\n * receives the current plain state (untracked) and returns a\n * partial to merge. Each field's signal short-circuits on value-\n * equality, so unchanged fields don't notify subscribers. */\n set: (patch: Partial<T> | ((current: T) => Partial<T>)) => void\n}\n\nexport function createStore<T extends object>(initial: T): SignalStore<T> {\n const state = { ...initial }\n const sigs = {} as { [K in keyof T]?: Signal<T[K]> }\n\n const ensure = <K extends keyof T>(key: K): Signal<T[K]> => (sigs[key] ??= signal(state[key]))\n\n const setKey = <K extends keyof T>(key: K, value: T[K]): void => {\n if (state[key] === value) return\n state[key] = value\n // Wrap in updater form so `signal.set`'s `typeof === \"function\"`\n // detection always picks the outer closure — necessary for storing\n // function-typed fields without `set` invoking them as updaters.\n sigs[key]?.set(() => value)\n }\n\n const set = (patch: Partial<T> | ((c: T) => Partial<T>)): void => {\n const p = typeof patch === \"function\" ? patch(state) : patch\n for (const k of Object.keys(p) as (keyof T)[]) {\n const v = p[k]\n setKey(k, v as T[typeof k])\n }\n }\n\n return new Proxy({} as object, {\n get(_, key) {\n if (key === \"set\") return set\n return ensure(key as keyof T).get()\n },\n getOwnPropertyDescriptor(_, key) {\n if (!Object.hasOwn(state, key)) return undefined\n return {\n configurable: true,\n enumerable: true,\n value: state[key as keyof T],\n }\n },\n has(_, key) {\n return key === \"set\" || (key as keyof T) in state\n },\n ownKeys() {\n return Reflect.ownKeys(state)\n },\n set(_, key, value) {\n setKey(key as keyof T, value as T[keyof T])\n return true\n },\n }) as SignalStore<T>\n}\n\n// ---- suspense --------------------------------------------------------\n\n/**\n * Suspense boundary handle — the value of `SuspenseContext`. Consumers\n * (`createAsync`) call `increment` / `decrement` around in-flight work\n * so providers (Stream's append, a `suspense()` widget) can observe\n * \"is anything pending below me\".\n *\n * Boundaries chain: when a `suspense()` body installs its own boundary,\n * its `parent` is the nearest ancestor boundary. Count flips at the\n * 0→1 and 1→0 transitions propagate to the parent, so the outermost\n * boundary's count is `> 0` iff *any* descendant has pending work —\n * a single integer, no walks.\n *\n * `whenIdle` resolves when count returns to 0. Used by Stream to gate\n * paint on resolved async; could be used by any other \"wait for\n * subtree to settle\" caller.\n */\nexport type SuspenseBoundary = {\n increment: () => void\n decrement: () => void\n active: () => boolean\n whenIdle: () => Promise<void>\n}\n\n/** Nearest Suspense provider in the Owner chain. `undefined` when no\n * boundary is installed — `createAsync` runs fire-and-forget in that\n * case (signal resolves later, normal invalidation re-renders). */\nexport const SuspenseContext = createContext<SuspenseBoundary | undefined>(undefined)\n\n/**\n * Build a boundary whose count flips propagate to `parent` on the 0→1\n * and 1→0 transitions. Used by Stream's `append` and the `suspense()`\n * widget. Internal-ish — most callers shouldn't construct boundaries\n * directly.\n *\n * @internal\n */\nexport function createSuspenseBoundary(parent?: SuspenseBoundary): SuspenseBoundary {\n let count = 0\n let idle: { promise: Promise<void>; resolve: () => void } | undefined\n return {\n active: () => count > 0,\n decrement: () => {\n if (count === 0) return\n count--\n if (count === 0) {\n parent?.decrement()\n idle?.resolve()\n idle = undefined\n }\n },\n increment: () => {\n count++\n if (count === 1) parent?.increment()\n },\n whenIdle: () => {\n if (count === 0) return Promise.resolve()\n if (idle === undefined) {\n const { promise, resolve } = Promise.withResolvers<void>()\n idle = { promise, resolve }\n }\n return idle.promise\n },\n }\n}\n\n// ---- async -----------------------------------------------------------\n\n/**\n * Resource-style async accessor. `fn` reads signals (tracked); the\n * effect re-fires when any of them change. Each run notifies the\n * nearest `SuspenseContext` so a surrounding boundary (Stream's\n * append, a `suspense()` widget) can observe pending work.\n *\n * ```ts\n * const highlighted = createAsync(\n * async (prev) => highlight(unwrap(props.code)),\n * { initialValue: unwrap(props.code) },\n * )\n * text(highlighted)\n * ```\n *\n * **Stale-write protection**: each run bumps a generation counter;\n * late `.then` callbacks check it and skip `setValue` if a newer run\n * has already fired. The boundary is decremented exactly once per\n * increment (in the settle callback, regardless of staleness).\n *\n * **`prev`** is the previously resolved value (or `initialValue`) —\n * useful for diff-based fetches. Reading it does *not* track, so\n * resolving the new value won't re-fire the effect.\n *\n * **No active boundary** → increment/decrement no-op, work is\n * fire-and-forget. Right for UI surface widgets that re-render\n * cheaply on signal change. The Stream surface installs a boundary\n * per appended subtree so committed-to-scrollback rows always reflect\n * resolved values.\n */\nexport function createAsync<T>(\n fn: (prev: T | undefined) => Promise<T>,\n opts: { initialValue: T }\n): Accessor<T>\nexport function createAsync<T>(\n fn: (prev: T | undefined) => Promise<T>,\n opts?: { initialValue?: T }\n): Accessor<T | undefined>\nexport function createAsync<T>(\n fn: (prev: T | undefined) => Promise<T>,\n opts?: { initialValue?: T }\n): Accessor<T | undefined> {\n const [value, setValue] = signal<T | undefined>(opts?.initialValue)\n const suspense = useContext(SuspenseContext)\n let gen = 0\n effect(() => {\n const my = ++gen\n let p: Promise<T>\n try {\n p = fn(untrack(value))\n } catch (error) {\n // Sync throw inside `fn` — surface as a rejected promise so the\n // boundary increment / decrement path stays uniform.\n p = Promise.reject(error as Error)\n }\n suspense?.increment()\n p.then(\n (v) => {\n if (my === gen) setValue(() => v)\n },\n () => {\n // Swallow — async failures leave the previous (or initial)\n // value in place.\n }\n ).finally(() => suspense?.decrement())\n })\n return value\n}\n\nexport type Progressive<T> = Accessor<T> & {\n readonly loading: Accessor<boolean>\n whenIdle: () => Promise<void>\n}\n\nexport function createProgressive<T>(\n fn: (ctx: { signal: AbortSignal; set: (value: T) => void }) => MaybePromise<T>,\n opts: { throttle?: number; initialValue: T }\n): Progressive<T>\nexport function createProgressive<T>(\n fn: (ctx: { signal: AbortSignal; set: (value: T) => void }) => MaybePromise<T>,\n opts: { throttle?: number; initialValue?: T }\n): Progressive<T | undefined>\nexport function createProgressive<T>(\n fn: (ctx: { signal: AbortSignal; set: (value: T) => void }) => MaybePromise<T>,\n opts: { throttle?: number; initialValue?: T } = {}\n): Progressive<T | undefined> {\n const throttle = opts.throttle ?? 16\n const [loading, setLoading] = signal(true)\n const [state, setState] = signal<T | undefined>(opts.initialValue, { equals: false })\n\n const ret: Progressive<T | undefined> = Object.assign(state, {\n get loading() {\n return loading\n },\n whenIdle: () => {\n if (!loading()) return Promise.resolve()\n idle ??= Promise.withResolvers<void>()\n return idle.promise\n },\n })\n\n let gen = 0\n let idle: ReturnType<typeof Promise.withResolvers<void>> | undefined\n\n effect(() => {\n const my = ++gen\n const ac = new AbortController()\n\n void (async () => {\n try {\n setLoading(true)\n let prev = 0\n const result = await fn({\n set: (value: T) => {\n if (ac.signal.aborted || my !== gen) return\n const now = performance.now()\n if (now - prev >= throttle) {\n prev = now\n setState(() => value)\n }\n },\n signal: ac.signal,\n })\n if (my === gen) {\n setState(() => result)\n setLoading(false)\n idle?.resolve()\n idle = undefined\n }\n } catch (error) {\n if (my === gen) {\n setLoading(false)\n idle?.reject(error)\n idle = undefined\n }\n } finally {\n ac.abort()\n }\n })()\n\n return () => {\n ac.abort()\n }\n })\n\n return ret\n}\n\nexport function createIterable<T>(\n fn: (ctx: { signal: AbortSignal }) => AsyncIterable<T | readonly T[]>,\n opts: { throttle?: number; initialValue?: readonly T[] } = {}\n): Progressive<readonly T[]> {\n return createProgressive(\n async ({ signal: s, set }) => {\n const results: T[] = []\n for await (const item of fn({ signal: s })) {\n if (s.aborted) return results\n results.push(...(Array.isArray(item) ? item : [item]))\n set(results)\n }\n return results\n },\n { ...opts, initialValue: opts.initialValue ?? [] }\n )\n}\n\nexport interface Ref<T> {\n (): T\n get value(): T | undefined\n set value(value: T)\n}\n\nexport function createRef<T>(\n value?: T,\n opts: { onSet?: (value: T, prev: T | undefined) => void | (() => void) } = {}\n): Ref<T> {\n let current = value\n let cleanup: (() => void) | undefined\n\n const get = (): T => {\n if (current === undefined) throw new Error(\"Ref value accessed before initialization\")\n return current\n }\n\n Object.defineProperty(get, \"value\", {\n get: () => current,\n set: (v: T) => {\n if (current === v) return\n cleanup?.()\n cleanup = undefined\n const prev = current\n current = v\n cleanup = opts.onSet?.(v, prev) ?? undefined\n },\n })\n\n return get as Ref<T>\n}\n"],"mappings":";;AA0CA,MAAM,YAAY,IAAI,kBAA2C;AAEjE,SAAS,aAAgB,KAAkB,IAAgB;CACzD,OAAO,UAAU,IAAI,KAAK,EAAE;AAC9B;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,QAAW,IAAgB;CACzC,OAAO,UAAU,IAAI,KAAA,GAAW,EAAE;AACpC;;;AAIA,SAAgB,KAAQ,GAAmB;CACzC,OAAO,cAAc,OAAO,CAAC,CAAC;AAChC;AAoCA,SAAgB,cAAiB,cAA0C;CACzE,OAAO;EAAE;EAAc,IAAI,OAAO,mBAAmB;CAAE;AACzD;;;;AAKA,SAAgB,eAAkB,KAAiB,OAAgB;CACjE,MAAM,QAAQ,iBAAiB,SAAS;CACxC,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,qEAAqE;CAEvF,MAAM,WAAW,IAAI,IAAI,KAAK;AAChC;;;;AAKA,SAAgB,WAAc,KAAoB;CAChD,KAAK,IAAI,IAAI,iBAAiB,SAAS,GAAG,MAAM,KAAA,GAAW,IAAI,EAAE,QAAQ;EACvE,MAAM,MAAM,EAAE;EACd,IAAI,KAAK,IAAI,IAAI,EAAE,GAAG,OAAO,IAAI,IAAI,IAAI,EAAE;CAC7C;CACA,OAAO,IAAI;AACb;;;;AAOA,MAAM,WAAW,OAAO,IAAI,oBAAoB;;;;;AAsBhD,SAAgB,WAAc,GAA8B;CAC1D,OAAO,OAAO,MAAM,cAAe,EAA8B,cAAc;AACjF;;;;;;AAOA,SAAgB,OAAU,GAAmB;CAC3C,OAAO,WAAc,CAAC,IAAI,EAAE,IAAI;AAClC;AAIA,SAAS,MAAyC,IAAO,KAAuB;CAC9E,OAAO,eAAe,IAAI,UAAU;EAClC,cAAc;EACd,YAAY;EACZ,OAAO;EACP,UAAU;CACZ,CAAC;CACD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;AAyBA,IAAa,QAAb,MAAmB;CACjB;CACA,YAA4B,CAAC;CAC7B;CACA,YAAY;CAEZ,YAAY,QAAgB;EAC1B,KAAK,SAAS;CAChB;CAEA,IAAI,WAAoB;EACtB,OAAO,KAAK;CACd;;;CAIA,IAAI,WAAqD;EACvD,OAAO,KAAK;CACd;CAEA,WAAW,IAAY,OAAsB;EAC1C,CAAC,KAAK,8BAAc,IAAI,IAAI,EAAA,CAAG,IAAI,IAAI,KAAK;CAC/C;;CAGA,WAAW,IAAsB;EAC/B,IAAI,KAAK,WAAW;GAClB,GAAG;GACH;EACF;EACA,KAAK,UAAU,KAAK,EAAE;CACxB;;CAGA,UAAgB;EACd,IAAI,KAAK,WAAW;EACpB,KAAK,YAAY;EACjB,KAAK,IAAI,IAAI,KAAK,UAAU,SAAS,GAAG,KAAK,GAAG,KAC9C,IAAI;GACF,KAAK,UAAU,EAAE,CAAC;EACpB,SAAS,OAAO;GAGd,QAAQ,MAAM,wBAAwB,KAAK;EAC7C;EAEF,KAAK,YAAY,CAAC;EAClB,KAAK,YAAY,KAAA;CACnB;AACF;AAEA,MAAM,mBAAmB,IAAI,kBAAqC;;;;;;;;;;;;;AAclE,SAAgB,eAAkB,MAAY,IAAgB;CAC5D,OAAO,aAAa,mBAAmB,IAAI,GAAG,EAAE;AAClD;;;;;;;AAQA,SAAgB,UAAa,OAAc,IAAgB;CACzD,OAAO,iBAAiB,IAAI,OAAO,EAAE;AACvC;AAEA,SAAS,mBAAmB,MAAyB;CACnD,IAAI,MAAM,QAAQ,IAAI,IAAI;CAC1B,IAAI,QAAQ,KAAA,GAAW;EACrB,MAAM;GACJ,cAAc,KAAK,WAAW;GAC9B,WAAW,YAAY;IACrB,KAAK,KAAK,WAAW,OAAO;GAC9B;EACF;EACA,QAAQ,IAAI,MAAM,GAAG;CACvB;CACA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,WAAc,IAAmC;CAE/D,MAAM,QAAQ,IAAI,MADH,iBAAiB,SACR,CAAM;CAC9B,OAAO,UAAU,aAAa,SAAS,MAAM,QAAQ,CAAC,CAAC;AACzD;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,WAA2B,IAAgB;CACzD,OAAO,YAAY,YAAY,GAAG,CAAC,CAAC,KAAK,WAAW,OAAO,CAAC;AAC9D;;;;;;;;;;;;;;;AAgBA,SAAgB,UAAU,IAAsB;CAC9C,MAAM,QAAQ,iBAAiB,SAAS;CACxC,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,0EAA0E;CAE5F,MAAM,WAAW,EAAE;AACrB;;;;;AAMA,SAAgB,iBAAoC;CAClD,OAAO,iBAAiB,SAAS;AACnC;;;;;;;;;;;;AAaA,SAAgB,kBAAkB,MAAqB;CACrD,MAAM,SAAS,UAAU,SAAS;CAClC,OAAO,WAAW,KAAA,KAAa,WAAW,QAAQ,IAAI,IAAI;AAC5D;AAEA,MAAM,0BAAU,IAAI,QAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsC/C,SAAgB,OACd,SACA,OAA6D,CAAC,GACnD;CACX,IAAI,QAAQ;CACZ,MAAM,uBAAO,IAAI,IAAgB;CACjC,MAAM,SAAS,KAAK,WAAW,cAAc,QAAS,KAAK,YAAY,GAAG,MAAM,MAAM;CAEtF,MAAM,MAAM,YAAe;EACzB,MAAM,MAAM,UAAU,SAAS;EAC/B,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,MAAM,GAAG;GAChC,KAAK,IAAI,IAAI,MAAM;GACnB,IAAI,eAAe,KAAK,OAAO,IAAI,MAAM,CAAC;EAC5C;EACA,OAAO;CACT,GAAG,KAAK;CAER,MAAM,MAAM,OAAO,SAAqC;EACtD,MAAM,WAAW,OAAO,SAAS,aAAc,KAAwB,KAAK,IAAI;EAChF,IAAI,OAAO,OAAO,QAAQ,GAAG;EAC7B,QAAQ;EAER,MAAM,WAAW,CAAC,GAAG,IAAI;EACzB,KAAK,MAAM,UAAU,UAAU,OAAO;CACxC,GAAG,KAAK;CAER,OAAO,OAAO,OAAO,CAAC,KAAK,GAAG,GAAY;EAAE;EAAK;CAAI,CAAC;AACxD;;;;;;;;;;;;;;;AAgBA,SAAgB,WAAc,IAA0B;CACtD,OAAO,YAAY,GAAG,GAAG,KAAK;AAChC;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,OAAO,IAA2C;CAChE,IAAI,WAA2B,CAAC;CAChC,IAAI,WAAW;CAOf,MAAM,QAAQ,eAAe;CAE7B,MAAM,MAAmB;EACvB,cAAc;GACZ,IAAI,UAAU;GACd,IAAI;EACN;EACA,WAAW,YAAY;GACrB,SAAS,KAAK,OAAO;EACvB;CACF;CAEA,MAAM,YAAkB;EAEtB,MAAM,MAAM;EACZ,WAAW,CAAC;EACZ,KAAK,MAAM,KAAK,KAAK,EAAE;EAEvB,MAAM,gBAAqC,aAAa,KAAK,EAAE;EAC/D,MAAM,UAAU,UAAU,KAAA,IAAY,UAAU,OAAO,OAAO,IAAI,QAAQ;EAC1E,IAAI,OAAO,YAAY,YAAY,SAAS,KAAK,OAAO;CAC1D;CAIA,MAAM,gBAAsB;EAC1B,IAAI,UAAU;EACd,WAAW;EACX,KAAK,MAAM,KAAK,UAAU,EAAE;EAC5B,WAAW,CAAC;CACd;CACA,OAAO,WAAW,OAAO;CAEzB,IAAI;CAEJ,OAAO;AACT;;;;;;;;;;;;;;;;AAmBA,SAAgB,KAAQ,IAA0B;CAChD,MAAM,CAAC,KAAK,OAAO,OAAU,KAAA,CAAc;CAC3C,aAAa;EAMX,UAAU,GAAG,CAAC;CAChB,CAAC;CACD,OAAO;AACT;AA2CA,SAAgB,YAA8B,SAA4B;CACxE,MAAM,QAAQ,EAAE,GAAG,QAAQ;CAC3B,MAAM,OAAO,CAAC;CAEd,MAAM,UAA6B,QAA0B,KAAK,SAAS,OAAO,MAAM,IAAI;CAE5F,MAAM,UAA6B,KAAQ,UAAsB;EAC/D,IAAI,MAAM,SAAS,OAAO;EAC1B,MAAM,OAAO;EAIb,KAAK,IAAI,EAAE,UAAU,KAAK;CAC5B;CAEA,MAAM,OAAO,UAAqD;EAChE,MAAM,IAAI,OAAO,UAAU,aAAa,MAAM,KAAK,IAAI;EACvD,KAAK,MAAM,KAAK,OAAO,KAAK,CAAC,GAAkB;GAC7C,MAAM,IAAI,EAAE;GACZ,OAAO,GAAG,CAAgB;EAC5B;CACF;CAEA,OAAO,IAAI,MAAM,CAAC,GAAa;EAC7B,IAAI,GAAG,KAAK;GACV,IAAI,QAAQ,OAAO,OAAO;GAC1B,OAAO,OAAO,GAAc,CAAC,CAAC,IAAI;EACpC;EACA,yBAAyB,GAAG,KAAK;GAC/B,IAAI,CAAC,OAAO,OAAO,OAAO,GAAG,GAAG,OAAO,KAAA;GACvC,OAAO;IACL,cAAc;IACd,YAAY;IACZ,OAAO,MAAM;GACf;EACF;EACA,IAAI,GAAG,KAAK;GACV,OAAO,QAAQ,SAAU,OAAmB;EAC9C;EACA,UAAU;GACR,OAAO,QAAQ,QAAQ,KAAK;EAC9B;EACA,IAAI,GAAG,KAAK,OAAO;GACjB,OAAO,KAAgB,KAAmB;GAC1C,OAAO;EACT;CACF,CAAC;AACH;;;;AA8BA,MAAa,kBAAkB,cAA4C,KAAA,CAAS;;;;;;;;;AAUpF,SAAgB,uBAAuB,QAA6C;CAClF,IAAI,QAAQ;CACZ,IAAI;CACJ,OAAO;EACL,cAAc,QAAQ;EACtB,iBAAiB;GACf,IAAI,UAAU,GAAG;GACjB;GACA,IAAI,UAAU,GAAG;IACf,QAAQ,UAAU;IAClB,MAAM,QAAQ;IACd,OAAO,KAAA;GACT;EACF;EACA,iBAAiB;GACf;GACA,IAAI,UAAU,GAAG,QAAQ,UAAU;EACrC;EACA,gBAAgB;GACd,IAAI,UAAU,GAAG,OAAO,QAAQ,QAAQ;GACxC,IAAI,SAAS,KAAA,GAAW;IACtB,MAAM,EAAE,SAAS,YAAY,QAAQ,cAAoB;IACzD,OAAO;KAAE;KAAS;IAAQ;GAC5B;GACA,OAAO,KAAK;EACd;CACF;AACF;AAyCA,SAAgB,YACd,IACA,MACyB;CACzB,MAAM,CAAC,OAAO,YAAY,OAAsB,MAAM,YAAY;CAClE,MAAM,WAAW,WAAW,eAAe;CAC3C,IAAI,MAAM;CACV,aAAa;EACX,MAAM,KAAK,EAAE;EACb,IAAI;EACJ,IAAI;GACF,IAAI,GAAG,QAAQ,KAAK,CAAC;EACvB,SAAS,OAAO;GAGd,IAAI,QAAQ,OAAO,KAAc;EACnC;EACA,UAAU,UAAU;EACpB,EAAE,MACC,MAAM;GACL,IAAI,OAAO,KAAK,eAAe,CAAC;EAClC,SACM,CAGN,CACF,CAAC,CAAC,cAAc,UAAU,UAAU,CAAC;CACvC,CAAC;CACD,OAAO;AACT;AAeA,SAAgB,kBACd,IACA,OAAgD,CAAC,GACrB;CAC5B,MAAM,WAAW,KAAK,YAAY;CAClC,MAAM,CAAC,SAAS,cAAc,OAAO,IAAI;CACzC,MAAM,CAAC,OAAO,YAAY,OAAsB,KAAK,cAAc,EAAE,QAAQ,MAAM,CAAC;CAEpF,MAAM,MAAkC,OAAO,OAAO,OAAO;EAC3D,IAAI,UAAU;GACZ,OAAO;EACT;EACA,gBAAgB;GACd,IAAI,CAAC,QAAQ,GAAG,OAAO,QAAQ,QAAQ;GACvC,SAAS,QAAQ,cAAoB;GACrC,OAAO,KAAK;EACd;CACF,CAAC;CAED,IAAI,MAAM;CACV,IAAI;CAEJ,aAAa;EACX,MAAM,KAAK,EAAE;EACb,MAAM,KAAK,IAAI,gBAAgB;EAE/B,CAAM,YAAY;GAChB,IAAI;IACF,WAAW,IAAI;IACf,IAAI,OAAO;IACX,MAAM,SAAS,MAAM,GAAG;KACtB,MAAM,UAAa;MACjB,IAAI,GAAG,OAAO,WAAW,OAAO,KAAK;MACrC,MAAM,MAAM,YAAY,IAAI;MAC5B,IAAI,MAAM,QAAQ,UAAU;OAC1B,OAAO;OACP,eAAe,KAAK;MACtB;KACF;KACA,QAAQ,GAAG;IACb,CAAC;IACD,IAAI,OAAO,KAAK;KACd,eAAe,MAAM;KACrB,WAAW,KAAK;KAChB,MAAM,QAAQ;KACd,OAAO,KAAA;IACT;GACF,SAAS,OAAO;IACd,IAAI,OAAO,KAAK;KACd,WAAW,KAAK;KAChB,MAAM,OAAO,KAAK;KAClB,OAAO,KAAA;IACT;GACF,UAAU;IACR,GAAG,MAAM;GACX;EACF,EAAA,CAAG;EAEH,aAAa;GACX,GAAG,MAAM;EACX;CACF,CAAC;CAED,OAAO;AACT;AAEA,SAAgB,eACd,IACA,OAA2D,CAAC,GACjC;CAC3B,OAAO,kBACL,OAAO,EAAE,QAAQ,GAAG,UAAU;EAC5B,MAAM,UAAe,CAAC;EACtB,WAAW,MAAM,QAAQ,GAAG,EAAE,QAAQ,EAAE,CAAC,GAAG;GAC1C,IAAI,EAAE,SAAS,OAAO;GACtB,QAAQ,KAAK,GAAI,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI,CAAE;GACrD,IAAI,OAAO;EACb;EACA,OAAO;CACT,GACA;EAAE,GAAG;EAAM,cAAc,KAAK,gBAAgB,CAAC;CAAE,CACnD;AACF;AAQA,SAAgB,UACd,OACA,OAA2E,CAAC,GACpE;CACR,IAAI,UAAU;CACd,IAAI;CAEJ,MAAM,YAAe;EACnB,IAAI,YAAY,KAAA,GAAW,MAAM,IAAI,MAAM,0CAA0C;EACrF,OAAO;CACT;CAEA,OAAO,eAAe,KAAK,SAAS;EAClC,WAAW;EACX,MAAM,MAAS;GACb,IAAI,YAAY,GAAG;GACnB,UAAU;GACV,UAAU,KAAA;GACV,MAAM,OAAO;GACb,UAAU;GACV,UAAU,KAAK,QAAQ,GAAG,IAAI,KAAK,KAAA;EACrC;CACF,CAAC;CAED,OAAO;AACT"}