@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,205 @@
1
+ import type { Color } from './cells.js';
2
+ import type { EdgeSpec } from './geometry.js';
3
+
4
+ /**
5
+ * Semantic theme tokens. A component names a role, never a colour - which is
6
+ * what lets one catalog render the same under a light theme, a dark theme and
7
+ * a 16-colour ssh session.
8
+ */
9
+ export type ColorToken =
10
+ | 'canvas' | 'surface' | 'surfaceAlt' | 'overlay'
11
+ | 'border' | 'borderStrong' | 'borderSubtle'
12
+ | 'text' | 'muted' | 'subtle' | 'inverted'
13
+ | 'accent' | 'primary' | 'secondary'
14
+ | 'success' | 'warning' | 'danger' | 'info'
15
+ | 'onDefault' | 'onMuted'
16
+ | 'onAccent' | 'onPrimary' | 'onSecondary'
17
+ | 'onSuccess' | 'onWarning' | 'onDanger' | 'onInfo'
18
+ | 'hover' | 'active' | 'selected' | 'focus' | 'disabled'
19
+ | 'scrim' | 'cursor' | 'shadow';
20
+
21
+ /** Anywhere a colour is accepted, a semantic token is accepted too. */
22
+ export type StyleColor = ColorToken | Color;
23
+
24
+ export type Dimension = number | `${number}%` | 'auto';
25
+
26
+ export type BorderStyle =
27
+ | 'none' | 'single' | 'double' | 'round' | 'bold'
28
+ | 'dashed' | 'ascii' | 'thick' | 'half';
29
+
30
+ /** The twelve glyphs a box needs. Themes may ship their own set. */
31
+ export interface BorderChars {
32
+ topLeft: string;
33
+ top: string;
34
+ topRight: string;
35
+ right: string;
36
+ bottomRight: string;
37
+ bottom: string;
38
+ bottomLeft: string;
39
+ left: string;
40
+ /** junctions, for tables and split panels */
41
+ cross: string;
42
+ teeTop: string;
43
+ teeBottom: string;
44
+ teeLeft: string;
45
+ teeRight: string;
46
+ }
47
+
48
+ export type BorderSides = {
49
+ top?: boolean;
50
+ right?: boolean;
51
+ bottom?: boolean;
52
+ left?: boolean;
53
+ };
54
+
55
+ /** A colour per edge. Unnamed edges fall back to the border's `color`. */
56
+ export type BorderColors = {
57
+ top?: StyleColor;
58
+ right?: StyleColor;
59
+ bottom?: StyleColor;
60
+ left?: StyleColor;
61
+ };
62
+
63
+ export type BorderSpec =
64
+ | BorderStyle
65
+ | {
66
+ style?: BorderStyle;
67
+ color?: StyleColor;
68
+ /**
69
+ * Per-edge colour, over `color`. A corner belongs to the edge that runs
70
+ * through it - the top rule owns both top corners - because a cell holds
71
+ * one colour and a terminal has no mitre to split it along.
72
+ */
73
+ colors?: BorderColors;
74
+ sides?: BorderSides;
75
+ chars?: Partial<BorderChars>;
76
+ /**
77
+ * Draw the frame dim. The frame only: a dim attribute on the box itself
78
+ * would take the content with it, and a quiet border around ordinary
79
+ * text is the whole reason to ask.
80
+ */
81
+ dim?: boolean;
82
+ };
83
+
84
+ export type Align = 'start' | 'center' | 'end' | 'stretch' | 'baseline';
85
+ export type Justify = 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly';
86
+ export type Overflow = 'visible' | 'hidden' | 'scroll' | 'ellipsis';
87
+ export type Position = 'relative' | 'absolute';
88
+ export type FlexWrap = 'nowrap' | 'wrap';
89
+ /**
90
+ * How a run of text meets the edge of its box.
91
+ *
92
+ * `none`, `word` and `char` describe *wrapping*: the text keeps every
93
+ * character and takes as many rows as it needs. The `truncate-*` forms are the
94
+ * opposite bargain - one row, and whatever does not fit is replaced by an
95
+ * ellipsis at the named end. `truncate` is `truncate-end`, which is the one
96
+ * everybody means.
97
+ *
98
+ * A truncating text is one row tall by definition, so an embedded newline
99
+ * would have nowhere to go; those become spaces rather than being dropped,
100
+ * because a joined sentence still reads and a silently halved one does not.
101
+ */
102
+ export type TextWrap =
103
+ | 'none' | 'word' | 'char'
104
+ | 'truncate' | 'truncate-start' | 'truncate-middle' | 'truncate-end';
105
+
106
+
107
+ export interface Style {
108
+ /**
109
+ * Wash whatever is already painted here toward this colour, instead of
110
+ * drawing over it. A modal scrim in a terminal: the screen behind recedes
111
+ * but stays legible, rather than being replaced by a rectangle of nothing.
112
+ * `true` uses the theme's `scrim` token; a number sets the strength.
113
+ */
114
+ scrim?: boolean | StyleColor;
115
+ scrimStrength?: number;
116
+
117
+ // --- box ---
118
+ display?: 'flex' | 'none';
119
+ direction?: 'row' | 'column';
120
+ /** Space between children on both axes. `columnGap`/`rowGap` override it. */
121
+ gap?: number;
122
+ /**
123
+ * Space between columns - horizontal, whichever way the container runs. It
124
+ * is the gap *between* children on a row, and the gap between wrapped lines
125
+ * on a column.
126
+ */
127
+ columnGap?: number;
128
+ /** Space between rows - vertical. The mirror of `columnGap`. */
129
+ rowGap?: number;
130
+ /**
131
+ * Whether children that do not fit start a new line. `nowrap` is the
132
+ * default and the cheaper path: one line, children shrink or get clipped.
133
+ */
134
+ flexWrap?: FlexWrap;
135
+ padding?: EdgeSpec;
136
+ margin?: EdgeSpec;
137
+ width?: Dimension;
138
+ height?: Dimension;
139
+ minWidth?: number;
140
+ maxWidth?: number;
141
+ minHeight?: number;
142
+ maxHeight?: number;
143
+ /** Grow factor along the parent's main axis. 0 = size to content. */
144
+ flex?: number;
145
+ /** Shrink factor. Defaults to 1 when flex is unset. */
146
+ shrink?: number;
147
+ /** Base size along the main axis before grow/shrink. */
148
+ basis?: Dimension;
149
+ align?: Align;
150
+ alignSelf?: Align;
151
+ justify?: Justify;
152
+ position?: Position;
153
+ top?: number;
154
+ right?: number;
155
+ bottom?: number;
156
+ left?: number;
157
+ /** Painting and hit-testing order within a layer. */
158
+ zIndex?: number;
159
+ /** What happens to content past the edge, on both axes. */
160
+ overflow?: Overflow;
161
+ /** Overrides `overflow` sideways. A row that scrolls but does not grow. */
162
+ overflowX?: Overflow;
163
+ /** Overrides `overflow` downwards. The usual scroll container. */
164
+ overflowY?: Overflow;
165
+
166
+ // --- paint ---
167
+ fg?: StyleColor;
168
+ bg?: StyleColor;
169
+ bold?: boolean;
170
+ dim?: boolean;
171
+ italic?: boolean;
172
+ underline?: boolean;
173
+ inverse?: boolean;
174
+ strike?: boolean;
175
+ blink?: boolean;
176
+ border?: BorderSpec;
177
+
178
+ // --- text ---
179
+ wrap?: TextWrap;
180
+ textAlign?: 'left' | 'center' | 'right';
181
+ /** Character painted into empty cells of this box. */
182
+ fill?: string;
183
+ }
184
+
185
+ /** Styles selected by interaction state. Merged over the base in this order. */
186
+ export interface StatefulStyle {
187
+ base?: Style;
188
+ focus?: Style;
189
+ hover?: Style;
190
+ active?: Style;
191
+ selected?: Style;
192
+ disabled?: Style;
193
+ }
194
+
195
+ export type StyleInput = Style | StatefulStyle | (Style | StatefulStyle | undefined | false)[];
196
+
197
+ /** Global semantic variants, available to every component that opts in. */
198
+ export type SemanticVariant =
199
+ | 'default' | 'primary' | 'secondary' | 'accent'
200
+ | 'success' | 'warning' | 'danger' | 'info' | 'muted';
201
+
202
+ /** Presentational variants a component may support. */
203
+ export type SurfaceVariant = 'solid' | 'outline' | 'ghost' | 'link';
204
+
205
+ export type Density = 'compact' | 'normal' | 'airy';
@@ -0,0 +1,119 @@
1
+ import type { Disposable } from './disposable.js';
2
+ import type { BindingPath, ComponentNode } from './graph.js';
3
+ import type { WhenClause } from './when.js';
4
+ import type { StyleColor } from './style.js';
5
+
6
+ /**
7
+ * Where something is mounted.
8
+ *
9
+ * A surface is the application's word, not the library's. The names below are
10
+ * the ones the shipped shells happen to use, and they are listed so an editor
11
+ * can complete them - `(string & {})` keeps the type open, so `lateral1`,
12
+ * `inspector` or `panel:bottom` are all equally valid and need no change here.
13
+ *
14
+ * The runtime never checks a surface name against a list. A name it has not
15
+ * seen gets default state the first time it is used, and a shell renders
16
+ * whichever surfaces it decides to render.
17
+ */
18
+ export type SurfaceName =
19
+ | 'header' // title bar / tab strip
20
+ | 'rail' // narrow icon strip (an activity bar)
21
+ | 'sidebar' // primary side region
22
+ | 'aside' // secondary side region
23
+ | 'main' // the content
24
+ | 'panel' // bottom drawer: logs, output, terminal
25
+ | 'status' // one-line status bar
26
+ | 'overlay' // modals, palettes, popovers, tooltips
27
+ | 'notify' // toasts
28
+ | (string & {});
29
+
30
+ export interface MountDisplay {
31
+ title?: string;
32
+ subtitle?: string;
33
+ icon?: string;
34
+ color?: StyleColor;
35
+ badge?: string | number;
36
+ /** Commands offered in this mount's header. */
37
+ actions?: string[];
38
+ }
39
+
40
+ export interface MountPolicy {
41
+ /** Survives a session snapshot. */
42
+ persistent?: boolean;
43
+ /** Removed on the next navigation. Previews want this. */
44
+ transient?: boolean;
45
+ closable?: boolean;
46
+ /** The user may move it to another surface. */
47
+ movable?: boolean;
48
+ }
49
+
50
+ /** An inline node, or a binding whose value is a node. */
51
+ export type MountTarget = ComponentNode | { path: BindingPath };
52
+
53
+ export interface Mount {
54
+ key: string;
55
+ surface: SurfaceName;
56
+ target: MountTarget;
57
+ display?: MountDisplay;
58
+ policy?: MountPolicy;
59
+ when?: WhenClause;
60
+ /** Relative paths inside this mount resolve against here. */
61
+ dataContext?: BindingPath;
62
+ order?: number;
63
+ }
64
+
65
+ /** How a surface arranges the several mounts it holds. */
66
+ export type LayoutName =
67
+ | 'single' // only the active one
68
+ | 'tabs' // tab strip plus the active one
69
+ | 'stack' // all of them, vertically
70
+ | 'split' // all of them, resizable
71
+ | 'rail' // icons only
72
+ | 'bar' // one line, horizontal
73
+ | 'inline' // all of them, no chrome
74
+ | 'floating' // positioned; overlay uses this
75
+ | 'toast'; // stacked, ephemeral
76
+
77
+ export interface SurfaceState {
78
+ /**
79
+ * Open, like `SurfaceName` and like `LayoutDefinition.name`. An application
80
+ * that registers a layout has to be able to put a surface into it, and the
81
+ * runtime never assumed a closed set anyway - `SurfaceArea` looks the name
82
+ * up in the registry and renders a diagnostic when nothing answers to it.
83
+ */
84
+ layout: LayoutName | (string & {});
85
+ activeKey: string | null;
86
+ visible: boolean;
87
+ /** Cells along the surface's cross axis. Unset lets the shell decide. */
88
+ size?: number;
89
+ collapsed?: boolean;
90
+ }
91
+
92
+ export interface SurfaceRegistry {
93
+ open(mount: Mount): Disposable;
94
+ close(surface: SurfaceName, key: string): void;
95
+ closeAll(surface: SurfaceName): void;
96
+ get(surface: SurfaceName, key: string): Mount | undefined;
97
+ mounts(surface: SurfaceName): Mount[];
98
+ activate(surface: SurfaceName, key: string): void;
99
+ state(surface: SurfaceName): SurfaceState;
100
+ setState(surface: SurfaceName, patch: Partial<SurfaceState>): void;
101
+ /** Resolve a resource's viewer and mount it. */
102
+ openResource(uri: string, options?: { surface?: SurfaceName; viewerId?: string; mode?: 'view' | 'edit' }): Promise<Disposable | null>;
103
+ }
104
+
105
+ /** A layout is a component that receives a surface's mounts and renders them. */
106
+ export interface LayoutDefinition {
107
+ name: LayoutName | (string & {});
108
+ /** Component name receiving `{ surface, mounts, state }`. */
109
+ component: string;
110
+ title?: string;
111
+ /** Surfaces this layout is offered for. Unset = all. */
112
+ surfaces?: SurfaceName[];
113
+ }
114
+
115
+ export interface LayoutRegistry {
116
+ register(def: LayoutDefinition): Disposable;
117
+ get(name: string): LayoutDefinition | undefined;
118
+ list(surface?: SurfaceName): LayoutDefinition[];
119
+ }
@@ -0,0 +1,93 @@
1
+ import type { Disposable } from './disposable.js';
2
+
3
+ /**
4
+ * Syntax highlighting.
5
+ *
6
+ * A highlighter names *scopes*, never colours. The theme owns the palette, so
7
+ * one JSON highlighter looks right on a dark console, a paper report and a
8
+ * sixteen-colour terminal without knowing that any of them exist - and a
9
+ * colourless terminal simply resolves every scope to the default foreground.
10
+ *
11
+ * The scope list is closed on purpose. An open vocabulary means a theme can
12
+ * only guess what a highlighter will emit, and the guess is what produces the
13
+ * uncoloured token nobody can explain.
14
+ */
15
+ export type SyntaxScope =
16
+ | 'plain'
17
+ | 'keyword'
18
+ | 'string'
19
+ | 'number'
20
+ | 'boolean'
21
+ | 'null'
22
+ | 'comment'
23
+ | 'punctuation'
24
+ /** An object key, a column name, a field label - the left of a pair. */
25
+ | 'key'
26
+ | 'operator'
27
+ | 'type'
28
+ | 'function'
29
+ | 'tag'
30
+ | 'attribute'
31
+ | 'regexp'
32
+ | 'escape'
33
+ /** Syntactically wrong. Worth seeing rather than hiding. */
34
+ | 'invalid';
35
+
36
+ export const SYNTAX_SCOPES: readonly SyntaxScope[] = [
37
+ 'plain', 'keyword', 'string', 'number', 'boolean', 'null', 'comment',
38
+ 'punctuation', 'key', 'operator', 'type', 'function', 'tag', 'attribute',
39
+ 'regexp', 'escape', 'invalid',
40
+ ];
41
+
42
+ /** A run of text with one scope. Never spans a newline. */
43
+ export interface SyntaxToken {
44
+ text: string;
45
+ scope: SyntaxScope;
46
+ }
47
+
48
+ /** A scored region of the source, before it is split into lines. */
49
+ export interface SyntaxSpan {
50
+ start: number;
51
+ end: number;
52
+ scope: SyntaxScope;
53
+ }
54
+
55
+ export interface HighlighterDefinition {
56
+ id: string;
57
+ title?: string;
58
+ /** Resource kinds this claims: `file.data.json`, `log.stream`. */
59
+ kinds?: string[];
60
+ /** Filename globs, for when nothing has classified the resource yet. */
61
+ extensions?: string[];
62
+ /** Higher wins when several match. */
63
+ priority?: number;
64
+ /**
65
+ * Tokenise a whole document into one array per line.
66
+ *
67
+ * The result must have exactly as many entries as `text.split('\n')`, and
68
+ * the tokens on each line must join back to that line. The registry checks
69
+ * both and falls back to plain text rather than paint a file that no longer
70
+ * lines up with its own gutter.
71
+ */
72
+ tokenize(text: string): SyntaxToken[][];
73
+ }
74
+
75
+ export interface SyntaxQuery {
76
+ /** Resource kind, when the resource has been classified. */
77
+ kind?: string;
78
+ /** URI or filename, matched against `extensions`. */
79
+ uri?: string;
80
+ /** An explicit highlighter id, which wins over everything. */
81
+ language?: string;
82
+ }
83
+
84
+ export interface SyntaxRegistry {
85
+ register(def: HighlighterDefinition): Disposable;
86
+ unregister(id: string): void;
87
+ get(id: string): HighlighterDefinition | undefined;
88
+ list(): HighlighterDefinition[];
89
+ /** The best highlighter for this resource, or undefined. */
90
+ find(query: SyntaxQuery): HighlighterDefinition | undefined;
91
+ /** Tokenise, falling back to one plain token per line. */
92
+ tokenize(text: string, query?: SyntaxQuery): SyntaxToken[][];
93
+ }
@@ -0,0 +1,58 @@
1
+ import type { Disposable } from './disposable.js';
2
+ import type { Size } from './geometry.js';
3
+ import type { TerminalCapabilities, CapabilityOverrides } from './capabilities.js';
4
+ import type { InputEvent } from './input.js';
5
+
6
+ /**
7
+ * Which capabilities the session wants turned on. The adapter records what it
8
+ * actually acquired, and `release` undoes exactly that and nothing else -
9
+ * which is the whole difference between a managed session and an embedded one.
10
+ */
11
+ export interface TerminalSessionOptions {
12
+ /** TextUI owns setup and teardown of the terminal. */
13
+ managed?: boolean;
14
+ altScreen?: boolean;
15
+ mouse?: boolean;
16
+ wheel?: boolean;
17
+ focusEvents?: boolean;
18
+ paste?: boolean;
19
+ hideCursor?: boolean;
20
+ /** Kitty keyboard disambiguation, when available. */
21
+ enhancedKeys?: boolean;
22
+ title?: string;
23
+ }
24
+
25
+ /** What the adapter actually turned on, so release is exact. */
26
+ export interface AcquiredState {
27
+ altScreen: boolean;
28
+ mouse: boolean;
29
+ wheel: boolean;
30
+ focusEvents: boolean;
31
+ paste: boolean;
32
+ cursorHidden: boolean;
33
+ enhancedKeys: boolean;
34
+ rawMode: boolean;
35
+ titleSet: boolean;
36
+ }
37
+
38
+ export interface TerminalAdapter extends Disposable {
39
+ readonly id: string;
40
+ size(): Size;
41
+ capabilities(): TerminalCapabilities;
42
+ /** Explicit overrides win over detection. */
43
+ setCapabilityOverrides(overrides: CapabilityOverrides): void;
44
+
45
+ acquire(options: TerminalSessionOptions): Promise<AcquiredState> | AcquiredState;
46
+ release(): Promise<void> | void;
47
+ readonly acquired: AcquiredState | null;
48
+
49
+ write(data: string): void;
50
+ flush(): Promise<void> | void;
51
+
52
+ onInput(fn: (event: InputEvent) => void): Disposable;
53
+ onResize(fn: (size: Size) => void): Disposable;
54
+
55
+ /** OSC 52, when the terminal allows it. */
56
+ writeClipboard?(text: string): void;
57
+ setTitle?(title: string): void;
58
+ }
@@ -0,0 +1,121 @@
1
+ import type { Color } from './cells.js';
2
+ import type { BorderChars, BorderStyle, ColorToken, Density, Style, StyleColor } from './style.js';
3
+ import type { SyntaxScope } from './syntax.js';
4
+ import type { Disposable } from './disposable.js';
5
+ import type { TerminalCapabilities } from './capabilities.js';
6
+
7
+ /** Spacing scale, in cells. Terminals have no sub-cell spacing. */
8
+ export interface ThemeSpacing {
9
+ none: number;
10
+ xs: number;
11
+ sm: number;
12
+ md: number;
13
+ lg: number;
14
+ xl: number;
15
+ }
16
+
17
+ /**
18
+ * The glyph vocabulary. Separated from colour because a 16-colour terminal may
19
+ * still be full-Unicode, and an ascii-only terminal may be truecolor.
20
+ */
21
+ export interface ThemeGlyphs {
22
+ /** Status dots, bullets, arrows - keyed by role so a component names a role. */
23
+ bulletFilled: string;
24
+ bulletHollow: string;
25
+ bulletHalf: string;
26
+ check: string;
27
+ cross: string;
28
+ warning: string;
29
+ info: string;
30
+ chevronRight: string;
31
+ chevronDown: string;
32
+ chevronLeft: string;
33
+ chevronUp: string;
34
+ arrowUp: string;
35
+ arrowDown: string;
36
+ ellipsis: string;
37
+ search: string;
38
+ radioOn: string;
39
+ radioOff: string;
40
+ checkboxOn: string;
41
+ checkboxOff: string;
42
+ checkboxMixed: string;
43
+ /** Eight levels for sparklines and bar charts. */
44
+ blocks: readonly string[];
45
+ /** Progress bar track and fill. */
46
+ progressFull: string;
47
+ progressEmpty: string;
48
+ progressPartial: readonly string[];
49
+ spinner: readonly string[];
50
+ /** Text cursor when the terminal cursor is unavailable. */
51
+ caret: string;
52
+ separator: string;
53
+ /** Path separator in a breadcrumb. */
54
+ breadcrumb: string;
55
+ /**
56
+ * Where a region sits in the frame.
57
+ *
58
+ * One family, so a list of regions reads as a diagram rather than as six
59
+ * unrelated marks: the glyph says *where*, and `regionOff` says the region
60
+ * is not on screen. A tick cannot say where, which is why a list of ticks
61
+ * needs a second column of words to be readable at all.
62
+ */
63
+ regionTop: string;
64
+ regionBottom: string;
65
+ regionLeft: string;
66
+ regionRight: string;
67
+ regionCentre: string;
68
+ regionOff: string;
69
+ }
70
+
71
+ export interface ThemeDefinition {
72
+ id: string;
73
+ name: string;
74
+ appearance: 'light' | 'dark';
75
+ /** Extend another registered theme; only the differences need stating. */
76
+ extends?: string;
77
+ colors: Partial<Record<ColorToken, Color>>;
78
+ spacing?: Partial<ThemeSpacing>;
79
+ glyphs?: Partial<ThemeGlyphs>;
80
+ /** Default border style for chrome. `'none'` gives the borderless look. */
81
+ border?: BorderStyle;
82
+ borderChars?: Partial<Record<BorderStyle, BorderChars>>;
83
+ density?: Density;
84
+ /** Per-component style overrides, keyed by component name then variant. */
85
+ components?: Record<string, Record<string, Style>>;
86
+ /**
87
+ * Colours for syntax scopes. Every scope has a default drawn from the
88
+ * semantic palette, so a theme states only what it wants to differ - and a
89
+ * theme that states nothing still highlights.
90
+ */
91
+ syntax?: Partial<Record<SyntaxScope, StyleColor>>;
92
+ }
93
+
94
+ /** A theme after `extends` resolution and capability downgrade. */
95
+ export interface ResolvedTheme {
96
+ id: string;
97
+ name: string;
98
+ appearance: 'light' | 'dark';
99
+ colors: Record<ColorToken, Color>;
100
+ spacing: ThemeSpacing;
101
+ glyphs: ThemeGlyphs;
102
+ border: BorderStyle;
103
+ density: Density;
104
+ components: Record<string, Record<string, Style>>;
105
+ /** Every syntax scope, resolved to a colour. */
106
+ syntax: Record<SyntaxScope, Color>;
107
+ /** Resolve a token (or pass a literal colour through). */
108
+ color(token: string): Color;
109
+ borderChars(style?: BorderStyle): BorderChars;
110
+ /** Component style for a name + variant list, merged in order. */
111
+ styleFor(component: string, variants?: string[]): Style;
112
+ }
113
+
114
+ export interface ThemeRegistry {
115
+ register(def: ThemeDefinition): Disposable;
116
+ unregister(id: string): void;
117
+ get(id: string): ThemeDefinition | undefined;
118
+ list(): ThemeDefinition[];
119
+ /** Resolve `extends`, apply capability downgrade, return a usable theme. */
120
+ resolve(id: string, caps: TerminalCapabilities): ResolvedTheme;
121
+ }
@@ -0,0 +1,21 @@
1
+ import type { BindingPath } from './graph.js';
2
+
3
+ export type ContextValue = string | number | boolean | null;
4
+
5
+ /**
6
+ * A small expression over store paths and context keys. Chrome that should not
7
+ * exist for this user does not mount, rather than mounting disabled.
8
+ *
9
+ * "$/session/role == 'admin'"
10
+ * "$/modus/capabilities/mouse && !$/ui/sidebar/collapsed"
11
+ * "$/modus/size/width >= 100"
12
+ */
13
+ export type WhenClause = string;
14
+
15
+ export interface WhenEngine {
16
+ evaluate(clause: WhenClause | undefined, extra?: Record<string, ContextValue>): boolean;
17
+ /** Paths a clause reads, so a caller can subscribe to exactly those. */
18
+ dependencies(clause: WhenClause): BindingPath[];
19
+ setContext(key: string, value: ContextValue): void;
20
+ getContext(key: string): ContextValue | undefined;
21
+ }