@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.
- package/assets/schemas/shiki-language.schema.json +352 -0
- package/assets/schemas/shiki-theme.schema.json +71 -0
- package/assets/schemas/theme.schema.json +226 -1046
- package/assets/themes/andromeeda.json +97 -0
- package/assets/themes/ayu-dark.json +31 -25
- package/assets/themes/ayu-light.json +106 -0
- package/assets/themes/ayu-mirage.json +106 -0
- package/assets/themes/catppuccin-frappe.json +43 -40
- package/assets/themes/catppuccin-latte.json +43 -40
- package/assets/themes/catppuccin-macchiato.json +43 -40
- package/assets/themes/catppuccin-mocha.json +43 -40
- package/assets/themes/dark-plus.json +99 -0
- package/assets/themes/dracula.json +47 -47
- package/assets/themes/everforest-dark.json +28 -26
- package/assets/themes/everforest-light.json +28 -26
- package/assets/themes/github-dark-default.json +107 -0
- package/assets/themes/github-dark-dimmed.json +107 -0
- package/assets/themes/github-light-default.json +107 -0
- package/assets/themes/gruvbox-dark-hard.json +98 -0
- package/assets/themes/gruvbox-dark-medium.json +34 -29
- package/assets/themes/gruvbox-light-medium.json +98 -0
- package/assets/themes/horizon-bright.json +101 -0
- package/assets/themes/horizon.json +101 -0
- package/assets/themes/iterm2/LICENSE +25 -0
- package/assets/themes/iterm2/README.md +28 -0
- package/assets/themes/iterm2/catppuccin-latte.json +140 -0
- package/assets/themes/iterm2/catppuccin-mocha.json +140 -0
- package/assets/themes/iterm2/github-dark.json +140 -0
- package/assets/themes/iterm2/github.json +140 -0
- package/assets/themes/iterm2/gruvbox-dark.json +140 -0
- package/assets/themes/iterm2/gruvbox-light.json +140 -0
- package/assets/themes/iterm2/nord.json +140 -0
- package/assets/themes/iterm2/tokyonight-day.json +140 -0
- package/assets/themes/iterm2/tokyonight-moon.json +140 -0
- package/assets/themes/kanagawa-dragon.json +55 -49
- package/assets/themes/kanagawa-lotus.json +105 -0
- package/assets/themes/kanagawa-wave.json +56 -50
- package/assets/themes/light-plus.json +99 -0
- package/assets/themes/material-theme-lighter.json +102 -0
- package/assets/themes/material-theme-palenight.json +52 -45
- package/assets/themes/material-theme.json +102 -0
- package/assets/themes/min-dark.json +69 -14
- package/assets/themes/min-light.json +68 -17
- package/assets/themes/monokai.json +54 -47
- package/assets/themes/night-owl-light.json +105 -0
- package/assets/themes/night-owl.json +57 -49
- package/assets/themes/nord.json +53 -39
- package/assets/themes/one-dark-pro.json +46 -38
- package/assets/themes/one-light.json +52 -41
- package/assets/themes/poimandres.json +51 -49
- package/assets/themes/rose-pine-dawn.json +99 -0
- package/assets/themes/rose-pine-moon.json +99 -0
- package/assets/themes/rose-pine.json +50 -33
- package/assets/themes/solarized-dark.json +38 -31
- package/assets/themes/solarized-light.json +40 -33
- package/assets/themes/synthwave-84.json +47 -30
- package/assets/themes/tokyonight-day.json +3 -3
- package/assets/themes/tokyonight-moon.json +3 -2
- package/assets/themes/tokyonight-night.json +3 -2
- package/assets/themes/tokyonight-storm.json +3 -2
- package/assets/themes/vesper.json +50 -42
- package/assets/themes/vitesse-black.json +103 -0
- package/assets/themes/vitesse-dark.json +26 -30
- package/assets/themes/vitesse-light.json +26 -30
- package/dist/{actions-DEIKF2ts.mjs → actions-AY6avfEV.mjs} +2 -3
- package/dist/{actions-DEIKF2ts.mjs.map → actions-AY6avfEV.mjs.map} +1 -1
- package/dist/{actions-Dc4D4uSf.d.mts → actions-B0yyZ-Ww.d.mts} +4 -6
- package/dist/actions-B0yyZ-Ww.d.mts.map +1 -0
- package/dist/{ansi-DZlXaItJ.mjs → ansi-CxgRPLA2.mjs} +4 -33
- package/dist/ansi-CxgRPLA2.mjs.map +1 -0
- package/dist/ansi.d.mts +1 -3
- package/dist/ansi.d.mts.map +1 -1
- package/dist/ansi.mjs +1 -1
- package/dist/{autocomplete-StW1QJZJ.d.mts → autocomplete-wgceuhLr.d.mts} +5 -7
- package/dist/autocomplete-wgceuhLr.d.mts.map +1 -0
- package/dist/{box-BkP4MF82.mjs → box-DToDoXlU.mjs} +8 -10
- package/dist/{box-BkP4MF82.mjs.map → box-DToDoXlU.mjs.map} +1 -1
- package/dist/builder-BdYlK1Ew.mjs +195 -0
- package/dist/builder-BdYlK1Ew.mjs.map +1 -0
- package/dist/{callbacks-BwWTCqPJ.mjs → callbacks-DW8XKYKy.mjs} +9 -13
- package/dist/{callbacks-BwWTCqPJ.mjs.map → callbacks-DW8XKYKy.mjs.map} +1 -1
- package/dist/{client-C2GXKfJ1.mjs → client-BWm6dNZF.mjs} +9 -6
- package/dist/client-BWm6dNZF.mjs.map +1 -0
- package/dist/client-C69qWhMG.mjs +1 -0
- package/dist/{clipboard-CNPBTX7j.mjs → clipboard-UEoX9sup.mjs} +2 -3
- package/dist/{clipboard-CNPBTX7j.mjs.map → clipboard-UEoX9sup.mjs.map} +1 -1
- package/dist/clipboard.d.mts +0 -2
- package/dist/clipboard.d.mts.map +1 -1
- package/dist/clipboard.mjs +1 -1
- package/dist/color-Cr1VoL49.mjs +36 -0
- package/dist/color-Cr1VoL49.mjs.map +1 -0
- package/dist/ctx-CYEzzH-7.mjs +1 -0
- package/dist/{ctx-B7BmPUCD.mjs → ctx-DBeFcZt6.mjs} +4 -5
- package/dist/{ctx-B7BmPUCD.mjs.map → ctx-DBeFcZt6.mjs.map} +1 -1
- package/dist/{divider-TSx9NhI_.mjs → divider-qEj5prKE.mjs} +3 -4
- package/dist/{divider-TSx9NhI_.mjs.map → divider-qEj5prKE.mjs.map} +1 -1
- package/dist/{files-BvThQpOf.mjs → files-C3ZnFpvq.mjs} +3 -4
- package/dist/{files-BvThQpOf.mjs.map → files-C3ZnFpvq.mjs.map} +1 -1
- package/dist/{files-7DUYSeNc.d.mts → files-CdiDnwA_.d.mts} +3 -5
- package/dist/files-CdiDnwA_.d.mts.map +1 -0
- package/dist/{flex-Bguo-fUe.mjs → flex-CYp4etqn.mjs} +3 -4
- package/dist/{flex-Bguo-fUe.mjs.map → flex-CYp4etqn.mjs.map} +1 -1
- package/dist/{github-Cy2hfWJ7.mjs → github-CLveT9mq.mjs} +2 -3
- package/dist/{github-Cy2hfWJ7.mjs.map → github-CLveT9mq.mjs.map} +1 -1
- package/dist/{github-C1KfXk98.d.mts → github-DC0XemKa.d.mts} +3 -5
- package/dist/github-DC0XemKa.d.mts.map +1 -0
- package/dist/{image-VaT7AN-S.d.mts → image-DdRDv7q6.d.mts} +2 -4
- package/dist/image-DdRDv7q6.d.mts.map +1 -0
- package/dist/image-M--Bw4bs.mjs +177 -0
- package/dist/image-M--Bw4bs.mjs.map +1 -0
- package/dist/image.d.mts +1 -3
- package/dist/image.d.mts.map +1 -1
- package/dist/image.mjs +1 -1
- package/dist/index.d.mts +11 -14
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +12 -14
- package/dist/index.mjs.map +1 -1
- package/dist/{input-BGTTujDN.mjs → input-BkE4EpBw.mjs} +6 -7
- package/dist/{input-BGTTujDN.mjs.map → input-BkE4EpBw.mjs.map} +1 -1
- package/dist/{input-BAYux7qo.d.mts → input-C3kfYoEJ.d.mts} +3 -5
- package/dist/input-C3kfYoEJ.d.mts.map +1 -0
- package/dist/{inspect-jG_W4njH.mjs → inspect-Cli1beu8.mjs} +3 -4
- package/dist/{inspect-jG_W4njH.mjs.map → inspect-Cli1beu8.mjs.map} +1 -1
- package/dist/{inspect-CfNydMgO.d.mts → inspect-hSl3U2BD.d.mts} +2 -6
- package/dist/inspect-hSl3U2BD.d.mts.map +1 -0
- package/dist/kitty-0sJ8axU_.mjs +1 -0
- package/dist/{kitty-JbCJC0iQ.mjs → kitty-BH_eK6lz.mjs} +2 -3
- package/dist/{kitty-JbCJC0iQ.mjs.map → kitty-BH_eK6lz.mjs.map} +1 -1
- package/dist/{log-ByKlM4iI.mjs → log-96b1_J6G.mjs} +6 -7
- package/dist/{log-ByKlM4iI.mjs.map → log-96b1_J6G.mjs.map} +1 -1
- package/dist/{logger-DSQb0sLP.mjs → logger-DwfXp8LF.mjs} +5 -6
- package/dist/{logger-DSQb0sLP.mjs.map → logger-DwfXp8LF.mjs.map} +1 -1
- package/dist/{markdown-CwRmWuU6.mjs → markdown-CgRZBhIX.mjs} +12 -12
- package/dist/markdown-CgRZBhIX.mjs.map +1 -0
- package/dist/markdown.d.mts +2 -4
- package/dist/markdown.d.mts.map +1 -1
- package/dist/markdown.mjs +1 -1
- package/dist/math-Dk8hxbmz.mjs +1 -0
- package/dist/math-VPuwFCid.mjs +205 -0
- package/dist/math-VPuwFCid.mjs.map +1 -0
- package/dist/md.bun.d.mts +1 -3
- package/dist/md.bun.d.mts.map +1 -1
- package/dist/md.bun.mjs +2 -3
- package/dist/md.node.d.mts +1 -3
- package/dist/md.node.d.mts.map +1 -1
- package/dist/md.node.mjs +2 -3
- package/dist/{node-BZ7f6HzU.mjs → node-CXNobGaP.mjs} +3 -4
- package/dist/{node-BZ7f6HzU.mjs.map → node-CXNobGaP.mjs.map} +1 -1
- package/dist/oklch-Boh4YHEc.mjs +98 -0
- package/dist/oklch-Boh4YHEc.mjs.map +1 -0
- package/dist/{overlay-BnvOKtGT.mjs → overlay-CevDWgSF.mjs} +3 -4
- package/dist/{overlay-BnvOKtGT.mjs.map → overlay-CevDWgSF.mjs.map} +1 -1
- package/dist/{picker-Dh5IUrTk.mjs → picker-D9WrE3zF.mjs} +11 -16
- package/dist/{picker-Dh5IUrTk.mjs.map → picker-D9WrE3zF.mjs.map} +1 -1
- package/dist/{picker-DQs_IW77.d.mts → picker-DsB6--GN.d.mts} +6 -8
- package/dist/picker-DsB6--GN.d.mts.map +1 -0
- package/dist/{queries-B_lOwEiE.mjs → queries-BIniKnLL.mjs} +68 -7
- package/dist/queries-BIniKnLL.mjs.map +1 -0
- package/dist/{queries-BDX8mcl5.d.mts → queries-Dmd3IjSd.d.mts} +19 -52
- package/dist/queries-Dmd3IjSd.d.mts.map +1 -0
- package/dist/{reactive-f7NpAi69.mjs → reactive-DkP75TPk.mjs} +2 -3
- package/dist/{reactive-f7NpAi69.mjs.map → reactive-DkP75TPk.mjs.map} +1 -1
- package/dist/{registry-D-suU3g0.mjs → registry-CQU0VwpM.mjs} +205 -65
- package/dist/registry-CQU0VwpM.mjs.map +1 -0
- package/dist/{render-DEIUNLkh.mjs → render-Bp2N2i6J.mjs} +4 -5
- package/dist/{render-DEIUNLkh.mjs.map → render-Bp2N2i6J.mjs.map} +1 -1
- package/dist/{renderer-zDNlAovy.mjs → renderer-B9sAMA10.mjs} +123 -40
- package/dist/renderer-B9sAMA10.mjs.map +1 -0
- package/dist/{renderer-MQue4Da5.mjs → renderer-BYl2pbdx.mjs} +9 -9
- package/dist/renderer-BYl2pbdx.mjs.map +1 -0
- package/dist/renderer-Ctz0hv5o.mjs +1 -0
- package/dist/{search-FvGnswRl.d.mts → search-DsHzamic.d.mts} +1 -9
- package/dist/search-DsHzamic.d.mts.map +1 -0
- package/dist/{select-J2KtwxyK.d.mts → select-BZCFXdjp.d.mts} +3 -5
- package/dist/select-BZCFXdjp.d.mts.map +1 -0
- package/dist/{select-m7NE6Rwa.mjs → select-CUmAFKJh.mjs} +5 -6
- package/dist/{select-m7NE6Rwa.mjs.map → select-CUmAFKJh.mjs.map} +1 -1
- package/dist/services/logger.d.mts +1 -1
- package/dist/services/logger.mjs +1 -1
- package/dist/services/notifier.d.mts +1 -3
- package/dist/services/notifier.d.mts.map +1 -1
- package/dist/services/notifier.mjs +3 -4
- package/dist/services/picker.d.mts +5 -7
- package/dist/services/picker.d.mts.map +1 -1
- package/dist/services/picker.mjs +8 -9
- package/dist/services/prompt.d.mts +4 -6
- package/dist/services/prompt.d.mts.map +1 -1
- package/dist/services/prompt.mjs +7 -8
- package/dist/shiki/server.mjs +40 -19
- package/dist/shiki/server.mjs.map +1 -1
- package/dist/shiki-BAf9PdIc.mjs +19 -0
- package/dist/shiki-BAf9PdIc.mjs.map +1 -0
- package/dist/shiki-DUUAIE6f.mjs +632 -0
- package/dist/shiki-DUUAIE6f.mjs.map +1 -0
- package/dist/{show-DR2x1YFc.mjs → show-D5XNXgZf.mjs} +4 -5
- package/dist/{show-DR2x1YFc.mjs.map → show-D5XNXgZf.mjs.map} +1 -1
- package/dist/{size-D8JogYLy.mjs → size-BHRJuRk9.mjs} +2 -3
- package/dist/{size-D8JogYLy.mjs.map → size-BHRJuRk9.mjs.map} +1 -1
- package/dist/style-Cw_EuszU.mjs +108 -0
- package/dist/style-Cw_EuszU.mjs.map +1 -0
- package/dist/style.d.mts +4 -5
- package/dist/style.d.mts.map +1 -1
- package/dist/style.mjs +4 -4
- package/dist/{text-CkQ7Irmt.mjs → text-4arC3odI.mjs} +3 -4
- package/dist/{text-CkQ7Irmt.mjs.map → text-4arC3odI.mjs.map} +1 -1
- package/dist/{text-XvPfweeg.mjs → text-BArwVVkg.mjs} +5 -6
- package/dist/{text-XvPfweeg.mjs.map → text-BArwVVkg.mjs.map} +1 -1
- package/dist/{text-CCYs9RB2.d.mts → text-DdkJXgoC.d.mts} +3 -5
- package/dist/text-DdkJXgoC.d.mts.map +1 -0
- package/dist/text.d.mts +1 -1
- package/dist/text.mjs +1 -1
- package/dist/theme-B8hb1lPU.mjs +60 -0
- package/dist/theme-B8hb1lPU.mjs.map +1 -0
- package/dist/theme-BeSaXGNY.mjs +1792 -0
- package/dist/theme-BeSaXGNY.mjs.map +1 -0
- package/dist/themes.d.mts +211 -77
- package/dist/themes.d.mts.map +1 -1
- package/dist/themes.mjs +1 -1
- package/dist/{tree-DJl5W_B7.d.mts → tree-Berzv8Rz.d.mts} +3 -5
- package/dist/tree-Berzv8Rz.d.mts.map +1 -0
- package/dist/{tree-Bo1afYhe.mjs → tree-D6NvMQx8.mjs} +5 -6
- package/dist/{tree-Bo1afYhe.mjs.map → tree-D6NvMQx8.mjs.map} +1 -1
- package/dist/{types-D2EYlzmK.d.mts → types-ByMHEdCF.d.mts} +133 -131
- package/dist/types-ByMHEdCF.d.mts.map +1 -0
- package/dist/{types-D3jk1rtk.d.mts → types-CUVUJPz6.d.mts} +1 -3
- package/dist/types-CUVUJPz6.d.mts.map +1 -0
- package/dist/{utils-3M4D_AXZ.mjs → utils-DHXAegVW.mjs} +1 -2
- package/dist/{utils-3M4D_AXZ.mjs.map → utils-DHXAegVW.mjs.map} +1 -1
- package/dist/{widget-BkMwhY2p.mjs → widget-sFveyrZE.mjs} +3 -4
- package/dist/{widget-BkMwhY2p.mjs.map → widget-sFveyrZE.mjs.map} +1 -1
- package/dist/{widget-DPqBbB57.d.mts → widget-sPJaKVU2.d.mts} +2 -4
- package/dist/widget-sPJaKVU2.d.mts.map +1 -0
- package/dist/widgets/autocomplete.d.mts +1 -1
- package/dist/widgets/autocomplete.mjs +5 -6
- package/dist/widgets/box.d.mts +1 -1
- package/dist/widgets/box.mjs +1 -1
- package/dist/widgets/code.d.mts +4 -4
- package/dist/widgets/code.d.mts.map +1 -1
- package/dist/widgets/code.mjs +12 -12
- package/dist/widgets/code.mjs.map +1 -1
- package/dist/widgets/completions/actions.d.mts +1 -1
- package/dist/widgets/completions/actions.mjs +1 -1
- package/dist/widgets/completions/files.d.mts +1 -1
- package/dist/widgets/completions/files.mjs +1 -1
- package/dist/widgets/completions/github.d.mts +1 -1
- package/dist/widgets/completions/github.mjs +1 -1
- package/dist/widgets/completions/index.d.mts +3 -3
- package/dist/widgets/completions/index.mjs +3 -3
- package/dist/widgets/diff.d.mts +2 -4
- package/dist/widgets/diff.d.mts.map +1 -1
- package/dist/widgets/diff.mjs +38 -16
- package/dist/widgets/diff.mjs.map +1 -1
- package/dist/widgets/divider.d.mts +2 -4
- package/dist/widgets/divider.d.mts.map +1 -1
- package/dist/widgets/divider.mjs +1 -1
- package/dist/widgets/image.d.mts +1 -1
- package/dist/widgets/image.mjs +8 -9
- package/dist/widgets/image.mjs.map +1 -1
- package/dist/widgets/input.d.mts +1 -1
- package/dist/widgets/input.mjs +1 -1
- package/dist/widgets/log.d.mts +1 -1
- package/dist/widgets/log.mjs +1 -1
- package/dist/widgets/markdown.d.mts +5 -7
- package/dist/widgets/markdown.d.mts.map +1 -1
- package/dist/widgets/markdown.mjs +1 -1
- package/dist/widgets/overlay.d.mts +1 -1
- package/dist/widgets/overlay.mjs +1 -1
- package/dist/widgets/picker.d.mts +1 -1
- package/dist/widgets/picker.mjs +1 -1
- package/dist/widgets/progress.d.mts +2 -4
- package/dist/widgets/progress.d.mts.map +1 -1
- package/dist/widgets/progress.mjs +4 -5
- package/dist/widgets/select.d.mts +1 -1
- package/dist/widgets/select.mjs +1 -1
- package/dist/widgets/show.d.mts +1 -3
- package/dist/widgets/show.d.mts.map +1 -1
- package/dist/widgets/show.mjs +1 -1
- package/dist/widgets/spinner.d.mts +2 -4
- package/dist/widgets/spinner.d.mts.map +1 -1
- package/dist/widgets/spinner.mjs +3 -4
- package/dist/widgets/text.d.mts +1 -1
- package/dist/widgets/text.mjs +1 -1
- package/dist/widgets/tree.d.mts +1 -1
- package/dist/widgets/tree.mjs +1 -1
- package/dist/widgets/widget.d.mts +1 -1
- package/dist/widgets/widget.mjs +1 -1
- package/dist/{worker-T6SdPzUH.mjs → worker-CtEowucz.mjs} +2 -3
- package/dist/{worker-T6SdPzUH.mjs.map → worker-CtEowucz.mjs.map} +1 -1
- package/dist/worker-Mqi380Et.mjs +1 -0
- package/package.json +5 -7
- package/assets/themes/dracula-soft.json +0 -100
- package/assets/themes/github-dark.json +0 -104
- package/assets/themes/github-light.json +0 -104
- package/dist/actions-Dc4D4uSf.d.mts.map +0 -1
- package/dist/ansi-DZlXaItJ.mjs.map +0 -1
- package/dist/autocomplete-StW1QJZJ.d.mts.map +0 -1
- package/dist/builder-1z5ewEWK.mjs +0 -386
- package/dist/builder-1z5ewEWK.mjs.map +0 -1
- package/dist/client-C2GXKfJ1.mjs.map +0 -1
- package/dist/client-bzdHIDL2.mjs +0 -1
- package/dist/ctx-D_JgJ8Eo.mjs +0 -1
- package/dist/files-7DUYSeNc.d.mts.map +0 -1
- package/dist/github-C1KfXk98.d.mts.map +0 -1
- package/dist/image-Cm5T-uw-.mjs +0 -108
- package/dist/image-Cm5T-uw-.mjs.map +0 -1
- package/dist/image-VaT7AN-S.d.mts.map +0 -1
- package/dist/input-BAYux7qo.d.mts.map +0 -1
- package/dist/inspect-CfNydMgO.d.mts.map +0 -1
- package/dist/markdown-CwRmWuU6.mjs.map +0 -1
- package/dist/picker-DQs_IW77.d.mts.map +0 -1
- package/dist/queries-BDX8mcl5.d.mts.map +0 -1
- package/dist/queries-B_lOwEiE.mjs.map +0 -1
- package/dist/registry-D-suU3g0.mjs.map +0 -1
- package/dist/renderer-DhqbEVVR.mjs +0 -1
- package/dist/renderer-MQue4Da5.mjs.map +0 -1
- package/dist/renderer-zDNlAovy.mjs.map +0 -1
- package/dist/search-FvGnswRl.d.mts.map +0 -1
- package/dist/select-J2KtwxyK.d.mts.map +0 -1
- package/dist/shiki--ASSYv4_.mjs +0 -12
- package/dist/shiki--ASSYv4_.mjs.map +0 -1
- package/dist/shiki-D7l5--zz.mjs +0 -432
- package/dist/shiki-D7l5--zz.mjs.map +0 -1
- package/dist/text-CCYs9RB2.d.mts.map +0 -1
- package/dist/theme.config-B3Yx--C2.mjs +0 -855
- package/dist/theme.config-B3Yx--C2.mjs.map +0 -1
- package/dist/tree-DJl5W_B7.d.mts.map +0 -1
- package/dist/types-D2EYlzmK.d.mts.map +0 -1
- package/dist/types-D3jk1rtk.d.mts.map +0 -1
- package/dist/widget-DPqBbB57.d.mts.map +0 -1
- package/dist/worker-C01jK2Ip.mjs +0 -1
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { c as
|
|
2
|
-
import { a as StyleBuilder, t as InspectOpts } from "./inspect-
|
|
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
|
-
|
|
1978
|
-
|
|
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
|
-
|
|
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-
|
|
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":";;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"}
|
|
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"}
|