@effect-tui/core 0.1.0 → 0.1.4

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 (271) hide show
  1. package/README.md +31 -11
  2. package/dist/ansi.d.ts +127 -32
  3. package/dist/ansi.d.ts.map +1 -1
  4. package/dist/ansi.js +159 -37
  5. package/dist/ansi.js.map +1 -1
  6. package/dist/colors.d.ts +139 -0
  7. package/dist/colors.d.ts.map +1 -0
  8. package/dist/colors.js +339 -0
  9. package/dist/colors.js.map +1 -0
  10. package/dist/index.d.ts +6 -10
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +13 -11
  13. package/dist/index.js.map +1 -1
  14. package/dist/keys.d.ts +21 -0
  15. package/dist/keys.d.ts.map +1 -1
  16. package/dist/keys.js +199 -58
  17. package/dist/keys.js.map +1 -1
  18. package/dist/layout/axis-helpers.d.ts +19 -0
  19. package/dist/layout/axis-helpers.d.ts.map +1 -0
  20. package/dist/layout/axis-helpers.js +19 -0
  21. package/dist/layout/axis-helpers.js.map +1 -0
  22. package/dist/output.d.ts +59 -0
  23. package/dist/output.d.ts.map +1 -0
  24. package/dist/output.js +142 -0
  25. package/dist/output.js.map +1 -0
  26. package/dist/render/buffer.d.ts.map +1 -1
  27. package/dist/render/buffer.js +6 -25
  28. package/dist/render/buffer.js.map +1 -1
  29. package/dist/render/graphemes.d.ts +15 -0
  30. package/dist/render/graphemes.d.ts.map +1 -0
  31. package/dist/render/graphemes.js +28 -0
  32. package/dist/render/graphemes.js.map +1 -0
  33. package/dist/render/measure.d.ts +1 -0
  34. package/dist/render/measure.d.ts.map +1 -1
  35. package/dist/render/measure.js +14 -36
  36. package/dist/render/measure.js.map +1 -1
  37. package/dist/render/palette.d.ts.map +1 -1
  38. package/dist/render/palette.js +26 -1
  39. package/dist/render/palette.js.map +1 -1
  40. package/dist/render/segmenter.d.ts +8 -0
  41. package/dist/render/segmenter.d.ts.map +1 -0
  42. package/dist/render/segmenter.js +23 -0
  43. package/dist/render/segmenter.js.map +1 -0
  44. package/dist/render/surface.d.ts +6 -32
  45. package/dist/render/surface.d.ts.map +1 -1
  46. package/dist/render/surface.js +11 -80
  47. package/dist/render/surface.js.map +1 -1
  48. package/dist/runtime/backend_node.d.ts.map +1 -1
  49. package/dist/runtime/backend_node.js.map +1 -1
  50. package/dist/tailwind-colors.d.ts +291 -0
  51. package/dist/tailwind-colors.d.ts.map +1 -0
  52. package/dist/tailwind-colors.js +291 -0
  53. package/dist/tailwind-colors.js.map +1 -0
  54. package/dist/types.d.ts +15 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +3 -0
  57. package/dist/types.js.map +1 -0
  58. package/package.json +55 -55
  59. package/src/ansi.ts +201 -73
  60. package/src/colors.ts +468 -0
  61. package/src/index.ts +28 -14
  62. package/src/keys.ts +467 -287
  63. package/src/layout/axis-helpers.ts +33 -0
  64. package/src/output.ts +175 -0
  65. package/src/render/buffer.ts +161 -184
  66. package/src/render/graphemes.ts +34 -0
  67. package/src/render/measure.ts +15 -38
  68. package/src/render/palette.ts +98 -77
  69. package/src/render/segmenter.ts +27 -0
  70. package/src/render/surface.ts +139 -225
  71. package/src/runtime/backend_node.ts +71 -71
  72. package/src/tailwind-colors.ts +295 -0
  73. package/src/types.ts +18 -0
  74. package/dist/anim.d.ts +0 -4
  75. package/dist/anim.d.ts.map +0 -1
  76. package/dist/anim.js +0 -5
  77. package/dist/anim.js.map +0 -1
  78. package/dist/layout/linearStack.d.ts +0 -17
  79. package/dist/layout/linearStack.d.ts.map +0 -1
  80. package/dist/layout/linearStack.js +0 -86
  81. package/dist/layout/linearStack.js.map +0 -1
  82. package/dist/motion-value.d.ts +0 -58
  83. package/dist/motion-value.d.ts.map +0 -1
  84. package/dist/motion-value.js +0 -250
  85. package/dist/motion-value.js.map +0 -1
  86. package/dist/present/display.d.ts +0 -58
  87. package/dist/present/display.d.ts.map +0 -1
  88. package/dist/present/display.js +0 -168
  89. package/dist/present/display.js.map +0 -1
  90. package/dist/present/writers/fullscreen.d.ts +0 -19
  91. package/dist/present/writers/fullscreen.d.ts.map +0 -1
  92. package/dist/present/writers/fullscreen.js +0 -55
  93. package/dist/present/writers/fullscreen.js.map +0 -1
  94. package/dist/present/writers/inline.d.ts +0 -20
  95. package/dist/present/writers/inline.d.ts.map +0 -1
  96. package/dist/present/writers/inline.js +0 -92
  97. package/dist/present/writers/inline.js.map +0 -1
  98. package/dist/render/color-utils.d.ts +0 -18
  99. package/dist/render/color-utils.d.ts.map +0 -1
  100. package/dist/render/color-utils.js +0 -58
  101. package/dist/render/color-utils.js.map +0 -1
  102. package/dist/render/diff.d.ts +0 -30
  103. package/dist/render/diff.d.ts.map +0 -1
  104. package/dist/render/diff.js +0 -83
  105. package/dist/render/diff.js.map +0 -1
  106. package/dist/spring-physics.d.ts +0 -36
  107. package/dist/spring-physics.d.ts.map +0 -1
  108. package/dist/spring-physics.js +0 -113
  109. package/dist/spring-physics.js.map +0 -1
  110. package/dist/spring.d.ts +0 -73
  111. package/dist/spring.d.ts.map +0 -1
  112. package/dist/spring.js +0 -136
  113. package/dist/spring.js.map +0 -1
  114. package/dist/ui/containers/canvas.d.ts +0 -13
  115. package/dist/ui/containers/canvas.d.ts.map +0 -1
  116. package/dist/ui/containers/canvas.js +0 -16
  117. package/dist/ui/containers/canvas.js.map +0 -1
  118. package/dist/ui/containers/geometry-reader.d.ts +0 -17
  119. package/dist/ui/containers/geometry-reader.d.ts.map +0 -1
  120. package/dist/ui/containers/geometry-reader.js +0 -24
  121. package/dist/ui/containers/geometry-reader.js.map +0 -1
  122. package/dist/ui/containers/hstack.d.ts +0 -12
  123. package/dist/ui/containers/hstack.d.ts.map +0 -1
  124. package/dist/ui/containers/hstack.js +0 -28
  125. package/dist/ui/containers/hstack.js.map +0 -1
  126. package/dist/ui/containers/scroll.d.ts +0 -28
  127. package/dist/ui/containers/scroll.d.ts.map +0 -1
  128. package/dist/ui/containers/scroll.js +0 -97
  129. package/dist/ui/containers/scroll.js.map +0 -1
  130. package/dist/ui/containers/shared.d.ts +0 -12
  131. package/dist/ui/containers/shared.d.ts.map +0 -1
  132. package/dist/ui/containers/shared.js +0 -19
  133. package/dist/ui/containers/shared.js.map +0 -1
  134. package/dist/ui/containers/vstack.d.ts +0 -12
  135. package/dist/ui/containers/vstack.d.ts.map +0 -1
  136. package/dist/ui/containers/vstack.js +0 -28
  137. package/dist/ui/containers/vstack.js.map +0 -1
  138. package/dist/ui/containers/zstack.d.ts +0 -14
  139. package/dist/ui/containers/zstack.d.ts.map +0 -1
  140. package/dist/ui/containers/zstack.js +0 -36
  141. package/dist/ui/containers/zstack.js.map +0 -1
  142. package/dist/ui/core/geometry-store.d.ts +0 -22
  143. package/dist/ui/core/geometry-store.d.ts.map +0 -1
  144. package/dist/ui/core/geometry-store.js +0 -29
  145. package/dist/ui/core/geometry-store.js.map +0 -1
  146. package/dist/ui/core/geometry.d.ts +0 -34
  147. package/dist/ui/core/geometry.d.ts.map +0 -1
  148. package/dist/ui/core/geometry.js +0 -14
  149. package/dist/ui/core/geometry.js.map +0 -1
  150. package/dist/ui/core/view.d.ts +0 -25
  151. package/dist/ui/core/view.d.ts.map +0 -1
  152. package/dist/ui/core/view.js +0 -34
  153. package/dist/ui/core/view.js.map +0 -1
  154. package/dist/ui/index.d.ts +0 -44
  155. package/dist/ui/index.d.ts.map +0 -1
  156. package/dist/ui/index.js +0 -39
  157. package/dist/ui/index.js.map +0 -1
  158. package/dist/ui/inlinetext.d.ts +0 -24
  159. package/dist/ui/inlinetext.d.ts.map +0 -1
  160. package/dist/ui/inlinetext.js +0 -131
  161. package/dist/ui/inlinetext.js.map +0 -1
  162. package/dist/ui/install.d.ts +0 -22
  163. package/dist/ui/install.d.ts.map +0 -1
  164. package/dist/ui/install.js +0 -66
  165. package/dist/ui/install.js.map +0 -1
  166. package/dist/ui/markdown.d.ts +0 -40
  167. package/dist/ui/markdown.d.ts.map +0 -1
  168. package/dist/ui/markdown.js +0 -351
  169. package/dist/ui/markdown.js.map +0 -1
  170. package/dist/ui/modifiers/border.d.ts +0 -33
  171. package/dist/ui/modifiers/border.d.ts.map +0 -1
  172. package/dist/ui/modifiers/border.js +0 -82
  173. package/dist/ui/modifiers/border.js.map +0 -1
  174. package/dist/ui/modifiers/fill.d.ts +0 -14
  175. package/dist/ui/modifiers/fill.d.ts.map +0 -1
  176. package/dist/ui/modifiers/fill.js +0 -25
  177. package/dist/ui/modifiers/fill.js.map +0 -1
  178. package/dist/ui/modifiers/frame.d.ts +0 -23
  179. package/dist/ui/modifiers/frame.d.ts.map +0 -1
  180. package/dist/ui/modifiers/frame.js +0 -54
  181. package/dist/ui/modifiers/frame.js.map +0 -1
  182. package/dist/ui/modifiers/offset.d.ts +0 -15
  183. package/dist/ui/modifiers/offset.d.ts.map +0 -1
  184. package/dist/ui/modifiers/offset.js +0 -21
  185. package/dist/ui/modifiers/offset.js.map +0 -1
  186. package/dist/ui/modifiers/opacity.d.ts +0 -15
  187. package/dist/ui/modifiers/opacity.d.ts.map +0 -1
  188. package/dist/ui/modifiers/opacity.js +0 -95
  189. package/dist/ui/modifiers/opacity.js.map +0 -1
  190. package/dist/ui/modifiers/padding.d.ts +0 -20
  191. package/dist/ui/modifiers/padding.d.ts.map +0 -1
  192. package/dist/ui/modifiers/padding.js +0 -36
  193. package/dist/ui/modifiers/padding.js.map +0 -1
  194. package/dist/ui/modifiers/styled.d.ts +0 -14
  195. package/dist/ui/modifiers/styled.d.ts.map +0 -1
  196. package/dist/ui/modifiers/styled.js +0 -26
  197. package/dist/ui/modifiers/styled.js.map +0 -1
  198. package/dist/ui/primitives/rectangle.d.ts +0 -15
  199. package/dist/ui/primitives/rectangle.d.ts.map +0 -1
  200. package/dist/ui/primitives/rectangle.js +0 -23
  201. package/dist/ui/primitives/rectangle.js.map +0 -1
  202. package/dist/ui/primitives/spacer.d.ts +0 -13
  203. package/dist/ui/primitives/spacer.d.ts.map +0 -1
  204. package/dist/ui/primitives/spacer.js +0 -16
  205. package/dist/ui/primitives/spacer.js.map +0 -1
  206. package/dist/ui/primitives/text.d.ts +0 -15
  207. package/dist/ui/primitives/text.d.ts.map +0 -1
  208. package/dist/ui/primitives/text.js +0 -79
  209. package/dist/ui/primitives/text.js.map +0 -1
  210. package/dist/ui/primitives/wrapped-text.d.ts +0 -30
  211. package/dist/ui/primitives/wrapped-text.d.ts.map +0 -1
  212. package/dist/ui/primitives/wrapped-text.js +0 -117
  213. package/dist/ui/primitives/wrapped-text.js.map +0 -1
  214. package/dist/ui/shinytext.d.ts +0 -66
  215. package/dist/ui/shinytext.d.ts.map +0 -1
  216. package/dist/ui/shinytext.js +0 -99
  217. package/dist/ui/shinytext.js.map +0 -1
  218. package/dist/ui/text/layout.d.ts +0 -35
  219. package/dist/ui/text/layout.d.ts.map +0 -1
  220. package/dist/ui/text/layout.js +0 -102
  221. package/dist/ui/text/layout.js.map +0 -1
  222. package/dist/ui/textinput.d.ts +0 -140
  223. package/dist/ui/textinput.d.ts.map +0 -1
  224. package/dist/ui/textinput.js +0 -402
  225. package/dist/ui/textinput.js.map +0 -1
  226. package/dist/ui/view-constructors.d.ts +0 -72
  227. package/dist/ui/view-constructors.d.ts.map +0 -1
  228. package/dist/ui/view-constructors.js +0 -74
  229. package/dist/ui/view-constructors.js.map +0 -1
  230. package/src/anim.ts +0 -5
  231. package/src/layout/linearStack.ts +0 -115
  232. package/src/motion-value.ts +0 -335
  233. package/src/present/display.ts +0 -206
  234. package/src/present/writers/fullscreen.ts +0 -58
  235. package/src/present/writers/inline.ts +0 -101
  236. package/src/render/color-utils.ts +0 -60
  237. package/src/render/diff.ts +0 -95
  238. package/src/spring-physics.ts +0 -151
  239. package/src/spring.ts +0 -234
  240. package/src/ui/__snapshots__/wrappedtext.test.ts.snap +0 -57
  241. package/src/ui/containers/canvas.ts +0 -18
  242. package/src/ui/containers/geometry-reader.ts +0 -32
  243. package/src/ui/containers/hstack.ts +0 -33
  244. package/src/ui/containers/scroll.ts +0 -106
  245. package/src/ui/containers/shared.ts +0 -27
  246. package/src/ui/containers/vstack.ts +0 -34
  247. package/src/ui/containers/zstack.ts +0 -37
  248. package/src/ui/core/geometry-store.ts +0 -42
  249. package/src/ui/core/geometry.ts +0 -30
  250. package/src/ui/core/view.ts +0 -49
  251. package/src/ui/index.ts +0 -84
  252. package/src/ui/inlinetext.ts +0 -135
  253. package/src/ui/install.ts +0 -110
  254. package/src/ui/markdown.test.ts +0 -74
  255. package/src/ui/markdown.ts +0 -388
  256. package/src/ui/modifiers/border.ts +0 -100
  257. package/src/ui/modifiers/fill.ts +0 -28
  258. package/src/ui/modifiers/frame.ts +0 -74
  259. package/src/ui/modifiers/offset.ts +0 -23
  260. package/src/ui/modifiers/opacity.ts +0 -93
  261. package/src/ui/modifiers/padding.ts +0 -53
  262. package/src/ui/modifiers/styled.ts +0 -31
  263. package/src/ui/primitives/rectangle.ts +0 -25
  264. package/src/ui/primitives/spacer.ts +0 -18
  265. package/src/ui/primitives/text.ts +0 -85
  266. package/src/ui/primitives/wrapped-text.ts +0 -131
  267. package/src/ui/shinytext.ts +0 -159
  268. package/src/ui/text/layout.ts +0 -119
  269. package/src/ui/textinput.ts +0 -496
  270. package/src/ui/view-constructors.ts +0 -96
  271. package/src/ui/wrappedtext.test.ts +0 -138
package/package.json CHANGED
@@ -1,57 +1,57 @@
1
1
  {
2
- "name": "@effect-tui/core",
3
- "version": "0.1.0",
4
- "description": "Terminal UI library built with Effect",
5
- "type": "module",
6
- "files": [
7
- "dist",
8
- "src",
9
- "README.md",
10
- "LICENSE"
11
- ],
12
- "repository": {
13
- "type": "git",
14
- "url": "https://github.com/kitlangton/effect-tui.git"
15
- },
16
- "homepage": "https://github.com/kitlangton/effect-tui",
17
- "bugs": "https://github.com/kitlangton/effect-tui/issues",
18
- "exports": {
19
- ".": {
20
- "import": "./dist/index.js",
21
- "types": "./dist/index.d.ts"
22
- }
23
- },
24
- "types": "./dist/index.d.ts",
25
- "keywords": [
26
- "terminal",
27
- "tui",
28
- "effect",
29
- "cli",
30
- "console"
31
- ],
32
- "author": "Kit Langton",
33
- "license": "MIT",
34
- "publishConfig": {
35
- "access": "public",
36
- "tag": "alpha"
37
- },
38
- "scripts": {
39
- "build": "tsc -p .",
40
- "typecheck": "tsc -p . --noEmit",
41
- "test": "vitest run",
42
- "test:watch": "vitest",
43
- "format": "biome format --write .",
44
- "format:check": "biome format .",
45
- "prepublishOnly": "bun run typecheck && bun run build"
46
- },
47
- "peerDependencies": {
48
- "effect": "^3.0.0"
49
- },
50
- "devDependencies": {
51
- "@effect/vitest": "^0.27.0",
52
- "@types/node": "^24.10.1",
53
- "effect": "^3.19.8",
54
- "typescript": "^5.9.3",
55
- "vitest": "^4.0.14"
56
- }
2
+ "name": "@effect-tui/core",
3
+ "version": "0.1.4",
4
+ "description": "Terminal UI library built with Effect",
5
+ "type": "module",
6
+ "files": [
7
+ "dist",
8
+ "src",
9
+ "README.md",
10
+ "LICENSE"
11
+ ],
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/kitlangton/effect-tui.git"
15
+ },
16
+ "homepage": "https://github.com/kitlangton/effect-tui",
17
+ "bugs": "https://github.com/kitlangton/effect-tui/issues",
18
+ "exports": {
19
+ ".": {
20
+ "bun": "./src/index.ts",
21
+ "import": "./dist/index.js",
22
+ "types": "./dist/index.d.ts"
23
+ }
24
+ },
25
+ "types": "./dist/index.d.ts",
26
+ "keywords": [
27
+ "terminal",
28
+ "tui",
29
+ "effect",
30
+ "cli",
31
+ "console"
32
+ ],
33
+ "author": "Kit Langton",
34
+ "license": "MIT",
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "scripts": {
39
+ "build": "tsc -p .",
40
+ "typecheck": "tsc -p . --noEmit",
41
+ "test": "vitest run",
42
+ "test:watch": "vitest",
43
+ "format": "biome format --write .",
44
+ "format:check": "biome format .",
45
+ "prepublishOnly": "bun run typecheck && bun run build"
46
+ },
47
+ "peerDependencies": {
48
+ "effect": "^3.19.13"
49
+ },
50
+ "devDependencies": {
51
+ "@effect/vitest": "^0.27.0",
52
+ "@types/node": "^25.0.3",
53
+ "effect": "^3.19.13",
54
+ "typescript": "^5.9.3",
55
+ "vitest": "^4.0.16"
56
+ }
57
57
  }
package/src/ansi.ts CHANGED
@@ -1,83 +1,211 @@
1
- // ANSI escape sequences and terminal control utilities
1
+ // ansi.ts — ANSI escape sequences for terminal control
2
2
 
3
3
  /** CSI prefix (ESC [) */
4
4
  const CSI = "\x1b["
5
5
 
6
- /** Basic ANSI codes and helpers */
6
+ /** ANSI escape sequence primitives */
7
7
  export const ANSI = {
8
- /** Reset all attributes */
9
- reset: `${CSI}0m`,
10
-
11
- /** Cursor control */
12
- cursor: {
13
- /** Hide cursor */
14
- hide: `${CSI}?25l`,
15
- /** Show cursor */
16
- show: `${CSI}?25h`,
17
- /** Move cursor to home position (1,1) */
18
- home: `${CSI}H`,
19
- /** Move cursor to 1-based row/column */
20
- to: (row1: number, col1: number) => `${CSI}${row1};${col1}H`,
21
- /** Move cursor to 1-based column on current row */
22
- toCol: (col1: number) => `${CSI}${col1}G`,
23
- },
24
-
25
- /** Screen control */
26
- screen: {
27
- /** Enter alternate screen buffer */
28
- altEnter: `${CSI}?1049h`,
29
- /** Exit alternate screen buffer */
30
- altExit: `${CSI}?1049l`,
31
- /** Clear entire display */
32
- clear: `${CSI}2J`,
33
- /** Clear scrollback buffer */
34
- clearScrollback: `${CSI}3J`,
35
- },
36
-
37
- /** Scrolling */
38
- scroll: {
39
- /** Scroll up by n lines */
40
- up: (n: number) => `${CSI}${n}S`,
41
- },
42
-
43
- /** Device Status Reports / queries */
44
- report: {
45
- /** Report Cursor Position (response: ESC [ row ; col R) */
46
- cursorPosition: `${CSI}6n`,
47
- },
48
-
49
- /** Bracketed paste mode */
50
- paste: {
51
- bracketed: {
52
- on: `${CSI}?2004h`,
53
- off: `${CSI}?2004l`,
54
- },
55
- },
56
-
57
- /** Mouse reporting toggles */
58
- mouse: {
59
- /** Enable button tracking and SGR coordinates */
60
- on: `${CSI}?1002h${CSI}?1006h`,
61
- /** Disable SGR coords and button tracking */
62
- off: `${CSI}?1006l${CSI}?1002l`,
63
- },
64
- } as const
8
+ /** Cursor control */
9
+ cursor: {
10
+ /** Move cursor to 1-based row/column position */
11
+ to: (x: number, y: number) => `${CSI}${y};${x}H`,
12
+ /** Move cursor to 1-based column on current row */
13
+ toCol: (col: number) => `${CSI}${col}G`,
14
+ /** Move cursor up by n rows */
15
+ up: (n: number) => (n > 0 ? `${CSI}${n}A` : ""),
16
+ /** Move cursor down by n rows */
17
+ down: (n: number) => (n > 0 ? `${CSI}${n}B` : ""),
18
+ /** Hide cursor */
19
+ hide: `${CSI}?25l`,
20
+ /** Show cursor */
21
+ show: `${CSI}?25h`,
22
+ /** Move cursor to start of current line */
23
+ startOfLine: "\r",
24
+ /** Move cursor to home position (1,1) */
25
+ home: `${CSI}H`,
26
+ },
65
27
 
66
- /** Terminal session control utilities (compositions of ANSI primitives) */
67
- export const Terminal = {
68
- /** Enter full-screen mode: alternate screen + hide cursor */
69
- enterFullscreen: ANSI.screen.altEnter + ANSI.cursor.hide,
28
+ /** Line control */
29
+ line: {
30
+ /** Clear entire line */
31
+ clear: `${CSI}2K`,
32
+ /** Clear from cursor to end of line */
33
+ clearToEnd: `${CSI}0K`,
34
+ },
35
+
36
+ /** Screen control */
37
+ screen: {
38
+ /** Enter alternate screen buffer */
39
+ enterAlt: `${CSI}?1049h`,
40
+ /** Exit alternate screen buffer */
41
+ exitAlt: `${CSI}?1049l`,
42
+ /** Clear entire screen */
43
+ clear: `${CSI}2J`,
44
+ /** Clear from cursor to end of screen */
45
+ clearToEnd: `${CSI}J`,
46
+ /** Clear scrollback buffer */
47
+ clearScrollback: `${CSI}3J`,
48
+ },
49
+
50
+ /** Mouse reporting */
51
+ mouse: {
52
+ /** Enable SGR extended mouse mode with any-event tracking (scroll wheel support) */
53
+ enable: `${CSI}?1003h${CSI}?1006h`,
54
+ /** Disable mouse tracking */
55
+ disable: `${CSI}?1006l${CSI}?1003l`,
56
+ },
57
+
58
+ /** Bracketed paste mode */
59
+ paste: {
60
+ /** Enable bracketed paste */
61
+ enable: `${CSI}?2004h`,
62
+ /** Disable bracketed paste */
63
+ disable: `${CSI}?2004l`,
64
+ /** Paste start marker */
65
+ startMarker: `${CSI}200~`,
66
+ /** Paste end marker */
67
+ endMarker: `${CSI}201~`,
68
+ },
69
+
70
+ /** Line reflow control (DEC mode 2028 - limited terminal support) */
71
+ reflow: {
72
+ /** Disable line reflow on resize (Contour, some others) */
73
+ disable: `${CSI}?2028l`,
74
+ /** Enable line reflow on resize (default) */
75
+ enable: `${CSI}?2028h`,
76
+ },
77
+
78
+ /** Scroll region control (DECSTBM) */
79
+ scrollRegion: {
80
+ /** Set scroll region to rows [top, bottom] (1-indexed, inclusive) */
81
+ set: (top: number, bottom: number) => `${CSI}${top};${bottom}r`,
82
+ /** Reset scroll region to full screen */
83
+ reset: `${CSI}r`,
84
+ },
85
+
86
+ /** Line insertion/deletion */
87
+ lines: {
88
+ /** Insert n blank lines at cursor, pushing content down (IL) */
89
+ insert: (n: number) => (n > 0 ? `${CSI}${n}L` : ""),
90
+ /** Delete n lines at cursor, pulling content up (DL) */
91
+ delete: (n: number) => (n > 0 ? `${CSI}${n}M` : ""),
92
+ },
70
93
 
71
- /** Exit full-screen mode: reset + show cursor + exit alternate screen */
72
- exitFullscreen: ANSI.reset + ANSI.cursor.show + ANSI.screen.altExit,
94
+ /** Cursor save/restore (DECSC/DECRC) */
95
+ cursorState: {
96
+ /** Save cursor position and attributes */
97
+ save: "\x1b7",
98
+ /** Restore cursor position and attributes */
99
+ restore: "\x1b8",
100
+ },
73
101
 
74
- /** Clear screen and move cursor to home */
75
- clearAndHome: ANSI.screen.clear + ANSI.cursor.home,
102
+ /**
103
+ * Kitty keyboard protocol
104
+ * @see https://sw.kovidgoyal.net/kitty/keyboard-protocol/
105
+ * Enables enhanced key reporting with modifier detection for Ctrl+Shift+key combos
106
+ */
107
+ keyboard: {
108
+ /**
109
+ * Enable Kitty keyboard protocol with flags.
110
+ * Flag 1 (disambiguate): Reports Ctrl+C as CSI sequence instead of raw ETX,
111
+ * allowing detection of Ctrl+Shift+C vs Ctrl+C.
112
+ * Supported by: Kitty, iTerm2 3.5+, WezTerm, Ghostty, foot, Contour, rio
113
+ * NOTE: Many terminals intercept Ctrl+Shift+C for their own copy - may need
114
+ * to configure terminal or use different keybinding.
115
+ */
116
+ enable: (flags = 1) => `${CSI}>${flags}u`,
117
+ /** Disable/pop Kitty keyboard protocol */
118
+ disable: `${CSI}<u`,
119
+ /** Query current keyboard mode (response: CSI ? flags u) */
120
+ query: `${CSI}?u`,
121
+ },
76
122
 
77
- /** Convenience shorthands for common toggles */
78
- bracketedPasteOn: ANSI.paste.bracketed.on,
79
- bracketedPasteOff: ANSI.paste.bracketed.off,
80
- mouseOn: ANSI.mouse.on,
81
- mouseOff: ANSI.mouse.off,
82
- reportCursorPosition: ANSI.report.cursorPosition,
123
+ /**
124
+ * xterm modifyOtherKeys mode
125
+ * @see https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
126
+ * Alternative to Kitty protocol, supported by xterm and some other terminals.
127
+ */
128
+ modifyOtherKeys: {
129
+ /** Enable mode 2 (full modifier reporting) */
130
+ enable: `${CSI}>4;2m`,
131
+ /** Disable modifyOtherKeys */
132
+ disable: `${CSI}>4;0m`,
133
+ },
134
+
135
+ /** Style/SGR reset */
136
+ resetStyle: `${CSI}0m`,
137
+
138
+ /** Build style SGR sequence */
139
+ style: (s: {
140
+ fg?: number
141
+ bg?: number
142
+ bold?: boolean
143
+ italic?: boolean
144
+ underline?: boolean
145
+ inverse?: boolean
146
+ }) => {
147
+ const codes: number[] = []
148
+ if (s.bold) codes.push(1)
149
+ if (s.italic) codes.push(3)
150
+ if (s.underline) codes.push(4)
151
+ if (s.inverse) codes.push(7)
152
+ if (s.fg !== undefined) {
153
+ if (s.fg < 256) {
154
+ codes.push(38, 5, s.fg)
155
+ } else {
156
+ // Truecolor: decode from packed RGB
157
+ const r = (s.fg >> 16) & 0xff
158
+ const g = (s.fg >> 8) & 0xff
159
+ const b = s.fg & 0xff
160
+ codes.push(38, 2, r, g, b)
161
+ }
162
+ }
163
+ if (s.bg !== undefined) {
164
+ if (s.bg < 256) {
165
+ codes.push(48, 5, s.bg)
166
+ } else {
167
+ const r = (s.bg >> 16) & 0xff
168
+ const g = (s.bg >> 8) & 0xff
169
+ const b = s.bg & 0xff
170
+ codes.push(48, 2, r, g, b)
171
+ }
172
+ }
173
+ return codes.length > 0 ? `${CSI}${codes.join(";")}m` : ""
174
+ },
175
+
176
+ /** Scrolling */
177
+ scroll: {
178
+ /** Scroll up by n lines */
179
+ up: (n: number) => `${CSI}${n}S`,
180
+ },
181
+
182
+ /** Device Status Reports */
183
+ report: {
184
+ /** Request cursor position (response: ESC [ row ; col R) */
185
+ cursorPosition: `${CSI}6n`,
186
+ },
187
+ } as const
188
+
189
+ /** High-level terminal control utilities (compositions of ANSI primitives) */
190
+ export const Terminal = {
191
+ /** Enter full-screen mode: alternate screen + clear + hide cursor */
192
+ enterFullscreen: ANSI.screen.enterAlt + ANSI.screen.clear + ANSI.cursor.hide,
193
+ /** Exit full-screen mode: show cursor + exit alternate screen */
194
+ exitFullscreen: ANSI.screen.exitAlt + ANSI.cursor.show,
195
+ /** Hide cursor */
196
+ hideCursor: ANSI.cursor.hide,
197
+ /** Show cursor */
198
+ showCursor: ANSI.cursor.show,
199
+ /** Clear screen and move cursor to home */
200
+ clearAndHome: ANSI.screen.clear + ANSI.cursor.home,
201
+ /** Enable bracketed paste mode */
202
+ bracketedPasteOn: ANSI.paste.enable,
203
+ /** Disable bracketed paste mode */
204
+ bracketedPasteOff: ANSI.paste.disable,
205
+ /** Enable mouse tracking */
206
+ mouseOn: ANSI.mouse.enable,
207
+ /** Disable mouse tracking */
208
+ mouseOff: ANSI.mouse.disable,
209
+ /** Request cursor position report */
210
+ reportCursorPosition: ANSI.report.cursorPosition,
83
211
  } as const