@textui/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (323) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/adapters/index.d.ts +12 -0
  4. package/dist/adapters/index.d.ts.map +1 -0
  5. package/dist/adapters/index.js +11 -0
  6. package/dist/app/app.d.ts +200 -0
  7. package/dist/app/app.d.ts.map +1 -0
  8. package/dist/app/app.js +980 -0
  9. package/dist/core/animation.d.ts +34 -0
  10. package/dist/core/animation.d.ts.map +1 -0
  11. package/dist/core/animation.js +125 -0
  12. package/dist/core/clipboard.d.ts +29 -0
  13. package/dist/core/clipboard.d.ts.map +1 -0
  14. package/dist/core/clipboard.js +30 -0
  15. package/dist/core/commands.d.ts +42 -0
  16. package/dist/core/commands.d.ts.map +1 -0
  17. package/dist/core/commands.js +146 -0
  18. package/dist/core/components.d.ts +27 -0
  19. package/dist/core/components.d.ts.map +1 -0
  20. package/dist/core/components.js +78 -0
  21. package/dist/core/events.d.ts +23 -0
  22. package/dist/core/events.d.ts.map +1 -0
  23. package/dist/core/events.js +77 -0
  24. package/dist/core/focus.d.ts +69 -0
  25. package/dist/core/focus.d.ts.map +1 -0
  26. package/dist/core/focus.js +336 -0
  27. package/dist/core/i18n.d.ts +27 -0
  28. package/dist/core/i18n.d.ts.map +1 -0
  29. package/dist/core/i18n.js +88 -0
  30. package/dist/core/keybindings.d.ts +53 -0
  31. package/dist/core/keybindings.d.ts.map +1 -0
  32. package/dist/core/keybindings.js +163 -0
  33. package/dist/core/layers.d.ts +28 -0
  34. package/dist/core/layers.d.ts.map +1 -0
  35. package/dist/core/layers.js +84 -0
  36. package/dist/core/manifest.d.ts +22 -0
  37. package/dist/core/manifest.d.ts.map +1 -0
  38. package/dist/core/manifest.js +85 -0
  39. package/dist/core/navigation.d.ts +47 -0
  40. package/dist/core/navigation.d.ts.map +1 -0
  41. package/dist/core/navigation.js +110 -0
  42. package/dist/core/resources.d.ts +115 -0
  43. package/dist/core/resources.d.ts.map +1 -0
  44. package/dist/core/resources.js +321 -0
  45. package/dist/core/services.d.ts +21 -0
  46. package/dist/core/services.d.ts.map +1 -0
  47. package/dist/core/services.js +63 -0
  48. package/dist/core/store.d.ts +60 -0
  49. package/dist/core/store.d.ts.map +1 -0
  50. package/dist/core/store.js +593 -0
  51. package/dist/core/surfaces.d.ts +81 -0
  52. package/dist/core/surfaces.d.ts.map +1 -0
  53. package/dist/core/surfaces.js +237 -0
  54. package/dist/core/syntax.d.ts +49 -0
  55. package/dist/core/syntax.d.ts.map +1 -0
  56. package/dist/core/syntax.js +172 -0
  57. package/dist/core/when.d.ts +15 -0
  58. package/dist/core/when.d.ts.map +1 -0
  59. package/dist/core/when.js +224 -0
  60. package/dist/index.d.ts +49 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +54 -0
  63. package/dist/jsx/factory.d.ts +27 -0
  64. package/dist/jsx/factory.d.ts.map +1 -0
  65. package/dist/jsx/factory.js +102 -0
  66. package/dist/jsx/intrinsics.d.ts +96 -0
  67. package/dist/jsx/intrinsics.d.ts.map +1 -0
  68. package/dist/jsx/intrinsics.js +1 -0
  69. package/dist/jsx/jsx-dev-runtime.d.ts +13 -0
  70. package/dist/jsx/jsx-dev-runtime.d.ts.map +1 -0
  71. package/dist/jsx/jsx-dev-runtime.js +12 -0
  72. package/dist/jsx/jsx-runtime.d.ts +42 -0
  73. package/dist/jsx/jsx-runtime.d.ts.map +1 -0
  74. package/dist/jsx/jsx-runtime.js +16 -0
  75. package/dist/render/buffer.d.ts +77 -0
  76. package/dist/render/buffer.d.ts.map +1 -0
  77. package/dist/render/buffer.js +275 -0
  78. package/dist/render/color.d.ts +35 -0
  79. package/dist/render/color.d.ts.map +1 -0
  80. package/dist/render/color.js +160 -0
  81. package/dist/render/diff.d.ts +37 -0
  82. package/dist/render/diff.d.ts.map +1 -0
  83. package/dist/render/diff.js +66 -0
  84. package/dist/render/layout.d.ts +72 -0
  85. package/dist/render/layout.d.ts.map +1 -0
  86. package/dist/render/layout.js +633 -0
  87. package/dist/render/static.d.ts +63 -0
  88. package/dist/render/static.d.ts.map +1 -0
  89. package/dist/render/static.js +209 -0
  90. package/dist/runtime/bindings.d.ts +46 -0
  91. package/dist/runtime/bindings.d.ts.map +1 -0
  92. package/dist/runtime/bindings.js +116 -0
  93. package/dist/runtime/hooks.d.ts +284 -0
  94. package/dist/runtime/hooks.d.ts.map +1 -0
  95. package/dist/runtime/hooks.js +846 -0
  96. package/dist/runtime/instance.d.ts +106 -0
  97. package/dist/runtime/instance.d.ts.map +1 -0
  98. package/dist/runtime/instance.js +181 -0
  99. package/dist/runtime/paint.d.ts +27 -0
  100. package/dist/runtime/paint.d.ts.map +1 -0
  101. package/dist/runtime/paint.js +567 -0
  102. package/dist/runtime/reconcile.d.ts +23 -0
  103. package/dist/runtime/reconcile.d.ts.map +1 -0
  104. package/dist/runtime/reconcile.js +260 -0
  105. package/dist/runtime/runtime.d.ts +42 -0
  106. package/dist/runtime/runtime.d.ts.map +1 -0
  107. package/dist/runtime/runtime.js +1 -0
  108. package/dist/runtime/style.d.ts +55 -0
  109. package/dist/runtime/style.d.ts.map +1 -0
  110. package/dist/runtime/style.js +143 -0
  111. package/dist/themes/borders.d.ts +10 -0
  112. package/dist/themes/borders.d.ts.map +1 -0
  113. package/dist/themes/borders.js +88 -0
  114. package/dist/themes/builtin.d.ts +31 -0
  115. package/dist/themes/builtin.d.ts.map +1 -0
  116. package/dist/themes/builtin.js +291 -0
  117. package/dist/themes/glyphs.d.ts +15 -0
  118. package/dist/themes/glyphs.d.ts.map +1 -0
  119. package/dist/themes/glyphs.js +97 -0
  120. package/dist/themes/index.d.ts +5 -0
  121. package/dist/themes/index.d.ts.map +1 -0
  122. package/dist/themes/index.js +4 -0
  123. package/dist/themes/registry.d.ts +20 -0
  124. package/dist/themes/registry.d.ts.map +1 -0
  125. package/dist/themes/registry.js +204 -0
  126. package/dist/types/adapter.d.ts +38 -0
  127. package/dist/types/adapter.d.ts.map +1 -0
  128. package/dist/types/adapter.js +1 -0
  129. package/dist/types/animation.d.ts +31 -0
  130. package/dist/types/animation.d.ts.map +1 -0
  131. package/dist/types/animation.js +1 -0
  132. package/dist/types/app.d.ts +148 -0
  133. package/dist/types/app.d.ts.map +1 -0
  134. package/dist/types/app.js +1 -0
  135. package/dist/types/async.d.ts +30 -0
  136. package/dist/types/async.d.ts.map +1 -0
  137. package/dist/types/async.js +1 -0
  138. package/dist/types/capabilities.d.ts +44 -0
  139. package/dist/types/capabilities.d.ts.map +1 -0
  140. package/dist/types/capabilities.js +33 -0
  141. package/dist/types/cells.d.ts +72 -0
  142. package/dist/types/cells.d.ts.map +1 -0
  143. package/dist/types/cells.js +10 -0
  144. package/dist/types/command.d.ts +127 -0
  145. package/dist/types/command.d.ts.map +1 -0
  146. package/dist/types/command.js +1 -0
  147. package/dist/types/component-registry.d.ts +77 -0
  148. package/dist/types/component-registry.d.ts.map +1 -0
  149. package/dist/types/component-registry.js +1 -0
  150. package/dist/types/disposable.d.ts +8 -0
  151. package/dist/types/disposable.d.ts.map +1 -0
  152. package/dist/types/disposable.js +1 -0
  153. package/dist/types/focus.d.ts +72 -0
  154. package/dist/types/focus.d.ts.map +1 -0
  155. package/dist/types/focus.js +1 -0
  156. package/dist/types/geometry.d.ts +28 -0
  157. package/dist/types/geometry.d.ts.map +1 -0
  158. package/dist/types/geometry.js +14 -0
  159. package/dist/types/graph.d.ts +129 -0
  160. package/dist/types/graph.d.ts.map +1 -0
  161. package/dist/types/graph.js +31 -0
  162. package/dist/types/i18n.d.ts +23 -0
  163. package/dist/types/i18n.d.ts.map +1 -0
  164. package/dist/types/i18n.js +1 -0
  165. package/dist/types/index.d.ts +32 -0
  166. package/dist/types/index.d.ts.map +1 -0
  167. package/dist/types/index.js +31 -0
  168. package/dist/types/input.d.ts +65 -0
  169. package/dist/types/input.d.ts.map +1 -0
  170. package/dist/types/input.js +1 -0
  171. package/dist/types/keybinding.d.ts +49 -0
  172. package/dist/types/keybinding.d.ts.map +1 -0
  173. package/dist/types/keybinding.js +1 -0
  174. package/dist/types/layer.d.ts +54 -0
  175. package/dist/types/layer.d.ts.map +1 -0
  176. package/dist/types/layer.js +1 -0
  177. package/dist/types/manifest.d.ts +114 -0
  178. package/dist/types/manifest.d.ts.map +1 -0
  179. package/dist/types/manifest.js +1 -0
  180. package/dist/types/markdown.d.ts +58 -0
  181. package/dist/types/markdown.d.ts.map +1 -0
  182. package/dist/types/markdown.js +1 -0
  183. package/dist/types/navigation.d.ts +40 -0
  184. package/dist/types/navigation.d.ts.map +1 -0
  185. package/dist/types/navigation.js +1 -0
  186. package/dist/types/render.d.ts +72 -0
  187. package/dist/types/render.d.ts.map +1 -0
  188. package/dist/types/render.js +1 -0
  189. package/dist/types/resource.d.ts +170 -0
  190. package/dist/types/resource.d.ts.map +1 -0
  191. package/dist/types/resource.js +1 -0
  192. package/dist/types/services.d.ts +24 -0
  193. package/dist/types/services.d.ts.map +1 -0
  194. package/dist/types/services.js +3 -0
  195. package/dist/types/shell.d.ts +32 -0
  196. package/dist/types/shell.d.ts.map +1 -0
  197. package/dist/types/shell.js +1 -0
  198. package/dist/types/store.d.ts +124 -0
  199. package/dist/types/store.d.ts.map +1 -0
  200. package/dist/types/store.js +1 -0
  201. package/dist/types/stream.d.ts +18 -0
  202. package/dist/types/stream.d.ts.map +1 -0
  203. package/dist/types/stream.js +1 -0
  204. package/dist/types/style.d.ts +166 -0
  205. package/dist/types/style.d.ts.map +1 -0
  206. package/dist/types/style.js +1 -0
  207. package/dist/types/surface.d.ts +97 -0
  208. package/dist/types/surface.d.ts.map +1 -0
  209. package/dist/types/surface.js +1 -0
  210. package/dist/types/syntax.d.ts +68 -0
  211. package/dist/types/syntax.d.ts.map +1 -0
  212. package/dist/types/syntax.js +5 -0
  213. package/dist/types/terminal.d.ts +52 -0
  214. package/dist/types/terminal.d.ts.map +1 -0
  215. package/dist/types/terminal.js +1 -0
  216. package/dist/types/theme.d.ts +117 -0
  217. package/dist/types/theme.d.ts.map +1 -0
  218. package/dist/types/theme.js +1 -0
  219. package/dist/types/when.d.ts +19 -0
  220. package/dist/types/when.d.ts.map +1 -0
  221. package/dist/types/when.js +1 -0
  222. package/dist/ui/primitives.d.ts +56 -0
  223. package/dist/ui/primitives.d.ts.map +1 -0
  224. package/dist/ui/primitives.js +108 -0
  225. package/dist/ui/screen.d.ts +23 -0
  226. package/dist/ui/screen.d.ts.map +1 -0
  227. package/dist/ui/screen.js +18 -0
  228. package/dist/util/disposable.d.ts +6 -0
  229. package/dist/util/disposable.d.ts.map +1 -0
  230. package/dist/util/disposable.js +49 -0
  231. package/dist/util/markdown.d.ts +24 -0
  232. package/dist/util/markdown.d.ts.map +1 -0
  233. package/dist/util/markdown.js +220 -0
  234. package/dist/util/paths.d.ts +47 -0
  235. package/dist/util/paths.d.ts.map +1 -0
  236. package/dist/util/paths.js +134 -0
  237. package/dist/util/stream.d.ts +32 -0
  238. package/dist/util/stream.d.ts.map +1 -0
  239. package/dist/util/stream.js +206 -0
  240. package/dist/util/text.d.ts +65 -0
  241. package/dist/util/text.d.ts.map +1 -0
  242. package/dist/util/text.js +419 -0
  243. package/package.json +70 -0
  244. package/src/adapters/index.ts +11 -0
  245. package/src/app/app.ts +1096 -0
  246. package/src/core/animation.ts +144 -0
  247. package/src/core/clipboard.ts +40 -0
  248. package/src/core/commands.ts +169 -0
  249. package/src/core/components.ts +91 -0
  250. package/src/core/events.ts +95 -0
  251. package/src/core/focus.ts +358 -0
  252. package/src/core/i18n.ts +107 -0
  253. package/src/core/keybindings.ts +184 -0
  254. package/src/core/layers.ts +94 -0
  255. package/src/core/manifest.ts +84 -0
  256. package/src/core/navigation.ts +135 -0
  257. package/src/core/resources.ts +362 -0
  258. package/src/core/services.ts +69 -0
  259. package/src/core/store.ts +640 -0
  260. package/src/core/surfaces.ts +292 -0
  261. package/src/core/syntax.ts +200 -0
  262. package/src/core/when.ts +238 -0
  263. package/src/index.ts +76 -0
  264. package/src/jsx/factory.ts +124 -0
  265. package/src/jsx/intrinsics.ts +99 -0
  266. package/src/jsx/jsx-dev-runtime.ts +23 -0
  267. package/src/jsx/jsx-runtime.ts +76 -0
  268. package/src/render/buffer.ts +318 -0
  269. package/src/render/color.ts +180 -0
  270. package/src/render/diff.ts +99 -0
  271. package/src/render/layout.ts +764 -0
  272. package/src/render/static.ts +290 -0
  273. package/src/runtime/bindings.ts +150 -0
  274. package/src/runtime/hooks.ts +1057 -0
  275. package/src/runtime/instance.ts +284 -0
  276. package/src/runtime/paint.ts +737 -0
  277. package/src/runtime/reconcile.ts +335 -0
  278. package/src/runtime/runtime.ts +47 -0
  279. package/src/runtime/style.ts +205 -0
  280. package/src/themes/borders.ts +95 -0
  281. package/src/themes/builtin.ts +301 -0
  282. package/src/themes/glyphs.ts +101 -0
  283. package/src/themes/index.ts +4 -0
  284. package/src/themes/registry.ts +224 -0
  285. package/src/types/adapter.ts +41 -0
  286. package/src/types/animation.ts +34 -0
  287. package/src/types/app.ts +149 -0
  288. package/src/types/async.ts +35 -0
  289. package/src/types/capabilities.ts +79 -0
  290. package/src/types/cells.ts +79 -0
  291. package/src/types/command.ts +139 -0
  292. package/src/types/component-registry.ts +82 -0
  293. package/src/types/disposable.ts +8 -0
  294. package/src/types/focus.ts +77 -0
  295. package/src/types/geometry.ts +50 -0
  296. package/src/types/graph.ts +174 -0
  297. package/src/types/i18n.ts +25 -0
  298. package/src/types/index.ts +31 -0
  299. package/src/types/input.ts +81 -0
  300. package/src/types/keybinding.ts +51 -0
  301. package/src/types/layer.ts +46 -0
  302. package/src/types/manifest.ts +101 -0
  303. package/src/types/markdown.ts +47 -0
  304. package/src/types/navigation.ts +42 -0
  305. package/src/types/render.ts +86 -0
  306. package/src/types/resource.ts +185 -0
  307. package/src/types/services.ts +28 -0
  308. package/src/types/shell.ts +30 -0
  309. package/src/types/store.ts +148 -0
  310. package/src/types/stream.ts +24 -0
  311. package/src/types/style.ts +205 -0
  312. package/src/types/surface.ts +119 -0
  313. package/src/types/syntax.ts +93 -0
  314. package/src/types/terminal.ts +58 -0
  315. package/src/types/theme.ts +121 -0
  316. package/src/types/when.ts +21 -0
  317. package/src/ui/primitives.ts +118 -0
  318. package/src/ui/screen.ts +41 -0
  319. package/src/util/disposable.ts +49 -0
  320. package/src/util/markdown.ts +225 -0
  321. package/src/util/paths.ts +138 -0
  322. package/src/util/stream.ts +213 -0
  323. package/src/util/text.ts +428 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/render/static.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAwB,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC1F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAoBrC;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B;;;;;;;;;;OAUG;IACH,UAAU,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACnC,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/C;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,OAAO,IAAI,IAAI,CAAC;CACjB;AAaD,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,mBAAwB,GAAG;IACtE,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,OAAO,IAAI,IAAI,CAAC;CACjB,CA0EA;AAYD,wBAAgB,UAAU,CACxB,IAAI,EAAE,aAAa,EACnB,OAAO,GAAE,mBAAwB,GAChC,kBAAkB,CA2EpB;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,GAAE,mBAAwB,GAAG,MAAM,CAO7F"}
@@ -0,0 +1,209 @@
1
+ import { Buffer } from './buffer.js';
2
+ import { layout, resolveEdges } from './layout.js';
3
+ import { buildBoxes, paintTree } from '../runtime/paint.js';
4
+ import { collectEffects, disposeTree, renderTree } from '../runtime/reconcile.js';
5
+ import { flushMeasures } from '../runtime/hooks.js';
6
+ import { NO_INTERACTION } from '../runtime/style.js';
7
+ import { createStore } from '../core/store.js';
8
+ import { createEvents } from '../core/events.js';
9
+ import { createWhen } from '../core/when.js';
10
+ import { createComponents } from '../core/components.js';
11
+ import { createServices } from '../core/services.js';
12
+ import { createFocus } from '../core/focus.js';
13
+ import { createLayers } from '../core/layers.js';
14
+ import { createAnimation } from '../core/animation.js';
15
+ import { createI18n } from '../core/i18n.js';
16
+ import { createThemes } from '../themes/registry.js';
17
+ import { PRIMITIVES } from '../ui/primitives.js';
18
+ import { FULL_CAPABILITIES } from '../types/capabilities.js';
19
+ import { ZERO_EDGES } from '../types/geometry.js';
20
+ const DEFAULT_CAPABILITIES = {
21
+ ...FULL_CAPABILITIES,
22
+ mouse: false,
23
+ wheel: false,
24
+ focusEvents: false,
25
+ paste: false,
26
+ altScreen: false,
27
+ synchronizedOutput: false,
28
+ kittyKeyboard: false,
29
+ };
30
+ export function createStaticRuntime(options = {}) {
31
+ const store = createStore();
32
+ const events = createEvents();
33
+ const when = createWhen(store);
34
+ const components = createComponents();
35
+ const services = createServices();
36
+ const focus = createFocus();
37
+ const layers = createLayers();
38
+ const animation = createAnimation({ manual: true, enabled: false });
39
+ const i18n = createI18n(options.locale ?? 'en');
40
+ const themes = createThemes(options.themes);
41
+ // The four primitives, and nothing else by default.
42
+ //
43
+ // This registered the whole catalog until it didn't: some eighty entries a
44
+ // screen made of `box` and `text` never looked at, and that JSX never
45
+ // needed either, since an imported component travels on its own node.
46
+ // Naming a component in data is the case a registry is for, and that case
47
+ // asks for it through `components`.
48
+ components.registerMany(PRIMITIVES);
49
+ if (options.components)
50
+ components.registerMany(options.components);
51
+ const capabilities = {
52
+ ...DEFAULT_CAPABILITIES,
53
+ ...options.capabilities,
54
+ };
55
+ let size = { width: options.width ?? 80, height: 24 };
56
+ const onError = options.onError ?? ((err, context) => {
57
+ console.error(`[textui] ${context}`, err);
58
+ });
59
+ store.onError = onError;
60
+ events.onError = onError;
61
+ if (options.initialState) {
62
+ store.batch(() => {
63
+ for (const [path, value] of Object.entries(options.initialState)) {
64
+ store.set((path.startsWith('$/') ? path : `$/${path}`), value);
65
+ }
66
+ });
67
+ }
68
+ store.set('$/modus/capabilities', capabilities);
69
+ store.set('$/modus/size', size);
70
+ const runtime = {
71
+ store, events, when, components, services, focus, layers, animation, i18n,
72
+ theme: () => themes.resolve(options.theme ?? 'dark', capabilities),
73
+ capabilities: () => capabilities,
74
+ size: () => size,
75
+ execute: (id) => {
76
+ throw new Error(`[textui] command "${id}" cannot run under the static renderer`);
77
+ },
78
+ emit: (path, payload) => events.emit(path, payload),
79
+ requestRender: () => { },
80
+ app: () => null,
81
+ onError,
82
+ };
83
+ return {
84
+ runtime,
85
+ setSize(width, height) {
86
+ size = { width, height };
87
+ store.set('$/modus/size', size);
88
+ },
89
+ dispose() {
90
+ animation.dispose();
91
+ layers.dispose();
92
+ events.dispose();
93
+ store.dispose();
94
+ },
95
+ };
96
+ }
97
+ function rootBoxFor(children) {
98
+ return {
99
+ style: { direction: 'column' },
100
+ borderEdges: ZERO_EDGES,
101
+ children,
102
+ rect: { x: 0, y: 0, width: 0, height: 0 },
103
+ content: { x: 0, y: 0, width: 0, height: 0 },
104
+ };
105
+ }
106
+ export function renderOnce(node, options = {}) {
107
+ const width = options.width ?? 80;
108
+ const { runtime, setSize, dispose: disposeRuntime } = createStaticRuntime(options);
109
+ // Measure against a generous height first when the caller wants `auto`, so
110
+ // nothing is clipped before we know how tall the content actually is.
111
+ const measureHeight = options.height === 'auto' || options.height === undefined
112
+ ? 4096
113
+ : options.height;
114
+ setSize(width, measureHeight);
115
+ const env = {
116
+ theme: runtime.theme(),
117
+ capabilities: runtime.capabilities(),
118
+ stateOf: () => NO_INTERACTION,
119
+ };
120
+ let root = null;
121
+ const maxPasses = options.maxPasses ?? 8;
122
+ for (let pass = 0; pass < maxPasses; pass++) {
123
+ root = renderTree(runtime, root, node);
124
+ const effects = collectEffects(root);
125
+ if (effects.length === 0)
126
+ break;
127
+ for (const effect of effects)
128
+ effect();
129
+ if (!hasDirty(root))
130
+ break;
131
+ }
132
+ let instance = root;
133
+ let boxes = buildBoxes(instance, env);
134
+ let rootBox = rootBoxFor(boxes);
135
+ layout(rootBox, { x: 0, y: 0, width, height: measureHeight });
136
+ // A measured component only knows its size once it has been laid out. Give
137
+ // it that, then render again - otherwise the static renderer is the one
138
+ // place where a viewport draws nothing.
139
+ for (let pass = 0; pass < maxPasses && flushMeasures(); pass++) {
140
+ instance = renderTree(runtime, instance, node);
141
+ for (const effect of collectEffects(instance))
142
+ effect();
143
+ boxes = buildBoxes(instance, env);
144
+ rootBox = rootBoxFor(boxes);
145
+ layout(rootBox, { x: 0, y: 0, width, height: measureHeight });
146
+ }
147
+ const used = contentHeight(rootBox);
148
+ const height = options.height === 'auto' || options.height === undefined
149
+ ? Math.max(1, used)
150
+ : options.height;
151
+ // Lay out again at the real height so `flex` and `justify` see the truth.
152
+ if (height !== measureHeight) {
153
+ setSize(width, height);
154
+ layout(rootBox, { x: 0, y: 0, width, height });
155
+ for (let pass = 0; pass < maxPasses && flushMeasures(); pass++) {
156
+ instance = renderTree(runtime, instance, node);
157
+ for (const effect of collectEffects(instance))
158
+ effect();
159
+ rootBox = rootBoxFor(buildBoxes(instance, env));
160
+ layout(rootBox, { x: 0, y: 0, width, height });
161
+ }
162
+ }
163
+ const buffer = new Buffer(width, height);
164
+ paintTree(buffer, instance, env, { x: 0, y: 0, width, height });
165
+ return {
166
+ buffer,
167
+ text: buffer.toText(),
168
+ root: instance,
169
+ runtime,
170
+ dispose() {
171
+ disposeTree(instance);
172
+ disposeRuntime();
173
+ },
174
+ };
175
+ }
176
+ /** Render to plain text. The shortest path from a component to a string. */
177
+ export function renderToString(node, options = {}) {
178
+ const result = renderOnce(node, options);
179
+ try {
180
+ return result.text;
181
+ }
182
+ finally {
183
+ result.dispose();
184
+ }
185
+ }
186
+ function contentHeight(box) {
187
+ let bottom = 0;
188
+ const walk = (b) => {
189
+ if (b.rect.width > 0 && b.rect.height > 0) {
190
+ // Plus the margin below it, which is space the box needs even though
191
+ // nothing paints there. Measuring to the bottom edge alone reports a
192
+ // height the layout cannot reproduce: laid out again inside it, the
193
+ // margin has to come out of the box, and the box loses the rows.
194
+ // `<box margin={2} border="single">` measured 5 and then drew one row
195
+ // of a three-row box.
196
+ bottom = Math.max(bottom, b.rect.y + b.rect.height + resolveEdges(b.style.margin).bottom);
197
+ }
198
+ for (const child of b.children)
199
+ walk(child);
200
+ };
201
+ for (const child of box.children)
202
+ walk(child);
203
+ return bottom;
204
+ }
205
+ function hasDirty(instance) {
206
+ if (instance.dirty)
207
+ return true;
208
+ return instance.children.some(hasDirty);
209
+ }
@@ -0,0 +1,46 @@
1
+ import type { Action, BindingPath, ComponentNode } from '../types/graph.js';
2
+ import type { ReactiveStore } from '../types/store.js';
3
+ /**
4
+ * Prop values arrive as literals, bindings (`{ path }`) or function calls
5
+ * (`{ call }`). Resolving them is what makes a node written as data behave
6
+ * exactly like one written in JSX.
7
+ *
8
+ * Every path read during a resolve is recorded, so the caller can subscribe to
9
+ * precisely the paths this subtree depends on and re-render on nothing else.
10
+ */
11
+ export interface ResolveContext {
12
+ store: ReactiveStore;
13
+ /** Relative paths resolve against this. */
14
+ dataContext?: BindingPath;
15
+ /** Run a registered command. */
16
+ execute(id: string, args?: Record<string, unknown>): unknown;
17
+ /** Publish on an event path. */
18
+ emit(path: string, payload?: unknown): void;
19
+ /** Collected during the resolve; the caller subscribes to these. */
20
+ reads: Set<string>;
21
+ }
22
+ /**
23
+ * Turn an action into something callable. Actions stay data right up to the
24
+ * moment they are invoked, which is what lets the same button work whether it
25
+ * was written in JSX with a closure or loaded from JSON naming a command.
26
+ */
27
+ export declare function resolveAction(ctx: ResolveContext, action: Action | ((...args: unknown[]) => unknown) | undefined): ((...args: unknown[]) => unknown) | undefined;
28
+ /** Resolve one prop value, leaving nodes and closures alone. */
29
+ export declare function resolveValue(ctx: ResolveContext, value: unknown): unknown;
30
+ /**
31
+ * Resolve every prop on a node. `component`, `id`, `key` and `$meta` are
32
+ * structural and pass through untouched.
33
+ *
34
+ * A prop named `onSomething` whose value is an action becomes a callable, so a
35
+ * node loaded from JSON can say `{ onPress: { functionCall: { call: 'x' } } }`
36
+ * and the component receives the same shape it would get from JSX. Without
37
+ * this, actions-as-data would only work on the handful of props the runtime
38
+ * knew about by name.
39
+ */
40
+ export declare function resolveProps(ctx: ResolveContext, node: ComponentNode): Record<string, unknown>;
41
+ /** True when the value is a templated child list: one instance per item. */
42
+ export declare function isTemplateChildren(v: unknown): v is {
43
+ template: ComponentNode;
44
+ path: BindingPath;
45
+ };
46
+ //# sourceMappingURL=bindings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../../src/runtime/bindings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EAAE,WAAW,EAAE,aAAa,EACnC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gCAAgC;IAChC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7D,gCAAgC;IAChC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5C,oEAAoE;IACpE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACpB;AAsCD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,SAAS,GAC7D,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,SAAS,CAW/C;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAkBzE;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,aAAa,GAClB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAezB;AAOD,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAChC,CAAC,EAAE,OAAO,GACT,CAAC,IAAI;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAMrD"}
@@ -0,0 +1,116 @@
1
+ import { isAction, isComponentNode, isDataBinding, isFunctionCall } from '../types/graph.js';
2
+ import { resolvePath } from '../util/paths.js';
3
+ /** `#/a/b` means: the value AT this path is itself a path. One extra hop. */
4
+ function readPath(ctx, raw) {
5
+ let path = raw;
6
+ // `{{ /other/path }}` substitutes another path's value into this one first.
7
+ if (path.includes('{{')) {
8
+ path = path.replace(/\{\{\s*([^}]+?)\s*\}\}/g, (_m, inner) => {
9
+ const resolved = resolvePath(inner.trim(), ctx.dataContext);
10
+ ctx.reads.add(resolved);
11
+ return String(ctx.store.get(resolved) ?? '');
12
+ });
13
+ }
14
+ if (path.startsWith('#/')) {
15
+ const indirect = resolvePath(path.slice(1), ctx.dataContext);
16
+ ctx.reads.add(indirect);
17
+ const target = ctx.store.get(indirect);
18
+ if (typeof target !== 'string')
19
+ return undefined;
20
+ const final = resolvePath(target, ctx.dataContext);
21
+ ctx.reads.add(final);
22
+ return ctx.store.get(final);
23
+ }
24
+ const resolved = resolvePath(path, ctx.dataContext);
25
+ ctx.reads.add(resolved);
26
+ return ctx.store.get(resolved);
27
+ }
28
+ function resolveCall(ctx, call) {
29
+ const args = {};
30
+ for (const [k, v] of Object.entries(call.args ?? {})) {
31
+ args[k] = resolveValue(ctx, v);
32
+ }
33
+ return ctx.execute(call.call, args);
34
+ }
35
+ /**
36
+ * Turn an action into something callable. Actions stay data right up to the
37
+ * moment they are invoked, which is what lets the same button work whether it
38
+ * was written in JSX with a closure or loaded from JSON naming a command.
39
+ */
40
+ export function resolveAction(ctx, action) {
41
+ if (action === undefined)
42
+ return undefined;
43
+ if (typeof action === 'function')
44
+ return action;
45
+ if ('handler' in action)
46
+ return action.handler;
47
+ if ('functionCall' in action) {
48
+ return () => resolveCall(ctx, action.functionCall);
49
+ }
50
+ if ('emit' in action) {
51
+ return () => ctx.emit(action.emit.path, resolveValue(ctx, action.emit.payload));
52
+ }
53
+ return undefined;
54
+ }
55
+ /** Resolve one prop value, leaving nodes and closures alone. */
56
+ export function resolveValue(ctx, value) {
57
+ if (value === null || value === undefined)
58
+ return value;
59
+ if (typeof value !== 'object')
60
+ return value;
61
+ if (typeof value === 'function')
62
+ return value;
63
+ if (isDataBinding(value))
64
+ return readPath(ctx, value.path);
65
+ if (isFunctionCall(value))
66
+ return resolveCall(ctx, value);
67
+ // Nodes and templated child lists stay as they are; the reconciler owns them.
68
+ if (isComponentNode(value))
69
+ return value;
70
+ if (isAction(value))
71
+ return value;
72
+ if (Array.isArray(value))
73
+ return value.map((v) => resolveValue(ctx, v));
74
+ const out = {};
75
+ for (const [k, v] of Object.entries(value)) {
76
+ out[k] = resolveValue(ctx, v);
77
+ }
78
+ return out;
79
+ }
80
+ /**
81
+ * Resolve every prop on a node. `component`, `id`, `key` and `$meta` are
82
+ * structural and pass through untouched.
83
+ *
84
+ * A prop named `onSomething` whose value is an action becomes a callable, so a
85
+ * node loaded from JSON can say `{ onPress: { functionCall: { call: 'x' } } }`
86
+ * and the component receives the same shape it would get from JSX. Without
87
+ * this, actions-as-data would only work on the handful of props the runtime
88
+ * knew about by name.
89
+ */
90
+ export function resolveProps(ctx, node) {
91
+ const out = {};
92
+ for (const [k, v] of Object.entries(node)) {
93
+ if (k === 'component' || k === '$meta' || k === 'key')
94
+ continue;
95
+ if (k === 'children') {
96
+ out.children = v;
97
+ continue;
98
+ }
99
+ if (isHandlerProp(k) && isAction(v)) {
100
+ out[k] = resolveAction(ctx, v);
101
+ continue;
102
+ }
103
+ out[k] = resolveValue(ctx, v);
104
+ }
105
+ return out;
106
+ }
107
+ /** `onPress`, `onSelect`, `onChange` - but not `once` or `only`. */
108
+ function isHandlerProp(key) {
109
+ return key.length > 2 && key.startsWith('on') && key[2] === key[2]?.toUpperCase();
110
+ }
111
+ /** True when the value is a templated child list: one instance per item. */
112
+ export function isTemplateChildren(v) {
113
+ return (typeof v === 'object' && v !== null &&
114
+ 'template' in v && 'path' in v &&
115
+ isComponentNode(v.template));
116
+ }
@@ -0,0 +1,284 @@
1
+ import type { BindingPath, EventPath } from '../types/graph.js';
2
+ import type { Disposable } from '../types/disposable.js';
3
+ import type { ResolvedTheme } from '../types/theme.js';
4
+ import type { TerminalCapabilities } from '../types/capabilities.js';
5
+ import type { Rect, Size } from '../types/geometry.js';
6
+ import type { ServiceKey } from '../types/services.js';
7
+ import type { KeyEvent } from '../types/input.js';
8
+ import type { CommandDefinition } from '../types/command.js';
9
+ import type { FocusDirection } from '../types/focus.js';
10
+ import type { TaskFn, TaskState } from '../types/async.js';
11
+ import type { StreamSource } from '../types/stream.js';
12
+ import type { TextUIApp } from '../types/app.js';
13
+ import type { I18n } from '../types/i18n.js';
14
+ import type { Navigator } from '../types/navigation.js';
15
+ import type { Resource } from '../types/resource.js';
16
+ import type { SyntaxQuery, SyntaxRegistry, SyntaxToken } from '../types/syntax.js';
17
+ import type { RenderOutput } from '../types/render.js';
18
+ import type { Instance } from './instance.js';
19
+ import type { Runtime } from './runtime.js';
20
+ export declare function setCurrentInstance(instance: Instance | null): void;
21
+ export declare function currentInstance(): Instance;
22
+ export declare function useRuntime(): Runtime;
23
+ export type SetState<T> = (next: T | ((prev: T) => T)) => void;
24
+ export declare function useState<T>(initial: T | (() => T)): [T, SetState<T>];
25
+ export declare function useReducer<S, A>(reducer: (state: S, action: A) => S, initial: S): [S, (action: A) => void];
26
+ export declare function useRef<T>(initial: T): {
27
+ current: T;
28
+ };
29
+ export declare function useMemo<T>(factory: () => T, deps: unknown[]): T;
30
+ export declare function useCallback<T extends (...args: never[]) => unknown>(fn: T, deps: unknown[]): T;
31
+ /**
32
+ * Runs after the frame is painted. The returned function runs before the next
33
+ * run and on unmount - so a subscription set up here is torn down exactly once.
34
+ */
35
+ export declare function useEffect(effect: () => void | (() => void), deps?: unknown[]): void;
36
+ /** Same contract as `useEffect`, but flushed before the frame is painted. */
37
+ export declare function useLayoutEffect(effect: () => void | (() => void), deps?: unknown[]): void;
38
+ export interface Context<T> {
39
+ id: string;
40
+ defaultValue: T;
41
+ Provider: (props: {
42
+ value: T;
43
+ children?: unknown;
44
+ }) => RenderOutput;
45
+ }
46
+ export declare function createContext<T>(name: string, defaultValue: T): Context<T>;
47
+ export declare function useContext<T>(context: Context<T>): T;
48
+ /**
49
+ * Store-backed state, in the shape of `useState`.
50
+ *
51
+ * The second argument is an initial value, and it behaves like one: if the
52
+ * path is empty the first time a component asks for it, it is written. That is
53
+ * what makes the hook safe to read like state - every other reader of the same
54
+ * path sees the same thing, immediately, rather than each one privately
55
+ * imagining its own default.
56
+ *
57
+ * The store stays authoritative. Copying a value out into `useState` and
58
+ * editing the copy creates a second answer to a question the store already
59
+ * answers; this hook is the way to avoid needing to.
60
+ *
61
+ * For a reader that must not write - a component displaying a path that
62
+ * something else owns - use `useStoreValue`, whose second argument is a
63
+ * display fallback and nothing more.
64
+ */
65
+ export declare function useStore<T = unknown>(path: BindingPath, initial?: T): [T | undefined, (value: T) => void];
66
+ /**
67
+ * Read a store path without ever writing it.
68
+ *
69
+ * `fallback` is what this reader shows while the path is empty. It is not an
70
+ * initial value and it is not shared: another component reading the same path
71
+ * still sees nothing.
72
+ */
73
+ export declare function useStoreValue<T = unknown>(path: BindingPath, fallback?: T): T | undefined;
74
+ /** Subscribe to a whole subtree - a namespace, a collection, a scope. */
75
+ export declare function useStoreSubtree<T = unknown>(path: BindingPath): T | undefined;
76
+ export declare function useCollection<T = unknown>(path: BindingPath): import("../index.js").CollectionOps<T>;
77
+ export declare function useEvent(path: EventPath, handler: (payload: unknown) => void, options?: {
78
+ subtree?: boolean;
79
+ }): void;
80
+ export declare function useEmit(): (path: EventPath, payload?: unknown) => void;
81
+ export declare function useApp(): TextUIApp;
82
+ export declare function useTheme(): ResolvedTheme;
83
+ export declare function useCapabilities(): TerminalCapabilities;
84
+ /** Terminal size, re-rendering on resize. */
85
+ export declare function useSize(): Size;
86
+ /**
87
+ * Adapt to the space this component was actually given, not to the terminal.
88
+ * A sidebar and the main area are different widths on the same screen.
89
+ */
90
+ /**
91
+ * The content rect this component was last laid out into.
92
+ *
93
+ * A component that fills the space it is given cannot size itself from its
94
+ * content - a file viewer that renders one row per line makes every pane
95
+ * around it move when a different file is opened. Measuring inverts that: the
96
+ * layout decides the size, and the component renders exactly what fits.
97
+ *
98
+ * The value is the previous frame's, and asking for it schedules another pass
99
+ * when it changed, so the first frame after a resize is one frame behind and
100
+ * every frame after it is exact.
101
+ */
102
+ export declare function useMeasure(): Rect;
103
+ /**
104
+ * How big the content is, when it is bigger than the box holding it.
105
+ *
106
+ * `null` when everything fits. The layout has always recorded this - the
107
+ * comment where it does says "so a scroll container knows how far it can go" -
108
+ * but nothing read it, so no scroll container knew, and every one of them
109
+ * scrolled for ever past its own last line.
110
+ *
111
+ * Reported for the nearest *scroll container* at or below this component's own
112
+ * box - a viewport is a row holding the scrolling part beside a scrollbar, and
113
+ * the row is not the part that scrolls.
114
+ */
115
+ export declare function useScrollExtent(): Size | null;
116
+ /**
117
+ * Publish every watcher's laid-out rect. Returns true when one changed, which
118
+ * means the frame is not final and the caller should render again.
119
+ */
120
+ export declare function flushMeasures(): boolean;
121
+ export declare function useBreakpoint(width: number, breakpoints?: {
122
+ compact?: number;
123
+ minimal?: number;
124
+ }): 'full' | 'compact' | 'minimal';
125
+ export declare function useI18n(): I18n;
126
+ export declare function useService<T>(key: ServiceKey<T>): T | undefined;
127
+ export declare function useRequiredService<T>(key: ServiceKey<T>): T;
128
+ export interface UseFocusOptions {
129
+ id?: string;
130
+ disabled?: boolean;
131
+ skipTab?: boolean;
132
+ autoFocus?: boolean;
133
+ order?: number;
134
+ scopeId?: string;
135
+ onFocus?(): void;
136
+ onBlur?(): void;
137
+ }
138
+ export interface FocusHandle {
139
+ id: string;
140
+ focused: boolean;
141
+ focus(): void;
142
+ blur(): void;
143
+ move(direction: FocusDirection): void;
144
+ }
145
+ /** The focus scope this instance sits inside, if any. */
146
+ export declare function focusScopeOf(instance: Instance): string | undefined;
147
+ export declare function useFocus(options?: UseFocusOptions): FocusHandle;
148
+ /** A focus scope. Modals trap; a sidebar does not. */
149
+ export declare function useFocusScope(options?: {
150
+ id?: string;
151
+ trap?: boolean;
152
+ restore?: boolean;
153
+ autoFocus?: boolean;
154
+ active?: boolean;
155
+ }): string;
156
+ /**
157
+ * Keyboard input. Scoped to focus by default - a handler that fires while
158
+ * something else is focused is nearly always a bug, so `global` has to be
159
+ * asked for.
160
+ */
161
+ /**
162
+ * A key that is not this control's to take.
163
+ *
164
+ * A list handles `pagedown`, and `ctrl+pagedown` is an application saying
165
+ * "next file" over the top of it - one is navigation inside the control, the
166
+ * other is a chord aimed past it. A control that switches on `event.name`
167
+ * alone takes both, and the application's binding then works everywhere except
168
+ * in the pane a person is actually looking at.
169
+ */
170
+ export declare function chorded(event: KeyEvent): boolean;
171
+ export declare function useInput(handler: (event: KeyEvent) => boolean | void, options?: {
172
+ focusId?: string;
173
+ global?: boolean;
174
+ enabled?: boolean;
175
+ }): void;
176
+ /**
177
+ * The screen this is drawn inside: which one, and what it was given.
178
+ *
179
+ * Reads the published entry rather than props, so a control eight levels down
180
+ * can ask which task it is showing without every box between it and the screen
181
+ * forwarding an id it does not care about.
182
+ */
183
+ /**
184
+ * Keys, by the name they are written under everywhere else.
185
+ *
186
+ * `useInput` hands you a `KeyEvent` and leaves you to compare its fields,
187
+ * which is four lines of `event.ctrl && event.name === 's'` per key and a bug
188
+ * the first time somebody forgets that shift is implied by an uppercase
189
+ * letter. The keybinding registry already had the answer - one canonical
190
+ * spelling per stroke - so this reads the same strings.
191
+ *
192
+ * useKeymap({
193
+ * '+': () => setCount((c) => c + 1),
194
+ * '-': () => setCount((c) => c - 1),
195
+ * space: () => setRunning((r) => !r),
196
+ * 'ctrl+s': save,
197
+ * });
198
+ *
199
+ * Global by default, unlike `useInput`. A component that lists the keys it
200
+ * wants almost never also wants them to stop working the moment focus lands
201
+ * somewhere else - and the screens where that is wrong have a focusable to
202
+ * name, so they can say `{ global: false }` and mean it.
203
+ *
204
+ * A handler that returns nothing has handled the key. Return `false` to let
205
+ * it carry on to whatever is behind.
206
+ */
207
+ export declare function useKeymap(map: Record<string, (event: KeyEvent) => boolean | void>, options?: {
208
+ focusId?: string;
209
+ global?: boolean;
210
+ enabled?: boolean;
211
+ }): void;
212
+ export declare function useScreen<P = Record<string, unknown>>(): {
213
+ id: string | null;
214
+ params: P;
215
+ };
216
+ /** The stack, for a component that moves between screens. */
217
+ export declare function useNavigate(): Navigator;
218
+ export declare function useCommand(def: Omit<CommandDefinition, 'scopeId'>, deps?: unknown[]): void;
219
+ export declare function useExecute(): (id: string, args?: Record<string, unknown>) => unknown;
220
+ export interface TaskHandle<T> extends TaskState<T> {
221
+ run(...args: unknown[]): Promise<T | undefined>;
222
+ cancel(): void;
223
+ reset(): void;
224
+ }
225
+ /**
226
+ * An async unit of work with a lifecycle a component can render: idle,
227
+ * running, success, error, cancelled - plus progress and cancellation.
228
+ */
229
+ export declare function useTask<T>(fn: TaskFn<T>, deps?: unknown[]): TaskHandle<T>;
230
+ /** A task that runs on mount and can be refreshed. */
231
+ export declare function useResource<T>(fn: TaskFn<T>, deps?: unknown[]): TaskHandle<T> & {
232
+ refresh(): void;
233
+ };
234
+ /** Read a resource through the registry, by URI. */
235
+ export declare function useResourceUri(uri: string | null): {
236
+ resource: Resource | null;
237
+ content: string | Uint8Array | null;
238
+ status: TaskState['status'];
239
+ error: unknown;
240
+ refresh(): void;
241
+ };
242
+ /** The highlighter registry, or undefined outside an application. */
243
+ export declare function useSyntax(): SyntaxRegistry | undefined;
244
+ /**
245
+ * Tokenise text for display, memoised on the text and the query.
246
+ *
247
+ * Nothing registered for this kind means one plain token per line, which is
248
+ * exactly what an uncoloured viewer wants - so a caller never branches on
249
+ * whether highlighting exists.
250
+ */
251
+ export declare function useHighlight(text: string, query?: SyntaxQuery): SyntaxToken[][];
252
+ export interface ClipboardHandle {
253
+ /** What is on the clipboard now. Reading it here means a menu row that
254
+ * offers "Paste" redraws when there is something to paste. */
255
+ text: string;
256
+ read(): string;
257
+ write(text: string): void;
258
+ }
259
+ /**
260
+ * The clipboard, as a hook.
261
+ *
262
+ * `write` puts the text on the system clipboard as well, when the terminal
263
+ * can take it. Nothing reads the system clipboard back - see
264
+ * `core/clipboard.ts` for why - so a paste is whatever this application last
265
+ * copied, plus whatever the terminal delivers as a bracketed paste.
266
+ */
267
+ export declare function useClipboard(): ClipboardHandle;
268
+ /** The most recent `limit` values from any stream source. */
269
+ export declare function useStream<T>(source: StreamSource<T> | null, options?: {
270
+ limit?: number;
271
+ }): T[];
272
+ /** A frame ticker, throttled and globally disableable by the driver. */
273
+ export declare function useTicker(onTick: (frame: number, elapsedMs: number) => void, options?: {
274
+ fps?: number;
275
+ enabled?: boolean;
276
+ }): void;
277
+ /** A frame counter, for spinners and marquees. Frozen when animation is off. */
278
+ export declare function useFrame(fps?: number): number;
279
+ /** A value that eases towards its target. Snaps when animation is off. */
280
+ export declare function useTween(target: number, durationMs?: number): number;
281
+ export declare function useInterval(fn: () => void, ms: number, enabled?: boolean): void;
282
+ /** Register a disposable for the lifetime of this component. */
283
+ export declare function useDisposable(factory: () => Disposable, deps?: unknown[]): void;
284
+ //# sourceMappingURL=hooks.d.ts.map