@effect-tui/react 0.2.0 → 0.2.2

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 (289) hide show
  1. package/dist/jsx-runtime.d.ts +6 -6
  2. package/dist/jsx-runtime.d.ts.map +1 -1
  3. package/dist/src/codeblock.js.map +1 -1
  4. package/dist/src/components/Divider.d.ts.map +1 -1
  5. package/dist/src/components/Divider.js +1 -1
  6. package/dist/src/components/Divider.js.map +1 -1
  7. package/dist/src/components/Markdown.d.ts.map +1 -1
  8. package/dist/src/components/Markdown.js +1 -1
  9. package/dist/src/components/Markdown.js.map +1 -1
  10. package/dist/src/components/MultilineTextInput.d.ts.map +1 -1
  11. package/dist/src/components/MultilineTextInput.js +2 -2
  12. package/dist/src/components/MultilineTextInput.js.map +1 -1
  13. package/dist/src/components/Static.d.ts.map +1 -1
  14. package/dist/src/components/Static.js +1 -1
  15. package/dist/src/components/Static.js.map +1 -1
  16. package/dist/src/components/TextInput.d.ts.map +1 -1
  17. package/dist/src/components/TextInput.js +3 -3
  18. package/dist/src/components/TextInput.js.map +1 -1
  19. package/dist/src/components/index.d.ts +4 -4
  20. package/dist/src/components/index.d.ts.map +1 -1
  21. package/dist/src/components/index.js +4 -4
  22. package/dist/src/components/index.js.map +1 -1
  23. package/dist/src/console/ConsoleCapture.d.ts.map +1 -1
  24. package/dist/src/console/ConsoleCapture.js +1 -1
  25. package/dist/src/console/ConsoleCapture.js.map +1 -1
  26. package/dist/src/console/ConsolePopover.d.ts.map +1 -1
  27. package/dist/src/console/ConsolePopover.js +11 -13
  28. package/dist/src/console/ConsolePopover.js.map +1 -1
  29. package/dist/src/console/index.d.ts +1 -1
  30. package/dist/src/console/index.d.ts.map +1 -1
  31. package/dist/src/console/index.js +1 -1
  32. package/dist/src/console/index.js.map +1 -1
  33. package/dist/src/console/useConsole.d.ts.map +1 -1
  34. package/dist/src/console/useConsole.js +2 -2
  35. package/dist/src/console/useConsole.js.map +1 -1
  36. package/dist/src/debug/DebugOverlay.d.ts +1 -1
  37. package/dist/src/debug/DebugOverlay.d.ts.map +1 -1
  38. package/dist/src/debug/DebugOverlay.js +1 -1
  39. package/dist/src/debug/DebugOverlay.js.map +1 -1
  40. package/dist/src/dev/Toast.d.ts.map +1 -1
  41. package/dist/src/dev/Toast.js +2 -2
  42. package/dist/src/dev/Toast.js.map +1 -1
  43. package/dist/src/dev/index.d.ts +1 -1
  44. package/dist/src/dev/index.d.ts.map +1 -1
  45. package/dist/src/dev/index.js +1 -1
  46. package/dist/src/dev/index.js.map +1 -1
  47. package/dist/src/dev.d.ts +1 -2
  48. package/dist/src/dev.d.ts.map +1 -1
  49. package/dist/src/dev.js +10 -10
  50. package/dist/src/dev.js.map +1 -1
  51. package/dist/src/exit.d.ts +7 -0
  52. package/dist/src/exit.d.ts.map +1 -0
  53. package/dist/src/exit.js +9 -0
  54. package/dist/src/exit.js.map +1 -0
  55. package/dist/src/highlight.d.ts +1 -1
  56. package/dist/src/highlight.d.ts.map +1 -1
  57. package/dist/src/highlight.js.map +1 -1
  58. package/dist/src/hooks/index.d.ts +3 -3
  59. package/dist/src/hooks/index.d.ts.map +1 -1
  60. package/dist/src/hooks/index.js.map +1 -1
  61. package/dist/src/hooks/use-keyboard.d.ts.map +1 -1
  62. package/dist/src/hooks/use-keyboard.js.map +1 -1
  63. package/dist/src/hooks/use-mouse.d.ts +1 -1
  64. package/dist/src/hooks/use-mouse.d.ts.map +1 -1
  65. package/dist/src/hooks/use-mouse.js.map +1 -1
  66. package/dist/src/hooks/use-quit.d.ts.map +1 -1
  67. package/dist/src/hooks/use-quit.js +2 -1
  68. package/dist/src/hooks/use-quit.js.map +1 -1
  69. package/dist/src/hooks/use-scroll.d.ts.map +1 -1
  70. package/dist/src/hooks/use-scroll.js +2 -2
  71. package/dist/src/hooks/use-scroll.js.map +1 -1
  72. package/dist/src/hooks/useFrameStats.d.ts.map +1 -1
  73. package/dist/src/hooks/useFrameStats.js.map +1 -1
  74. package/dist/src/hosts/base.d.ts +2 -2
  75. package/dist/src/hosts/base.d.ts.map +1 -1
  76. package/dist/src/hosts/box.d.ts +3 -3
  77. package/dist/src/hosts/box.d.ts.map +1 -1
  78. package/dist/src/hosts/box.js +1 -1
  79. package/dist/src/hosts/box.js.map +1 -1
  80. package/dist/src/hosts/canvas.d.ts +6 -3
  81. package/dist/src/hosts/canvas.d.ts.map +1 -1
  82. package/dist/src/hosts/canvas.js +9 -1
  83. package/dist/src/hosts/canvas.js.map +1 -1
  84. package/dist/src/hosts/codeblock.d.ts +2 -2
  85. package/dist/src/hosts/codeblock.d.ts.map +1 -1
  86. package/dist/src/hosts/codeblock.js +1 -1
  87. package/dist/src/hosts/codeblock.js.map +1 -1
  88. package/dist/src/hosts/flex-container.d.ts +3 -3
  89. package/dist/src/hosts/flex-container.d.ts.map +1 -1
  90. package/dist/src/hosts/flex-container.js +1 -1
  91. package/dist/src/hosts/flex-container.js.map +1 -1
  92. package/dist/src/hosts/hstack.d.ts +1 -1
  93. package/dist/src/hosts/index.d.ts +8 -8
  94. package/dist/src/hosts/index.d.ts.map +1 -1
  95. package/dist/src/hosts/index.js +13 -13
  96. package/dist/src/hosts/index.js.map +1 -1
  97. package/dist/src/hosts/overlay-item.d.ts +1 -1
  98. package/dist/src/hosts/overlay.d.ts +1 -1
  99. package/dist/src/hosts/overlay.d.ts.map +1 -1
  100. package/dist/src/hosts/overlay.js +1 -1
  101. package/dist/src/hosts/overlay.js.map +1 -1
  102. package/dist/src/hosts/scroll.d.ts +2 -2
  103. package/dist/src/hosts/scroll.d.ts.map +1 -1
  104. package/dist/src/hosts/scroll.js +1 -1
  105. package/dist/src/hosts/scroll.js.map +1 -1
  106. package/dist/src/hosts/single-child.d.ts +1 -1
  107. package/dist/src/hosts/single-child.d.ts.map +1 -1
  108. package/dist/src/hosts/spacer.d.ts +1 -1
  109. package/dist/src/hosts/spacer.d.ts.map +1 -1
  110. package/dist/src/hosts/text.d.ts +2 -2
  111. package/dist/src/hosts/text.d.ts.map +1 -1
  112. package/dist/src/hosts/text.js +1 -1
  113. package/dist/src/hosts/text.js.map +1 -1
  114. package/dist/src/hosts/vstack.d.ts +1 -1
  115. package/dist/src/hosts/zstack.d.ts +2 -2
  116. package/dist/src/hosts/zstack.d.ts.map +1 -1
  117. package/dist/src/hosts/zstack.js +1 -1
  118. package/dist/src/hosts/zstack.js.map +1 -1
  119. package/dist/src/index.d.ts +17 -21
  120. package/dist/src/index.d.ts.map +1 -1
  121. package/dist/src/index.js +11 -15
  122. package/dist/src/index.js.map +1 -1
  123. package/dist/src/inline/index.d.ts.map +1 -1
  124. package/dist/src/inline/index.js +1 -1
  125. package/dist/src/inline/index.js.map +1 -1
  126. package/dist/src/motion/color-motion-value.d.ts +1 -1
  127. package/dist/src/motion/color-motion-value.d.ts.map +1 -1
  128. package/dist/src/motion/color-motion-value.js.map +1 -1
  129. package/dist/src/motion/color.d.ts +1 -1
  130. package/dist/src/motion/color.d.ts.map +1 -1
  131. package/dist/src/motion/color.js +1 -1
  132. package/dist/src/motion/color.js.map +1 -1
  133. package/dist/src/motion/color.test.js +2 -2
  134. package/dist/src/motion/color.test.js.map +1 -1
  135. package/dist/src/motion/hooks.d.ts +3 -3
  136. package/dist/src/motion/hooks.d.ts.map +1 -1
  137. package/dist/src/motion/hooks.js +1 -1
  138. package/dist/src/motion/hooks.js.map +1 -1
  139. package/dist/src/motion/index.d.ts +2 -2
  140. package/dist/src/motion/index.d.ts.map +1 -1
  141. package/dist/src/motion/index.js +3 -3
  142. package/dist/src/motion/index.js.map +1 -1
  143. package/dist/src/motion/motion-value.d.ts +5 -5
  144. package/dist/src/motion/motion-value.d.ts.map +1 -1
  145. package/dist/src/motion/motion-value.js +4 -4
  146. package/dist/src/motion/motion-value.js.map +1 -1
  147. package/dist/src/motion/motion-value.test.js +1 -1
  148. package/dist/src/motion/motion-value.test.js.map +1 -1
  149. package/dist/src/reconciler/host-config.d.ts +1 -1
  150. package/dist/src/reconciler/host-config.d.ts.map +1 -1
  151. package/dist/src/reconciler/host-config.js +1 -1
  152. package/dist/src/reconciler/host-config.js.map +1 -1
  153. package/dist/src/reconciler/types.d.ts +1 -1
  154. package/dist/src/remote/Procedures.d.ts.map +1 -1
  155. package/dist/src/remote/Procedures.js.map +1 -1
  156. package/dist/src/remote/Router.d.ts +1 -1
  157. package/dist/src/remote/Router.d.ts.map +1 -1
  158. package/dist/src/remote/Router.js +1 -1
  159. package/dist/src/remote/Router.js.map +1 -1
  160. package/dist/src/remote/Server.d.ts +1 -1
  161. package/dist/src/remote/Server.d.ts.map +1 -1
  162. package/dist/src/remote/Server.js +3 -3
  163. package/dist/src/remote/Server.js.map +1 -1
  164. package/dist/src/remote/index.d.ts +2 -2
  165. package/dist/src/remote/index.d.ts.map +1 -1
  166. package/dist/src/remote/index.js +5 -5
  167. package/dist/src/remote/index.js.map +1 -1
  168. package/dist/src/renderer/core/FrameBuilder.d.ts.map +1 -1
  169. package/dist/src/renderer/core/FrameBuilder.js.map +1 -1
  170. package/dist/src/renderer/input/InputProcessor.js +1 -1
  171. package/dist/src/renderer/input/InputProcessor.js.map +1 -1
  172. package/dist/src/renderer/lifecycle/TerminalSetup.d.ts +1 -1
  173. package/dist/src/renderer/lifecycle/TerminalSetup.d.ts.map +1 -1
  174. package/dist/src/renderer/lifecycle/index.d.ts +1 -1
  175. package/dist/src/renderer/lifecycle/index.d.ts.map +1 -1
  176. package/dist/src/renderer/lifecycle/index.js +1 -1
  177. package/dist/src/renderer/lifecycle/index.js.map +1 -1
  178. package/dist/src/renderer/modes/FullscreenRenderer.d.ts +1 -1
  179. package/dist/src/renderer/modes/FullscreenRenderer.d.ts.map +1 -1
  180. package/dist/src/renderer/modes/InlineRenderer.d.ts +1 -1
  181. package/dist/src/renderer/modes/InlineRenderer.d.ts.map +1 -1
  182. package/dist/src/renderer/modes/InlineRenderer.js +1 -1
  183. package/dist/src/renderer/modes/InlineRenderer.js.map +1 -1
  184. package/dist/src/renderer/modes/StaticContentRenderer.d.ts.map +1 -1
  185. package/dist/src/renderer/modes/StaticContentRenderer.js.map +1 -1
  186. package/dist/src/renderer/modes/index.d.ts +1 -1
  187. package/dist/src/renderer/modes/index.d.ts.map +1 -1
  188. package/dist/src/renderer/modes/index.js.map +1 -1
  189. package/dist/src/renderer-context.js +1 -1
  190. package/dist/src/renderer-context.js.map +1 -1
  191. package/dist/src/renderer-types.d.ts +7 -1
  192. package/dist/src/renderer-types.d.ts.map +1 -1
  193. package/dist/src/renderer.d.ts +2 -2
  194. package/dist/src/renderer.d.ts.map +1 -1
  195. package/dist/src/renderer.js +41 -16
  196. package/dist/src/renderer.js.map +1 -1
  197. package/dist/src/test/index.d.ts +2 -2
  198. package/dist/src/test/index.d.ts.map +1 -1
  199. package/dist/src/test/index.js +1 -1
  200. package/dist/src/test/index.js.map +1 -1
  201. package/dist/src/test/render-tui.d.ts +2 -2
  202. package/dist/src/test/render-tui.d.ts.map +1 -1
  203. package/dist/src/test/render-tui.js +2 -2
  204. package/dist/src/test/render-tui.js.map +1 -1
  205. package/dist/src/utils/flex-layout.d.ts +15 -1
  206. package/dist/src/utils/flex-layout.d.ts.map +1 -1
  207. package/dist/src/utils/flex-layout.js +79 -24
  208. package/dist/src/utils/flex-layout.js.map +1 -1
  209. package/dist/src/utils/index.d.ts +4 -4
  210. package/dist/src/utils/index.d.ts.map +1 -1
  211. package/dist/src/utils/index.js +2 -2
  212. package/dist/src/utils/index.js.map +1 -1
  213. package/dist/src/utils/styles.d.ts.map +1 -1
  214. package/dist/src/utils/styles.js.map +1 -1
  215. package/dist/src/visualize/index.js +2 -2
  216. package/dist/src/visualize/index.js.map +1 -1
  217. package/dist/tsconfig.tsbuildinfo +1 -1
  218. package/jsx-runtime.ts +6 -6
  219. package/package.json +2 -2
  220. package/src/codeblock.tsx +1 -1
  221. package/src/components/Divider.tsx +1 -1
  222. package/src/components/Markdown.tsx +2 -2
  223. package/src/components/MultilineTextInput.tsx +9 -9
  224. package/src/components/Static.tsx +1 -1
  225. package/src/components/TextInput.tsx +9 -9
  226. package/src/components/index.ts +4 -4
  227. package/src/console/ConsoleCapture.ts +1 -1
  228. package/src/console/ConsolePopover.tsx +112 -119
  229. package/src/console/index.ts +1 -3
  230. package/src/console/useConsole.ts +2 -2
  231. package/src/debug/DebugOverlay.ts +3 -6
  232. package/src/dev/Toast.tsx +12 -10
  233. package/src/dev/index.ts +1 -1
  234. package/src/dev.tsx +11 -12
  235. package/src/exit.ts +8 -0
  236. package/src/highlight.ts +1 -1
  237. package/src/hooks/index.ts +3 -3
  238. package/src/hooks/use-keyboard.ts +1 -1
  239. package/src/hooks/use-mouse.ts +1 -1
  240. package/src/hooks/use-quit.ts +2 -1
  241. package/src/hooks/use-scroll.ts +9 -11
  242. package/src/hooks/useFrameStats.ts +1 -1
  243. package/src/hosts/base.ts +2 -2
  244. package/src/hosts/box.ts +4 -4
  245. package/src/hosts/canvas.ts +14 -3
  246. package/src/hosts/codeblock.ts +3 -3
  247. package/src/hosts/flex-container.ts +3 -3
  248. package/src/hosts/hstack.ts +1 -1
  249. package/src/hosts/index.ts +14 -14
  250. package/src/hosts/overlay-item.ts +1 -1
  251. package/src/hosts/overlay.ts +2 -2
  252. package/src/hosts/scroll.ts +3 -3
  253. package/src/hosts/single-child.ts +1 -1
  254. package/src/hosts/spacer.ts +1 -1
  255. package/src/hosts/text.ts +3 -3
  256. package/src/hosts/vstack.ts +1 -1
  257. package/src/hosts/zstack.ts +2 -2
  258. package/src/index.ts +60 -60
  259. package/src/inline/index.tsx +1 -1
  260. package/src/motion/color-motion-value.ts +1 -1
  261. package/src/motion/color.test.ts +2 -2
  262. package/src/motion/color.ts +2 -2
  263. package/src/motion/hooks.ts +3 -3
  264. package/src/motion/index.ts +8 -8
  265. package/src/motion/motion-value.test.ts +1 -1
  266. package/src/motion/motion-value.ts +11 -11
  267. package/src/reconciler/host-config.ts +3 -3
  268. package/src/reconciler/types.ts +1 -1
  269. package/src/remote/Procedures.ts +1 -7
  270. package/src/remote/Router.ts +3 -7
  271. package/src/remote/Server.ts +7 -12
  272. package/src/remote/index.ts +6 -10
  273. package/src/renderer/core/FrameBuilder.ts +1 -1
  274. package/src/renderer/input/InputProcessor.ts +1 -1
  275. package/src/renderer/lifecycle/TerminalSetup.ts +1 -1
  276. package/src/renderer/lifecycle/index.ts +1 -1
  277. package/src/renderer/modes/FullscreenRenderer.ts +1 -1
  278. package/src/renderer/modes/InlineRenderer.ts +2 -2
  279. package/src/renderer/modes/StaticContentRenderer.ts +1 -1
  280. package/src/renderer/modes/index.ts +1 -1
  281. package/src/renderer-context.ts +1 -1
  282. package/src/renderer-types.ts +7 -1
  283. package/src/renderer.ts +53 -28
  284. package/src/test/index.ts +4 -4
  285. package/src/test/render-tui.ts +3 -3
  286. package/src/utils/flex-layout.ts +83 -24
  287. package/src/utils/index.ts +8 -8
  288. package/src/utils/styles.ts +2 -2
  289. package/src/visualize/index.tsx +2 -2
package/jsx-runtime.ts CHANGED
@@ -3,17 +3,17 @@ export { Fragment, jsx, jsxs } from "react/jsx-runtime"
3
3
 
4
4
  // JSX types (namespace is type-only, but we export a dummy runtime value for bundlers)
5
5
  import type * as React from "react"
6
- import type { TextProps } from "./src/hosts/text.js"
7
- import type { SpacerProps } from "./src/hosts/spacer.js"
8
- import type { VStackProps } from "./src/hosts/vstack.js"
9
- import type { HStackProps } from "./src/hosts/hstack.js"
10
- import type { ZStackProps } from "./src/hosts/zstack.js"
11
6
  import type { BoxProps } from "./src/hosts/box.js"
12
7
  import type { CanvasProps } from "./src/hosts/canvas.js"
13
8
  import type { CodeBlockProps } from "./src/hosts/codeblock.js"
14
- import type { ScrollProps } from "./src/hosts/scroll.js"
9
+ import type { HStackProps } from "./src/hosts/hstack.js"
15
10
  import type { OverlayProps } from "./src/hosts/overlay.js"
16
11
  import type { OverlayItemProps } from "./src/hosts/overlay-item.js"
12
+ import type { ScrollProps } from "./src/hosts/scroll.js"
13
+ import type { SpacerProps } from "./src/hosts/spacer.js"
14
+ import type { TextProps } from "./src/hosts/text.js"
15
+ import type { VStackProps } from "./src/hosts/vstack.js"
16
+ import type { ZStackProps } from "./src/hosts/zstack.js"
17
17
 
18
18
  // Runtime placeholder (the actual JSX namespace below is type-only)
19
19
  const JSX = {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-tui/react",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "React bindings for @effect-tui/core",
5
5
  "type": "module",
6
6
  "files": [
@@ -83,7 +83,7 @@
83
83
  "prepublishOnly": "bun run typecheck && bun run build"
84
84
  },
85
85
  "dependencies": {
86
- "@effect-tui/core": "^0.2.0",
86
+ "@effect-tui/core": "^0.2.2",
87
87
  "@effect/platform": "^0.94.0",
88
88
  "@effect/platform-bun": "^0.87.0",
89
89
  "@effect/rpc": "^0.73.0",
package/src/codeblock.tsx CHANGED
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useState } from "react"
2
2
  import type { BundledLanguage, BundledTheme } from "shiki"
3
- import { highlightCode, toPlainLines, type HighlightLine } from "./highlight.js"
3
+ import { type HighlightLine, highlightCode, toPlainLines } from "./highlight.js"
4
4
  import type { CodeBlockProps as HostCodeBlockProps } from "./hosts/codeblock.js"
5
5
 
6
6
  export interface CodeBlockProps extends Omit<HostCodeBlockProps, "lines"> {
@@ -1,5 +1,5 @@
1
+ import { type Color, Colors } from "@effect-tui/core"
1
2
  import { useTerminalSize } from "../renderer-context.js"
2
- import { Colors, type Color } from "@effect-tui/core"
3
3
 
4
4
  export interface DividerProps {
5
5
  /** Character to use for the divider (default: "─") */
@@ -1,6 +1,6 @@
1
1
  import { Colors, type ColorValue } from "@effect-tui/core"
2
- import { CodeBlock } from "../codeblock.js"
3
2
  import type { BundledLanguage, BundledTheme } from "shiki"
3
+ import { CodeBlock } from "../codeblock.js"
4
4
 
5
5
  export interface MarkdownTheme {
6
6
  /** Header colors by level (h1, h2, h3+) */
@@ -115,7 +115,7 @@ function parseInline(text: string): MdSpan[] {
115
115
  }
116
116
 
117
117
  // Plain text until next special character
118
- match = remaining.match(/^[^*_`\[]+/)
118
+ match = remaining.match(/^[^*_`[]+/)
119
119
  if (match) {
120
120
  spans.push({ type: "text", text: match[0] })
121
121
  remaining = remaining.slice(match[0].length)
@@ -1,19 +1,19 @@
1
- import { useState, useCallback, useEffect, useMemo, useRef } from "react"
2
- import { Colors, type Color, displayWidth, graphemes } from "@effect-tui/core"
1
+ import { type Color, Colors, displayWidth, graphemes } from "@effect-tui/core"
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react"
3
3
  import { useKeyboard } from "../hooks/use-keyboard.js"
4
4
  import type { DrawContext } from "../hosts/canvas.js"
5
5
  import {
6
- type MultilineState,
7
- graphemeColToCharIdx,
6
+ deleteCharBackwardMultiline,
7
+ deleteCharForwardMultiline,
8
8
  deleteWordBackwardMultiline,
9
+ graphemeColToCharIdx,
10
+ insertTextMultiline,
9
11
  killToEndMultiline,
10
12
  killToStartMultiline,
11
- transposeCharsMultiline,
12
- deleteCharForwardMultiline,
13
- deleteCharBackwardMultiline,
14
- insertTextMultiline,
15
- matchPrevWord,
13
+ type MultilineState,
16
14
  matchNextWord,
15
+ matchPrevWord,
16
+ transposeCharsMultiline,
17
17
  } from "./text-editing.js"
18
18
 
19
19
  export interface MultilineTextInputProps {
@@ -1,4 +1,4 @@
1
- import { useState, useMemo, useLayoutEffect, type ReactNode } from "react"
1
+ import { type ReactNode, useLayoutEffect, useMemo, useState } from "react"
2
2
 
3
3
  export interface StaticProps<T> {
4
4
  /**
@@ -1,18 +1,18 @@
1
- import { useState, useCallback, useEffect } from "react"
2
- import { Colors, type Color, displayWidth } from "@effect-tui/core"
1
+ import { type Color, Colors, displayWidth } from "@effect-tui/core"
2
+ import { useCallback, useEffect, useState } from "react"
3
3
  import { useKeyboard } from "../hooks/use-keyboard.js"
4
4
  import type { DrawContext } from "../hosts/canvas.js"
5
5
  import {
6
- type TextState,
6
+ deleteCharBackward,
7
+ deleteCharForward,
7
8
  deleteWordBackward,
9
+ insertText,
8
10
  killToEnd,
9
11
  killToStart,
10
- deleteCharForward,
11
- deleteCharBackward,
12
- transposeChars,
13
- insertText,
14
- matchPrevWord,
15
12
  matchNextWord,
13
+ matchPrevWord,
14
+ type TextState,
15
+ transposeChars,
16
16
  } from "./text-editing.js"
17
17
 
18
18
  export interface TextInputProps {
@@ -352,5 +352,5 @@ export function TextInput({
352
352
  ],
353
353
  )
354
354
 
355
- return <canvas draw={draw} width={width} height={1} />
355
+ return <canvas draw={draw} width={width} height={1} inheritBg />
356
356
  }
@@ -1,6 +1,6 @@
1
- export { TextInput, type TextInputProps } from "./TextInput.js"
2
- export { MultilineTextInput, type MultilineTextInputProps } from "./MultilineTextInput.js"
1
+ export { Divider, type DividerProps } from "./Divider.js"
3
2
  export { Markdown, type MarkdownProps, type MarkdownTheme } from "./Markdown.js"
3
+ export { MultilineTextInput, type MultilineTextInputProps } from "./MultilineTextInput.js"
4
+ export { Overlay, type OverlayItemProps, type OverlayProps } from "./Overlay.js"
4
5
  export { Static, type StaticProps } from "./Static.js"
5
- export { Divider, type DividerProps } from "./Divider.js"
6
- export { Overlay, type OverlayProps, type OverlayItemProps } from "./Overlay.js"
6
+ export { TextInput, type TextInputProps } from "./TextInput.js"
@@ -1,10 +1,10 @@
1
1
  // Console capture singleton for TUI debugging
2
2
  // Intercepts console.log/info/warn/error/debug and stores entries for display
3
3
 
4
- import { EventEmitter } from "events"
5
4
  import { Console } from "node:console"
6
5
  import { Writable } from "node:stream"
7
6
  import * as util from "node:util"
7
+ import { EventEmitter } from "events"
8
8
 
9
9
  // ─────────────────────────────────────────────────────────────
10
10
  // Types
@@ -1,14 +1,14 @@
1
1
  // Console popover component for displaying captured console output
2
2
  // Shows logs in a scrollable overlay with text selection and copy functionality
3
3
 
4
- import { useState, useCallback, useEffect, useMemo, useRef } from "react"
5
4
  import { Colors, type ColorValue } from "@effect-tui/core"
6
- import { useTerminalSize } from "../renderer.js"
5
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react"
7
6
  import { useKeyboard } from "../hooks/use-keyboard.js"
8
7
  import { useMouse } from "../hooks/use-mouse.js"
9
8
  import { useScroll } from "../hooks/use-scroll.js"
9
+ import { useTerminalSize } from "../renderer.js"
10
10
  import { getConsoleCapture, type LogEntry, type LogLevel } from "./ConsoleCapture.js"
11
- import { copyToClipboardSync, copyToClipboard } from "./clipboard.js"
11
+ import { copyToClipboard, copyToClipboardSync } from "./clipboard.js"
12
12
 
13
13
  // ─────────────────────────────────────────────────────────────
14
14
  // Types
@@ -97,10 +97,7 @@ function wrapLine(text: string, maxWidth: number): string[] {
97
97
  }
98
98
 
99
99
  /** Normalize selection so start is before end */
100
- function normalizeSelection(
101
- anchor: SelectionPoint,
102
- head: SelectionPoint,
103
- ): [SelectionPoint, SelectionPoint] {
100
+ function normalizeSelection(anchor: SelectionPoint, head: SelectionPoint): [SelectionPoint, SelectionPoint] {
104
101
  if (anchor.line < head.line || (anchor.line === head.line && anchor.col <= head.col)) {
105
102
  return [anchor, head]
106
103
  }
@@ -156,13 +153,17 @@ export function ConsolePopover({
156
153
  const [feedback, setFeedback] = useState<string | null>(null)
157
154
 
158
155
  // Calculate dimensions - inline mode uses adjustable fixed height
159
- const popoverHeight = mode === "inline"
160
- ? inlineHeight
161
- : Math.max(5, Math.floor(termHeight * (sizePercent / 100)))
156
+ const popoverHeight = mode === "inline" ? inlineHeight : Math.max(5, Math.floor(termHeight * (sizePercent / 100)))
162
157
  const contentStartY = termHeight - popoverHeight + 1 // +1 for title bar
163
158
 
164
159
  // Use scroll hook for content scrolling
165
- const { state: scrollState, scrollProps, scrollToEnd, scrollToStart, scrollBy } = useScroll({
160
+ const {
161
+ state: scrollState,
162
+ scrollProps,
163
+ scrollToEnd,
164
+ scrollToStart,
165
+ scrollBy,
166
+ } = useScroll({
166
167
  axis: "vertical",
167
168
  sticky: true,
168
169
  enableKeyboard: false,
@@ -299,107 +300,99 @@ export function ConsolePopover({
299
300
  [contentStartY, scrollState.offset, displayLines.length],
300
301
  )
301
302
 
302
- // Keyboard handler
303
- useKeyboard(
304
- useCallback(
305
- (key) => {
306
- // Ctrl+Y or Ctrl+C - Copy selection
307
- if (key.ctrl && !key.shift && key.name === "char" && (key.text === "y" || key.text === "c")) {
308
- handleCopy()
309
- return
310
- }
303
+ // Keyboard handler - no useCallback needed, useKeyboard uses ref internally
304
+ useKeyboard((key) => {
305
+ // Ctrl+Y or Ctrl+C - Copy selection
306
+ if (key.ctrl && !key.shift && key.name === "char" && (key.text === "y" || key.text === "c")) {
307
+ handleCopy()
308
+ return
309
+ }
311
310
 
312
- // Ctrl+S - Save logs to file
313
- if (key.ctrl && !key.shift && key.name === "char" && key.text === "s") {
314
- handleSave()
315
- return
316
- }
311
+ // Ctrl+S - Save logs to file
312
+ if (key.ctrl && !key.shift && key.name === "char" && key.text === "s") {
313
+ handleSave()
314
+ return
315
+ }
317
316
 
318
- // Size controls
319
- if (key.name === "char" && (key.text === "+" || key.text === "=")) {
320
- if (mode === "inline") {
321
- setInlineHeight((prev) => Math.min(30, prev + 2))
322
- } else {
323
- setSizePercent((prev) => Math.min(maxHeightPercent, prev + 5))
324
- }
325
- return
326
- }
327
- if (key.name === "char" && key.text === "-") {
328
- if (mode === "inline") {
329
- setInlineHeight((prev) => Math.max(4, prev - 2))
330
- } else {
331
- setSizePercent((prev) => Math.max(minHeightPercent, prev - 5))
332
- }
333
- return
334
- }
317
+ // Size controls
318
+ if (key.name === "char" && (key.text === "+" || key.text === "=")) {
319
+ if (mode === "inline") {
320
+ setInlineHeight((prev) => Math.min(30, prev + 2))
321
+ } else {
322
+ setSizePercent((prev) => Math.min(maxHeightPercent, prev + 5))
323
+ }
324
+ return
325
+ }
326
+ if (key.name === "char" && key.text === "-") {
327
+ if (mode === "inline") {
328
+ setInlineHeight((prev) => Math.max(4, prev - 2))
329
+ } else {
330
+ setSizePercent((prev) => Math.max(minHeightPercent, prev - 5))
331
+ }
332
+ return
333
+ }
335
334
 
336
- // Shift+up/down - jump to top/bottom
337
- if (key.shift && key.name === "up") {
338
- scrollToStart()
339
- return
340
- }
341
- if (key.shift && key.name === "down") {
342
- scrollToEnd()
343
- return
344
- }
335
+ // Shift+up/down - jump to top/bottom
336
+ if (key.shift && key.name === "up") {
337
+ scrollToStart()
338
+ return
339
+ }
340
+ if (key.shift && key.name === "down") {
341
+ scrollToEnd()
342
+ return
343
+ }
345
344
 
346
- // Regular up/down - scroll
347
- if (key.name === "up") {
348
- scrollBy(-1)
349
- return
350
- }
351
- if (key.name === "down") {
352
- scrollBy(1)
353
- return
354
- }
345
+ // Regular up/down - scroll
346
+ if (key.name === "up") {
347
+ scrollBy(-1)
348
+ return
349
+ }
350
+ if (key.name === "down") {
351
+ scrollBy(1)
352
+ return
353
+ }
355
354
 
356
- // Home/End
357
- if (key.name === "home") {
358
- scrollToStart()
359
- return
360
- }
361
- if (key.name === "end") {
362
- scrollToEnd()
363
- return
364
- }
365
- },
366
- [handleCopy, handleSave, maxHeightPercent, minHeightPercent, scrollToStart, scrollToEnd, scrollBy],
367
- ),
368
- )
355
+ // Home/End
356
+ if (key.name === "home") {
357
+ scrollToStart()
358
+ return
359
+ }
360
+ if (key.name === "end") {
361
+ scrollToEnd()
362
+ return
363
+ }
364
+ })
369
365
 
370
- // Mouse handler for text selection
366
+ // Mouse handler for text selection - no useCallback needed, useMouse uses ref internally
371
367
  useMouse(
372
- useCallback(
373
- (mouse) => {
374
- // Only handle events in content area
375
- if (mouse.y < contentStartY || mouse.y >= termHeight) return
376
-
377
- const point = mouseToSelectionPoint(mouse.x, mouse.y)
378
- if (!point) return
379
-
380
- if (mouse.action === "press") {
381
- // Start new selection
382
- setSelectionAnchor(point)
383
- setSelectionHead(point)
384
- isSelectingRef.current = true
385
- } else if (mouse.action === "drag" && isSelectingRef.current) {
386
- // Extend selection
387
- setSelectionHead(point)
388
-
389
- // Auto-scroll when dragging near edges
390
- const relativeY = mouse.y - contentStartY
391
- const viewportHeight = popoverHeight - 1 // -1 for title
392
- if (relativeY <= 1) {
393
- scrollBy(-1)
394
- } else if (relativeY >= viewportHeight - 2) {
395
- scrollBy(1)
396
- }
397
- } else if (mouse.action === "release") {
398
- isSelectingRef.current = false
368
+ (mouse) => {
369
+ // Only handle events in content area
370
+ if (mouse.y < contentStartY || mouse.y >= termHeight) return
371
+
372
+ const point = mouseToSelectionPoint(mouse.x, mouse.y)
373
+ if (!point) return
374
+
375
+ if (mouse.action === "press") {
376
+ // Start new selection
377
+ setSelectionAnchor(point)
378
+ setSelectionHead(point)
379
+ isSelectingRef.current = true
380
+ } else if (mouse.action === "drag" && isSelectingRef.current) {
381
+ // Extend selection
382
+ setSelectionHead(point)
383
+
384
+ // Auto-scroll when dragging near edges
385
+ const relativeY = mouse.y - contentStartY
386
+ const viewportHeight = popoverHeight - 1 // -1 for title
387
+ if (relativeY <= 1) {
388
+ scrollBy(-1)
389
+ } else if (relativeY >= viewportHeight - 2) {
390
+ scrollBy(1)
399
391
  }
400
- },
401
- [contentStartY, termHeight, mouseToSelectionPoint, popoverHeight, scrollBy],
402
- ),
392
+ } else if (mouse.action === "release") {
393
+ isSelectingRef.current = false
394
+ }
395
+ },
403
396
  { action: "any", button: "left" },
404
397
  )
405
398
 
@@ -423,22 +416,22 @@ export function ConsolePopover({
423
416
 
424
417
  return (
425
418
  <hstack key={index}>
426
- {before.length > 0 && (
427
- <text fg={LOG_COLORS[line.level]} bg={CONTENT_BG}>
428
- {before}
429
- </text>
430
- )}
431
- <text fg={Colors.white} bg={SELECTION_BG}>
432
- {selected}
433
- </text>
434
- {after.length > 0 && (
435
- <text fg={LOG_COLORS[line.level]} bg={CONTENT_BG}>
436
- {after}
419
+ {before.length > 0 && (
420
+ <text fg={LOG_COLORS[line.level]} bg={CONTENT_BG}>
421
+ {before}
422
+ </text>
423
+ )}
424
+ <text fg={Colors.white} bg={SELECTION_BG}>
425
+ {selected}
437
426
  </text>
438
- )}
439
- </hstack>
440
- )
441
- }
427
+ {after.length > 0 && (
428
+ <text fg={LOG_COLORS[line.level]} bg={CONTENT_BG}>
429
+ {after}
430
+ </text>
431
+ )}
432
+ </hstack>
433
+ )
434
+ }
442
435
  }
443
436
 
444
437
  // No selection on this line
@@ -36,7 +36,5 @@ export {
36
36
  } from "./ConsoleCapture.js"
37
37
 
38
38
  export { ConsolePopover, type ConsolePopoverProps } from "./ConsolePopover.js"
39
-
40
- export { useConsole, type UseConsoleOptions, type UseConsoleReturn } from "./useConsole.js"
41
-
42
39
  export { copyToClipboard, copyToClipboardSync } from "./clipboard.js"
40
+ export { type UseConsoleOptions, type UseConsoleReturn, useConsole } from "./useConsole.js"
@@ -2,9 +2,9 @@
2
2
  // Uses ` (backtick) for toggle, ~ (tilde) for screenshot
3
3
  // Auto-show on error
4
4
 
5
- import { useState, useEffect, useCallback, useMemo } from "react"
6
- import { getConsoleCapture, type LogEntry } from "./ConsoleCapture.js"
5
+ import { useCallback, useEffect, useMemo, useState } from "react"
7
6
  import { useKeyboard } from "../hooks/use-keyboard.js"
7
+ import { getConsoleCapture, type LogEntry } from "./ConsoleCapture.js"
8
8
 
9
9
  // ─────────────────────────────────────────────────────────────
10
10
  // Types
@@ -1,9 +1,9 @@
1
1
  // Integrated debug overlay for all TUI apps
2
2
  // Provides console log viewer with Ctrl+Shift+D toggle and Ctrl+Shift+S screenshot
3
3
 
4
- import type { CellBuffer, Palette, KeyMsg, MouseMsg } from "@effect-tui/core"
4
+ import type { CellBuffer, KeyMsg, MouseMsg, Palette } from "@effect-tui/core"
5
5
  import { getConsoleCapture, type LogLevel } from "../console/ConsoleCapture.js"
6
- import { copyToClipboardSync, copyToClipboard } from "../console/clipboard.js"
6
+ import { copyToClipboard, copyToClipboardSync } from "../console/clipboard.js"
7
7
 
8
8
  // ─────────────────────────────────────────────────────────────
9
9
  // Types
@@ -433,10 +433,7 @@ export class DebugOverlay {
433
433
  }
434
434
  }
435
435
 
436
- private getLineSelection(
437
- lineIndex: number,
438
- lineLength: number,
439
- ): { startCol: number; endCol: number } | null {
436
+ private getLineSelection(lineIndex: number, lineLength: number): { startCol: number; endCol: number } | null {
440
437
  if (!this.selectionAnchor || !this.selectionHead) return null
441
438
 
442
439
  const [start, end] = normalizeSelection(this.selectionAnchor, this.selectionHead)
package/src/dev/Toast.tsx CHANGED
@@ -1,8 +1,8 @@
1
1
  // Toast notification system for dev mode
2
2
  // Beautiful, minimal notifications that appear at the top of the screen
3
3
 
4
- import { useState, useCallback, createContext, useContext, type ReactNode } from "react"
5
4
  import { Colors } from "@effect-tui/core"
5
+ import { createContext, type ReactNode, useCallback, useContext, useState } from "react"
6
6
  import { useTerminalSize } from "../renderer-context.js"
7
7
 
8
8
  // ─────────────────────────────────────────────────────────────
@@ -41,7 +41,10 @@ export function useToast(): ToastContextValue {
41
41
  // Styling
42
42
  // ─────────────────────────────────────────────────────────────
43
43
 
44
- const TOAST_STYLES: Record<ToastType, { bg: ReturnType<typeof Colors.rgb>; fg: ReturnType<typeof Colors.rgb>; icon: string }> = {
44
+ const TOAST_STYLES: Record<
45
+ ToastType,
46
+ { bg: ReturnType<typeof Colors.rgb>; fg: ReturnType<typeof Colors.rgb>; icon: string }
47
+ > = {
45
48
  success: { bg: Colors.rgb(30, 70, 40), fg: Colors.rgb(140, 230, 140), icon: "✓" },
46
49
  info: { bg: Colors.rgb(30, 50, 80), fg: Colors.rgb(140, 180, 230), icon: "ℹ" },
47
50
  warning: { bg: Colors.rgb(80, 60, 20), fg: Colors.rgb(230, 200, 100), icon: "⚠" },
@@ -70,11 +73,7 @@ export function ToastProvider({ children }: { children: ReactNode }) {
70
73
  setToasts((prev) => prev.filter((t) => t.id !== id))
71
74
  }, [])
72
75
 
73
- return (
74
- <ToastContext.Provider value={{ toasts, show, dismiss }}>
75
- {children}
76
- </ToastContext.Provider>
77
- )
76
+ return <ToastContext.Provider value={{ toasts, show, dismiss }}>{children}</ToastContext.Provider>
78
77
  }
79
78
 
80
79
  // ─────────────────────────────────────────────────────────────
@@ -111,7 +110,10 @@ export function ToastContainer() {
111
110
  export function useScreenshotToast() {
112
111
  const { show } = useToast()
113
112
 
114
- return useCallback((path: string) => {
115
- show(`Screenshot saved: ${path}`, "success", 2500)
116
- }, [show])
113
+ return useCallback(
114
+ (path: string) => {
115
+ show(`Screenshot saved: ${path}`, "success", 2500)
116
+ },
117
+ [show],
118
+ )
117
119
  }
package/src/dev/index.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Dev mode utilities
2
- export { ToastProvider, ToastContainer, useToast, useScreenshotToast, type Toast, type ToastType } from "./Toast.js"
2
+ export { type Toast, ToastContainer, ToastProvider, type ToastType, useScreenshotToast, useToast } from "./Toast.js"
package/src/dev.tsx CHANGED
@@ -9,25 +9,24 @@
9
9
  * - Remote control when EFFECT_TUI_REMOTE=1
10
10
  */
11
11
 
12
- import { globalValue } from "effect/GlobalValue"
12
+ import { Colors } from "@effect-tui/core"
13
13
  import * as watcher from "@parcel/watcher"
14
- import { dirname } from "path"
15
- import { stat } from "fs/promises"
14
+ import { globalValue } from "effect/GlobalValue"
16
15
  import { readFileSync } from "fs"
16
+ import { stat } from "fs/promises"
17
+ import { dirname } from "path"
17
18
  import React from "react"
18
- import { Colors } from "@effect-tui/core"
19
- import { createRenderer, createRoot, type Root } from "./renderer.js"
20
- import type { RendererOptions } from "./renderer-types.js"
21
- import type { TuiRenderer } from "./renderer-types.js"
19
+ import { Overlay } from "./components/Overlay.js"
22
20
  import { ConsolePopover } from "./console/ConsolePopover.js"
21
+ import { copyToClipboard, copyToClipboardSync } from "./console/clipboard.js"
23
22
  import { useConsole } from "./console/useConsole.js"
24
- import { enableRemote } from "./remote/index.js"
25
- import { ToastProvider, ToastContainer, useToast } from "./dev/Toast.js"
23
+ import { DiagnosticsPanel } from "./debug/DiagnosticsPanel.js"
24
+ import { ToastContainer, ToastProvider, useToast } from "./dev/Toast.js"
26
25
  import { useKeyboard } from "./hooks/use-keyboard.js"
26
+ import { enableRemote } from "./remote/index.js"
27
+ import { createRenderer, createRoot, type Root } from "./renderer.js"
27
28
  import { useRenderer, useTerminalSize } from "./renderer-context.js"
28
- import { copyToClipboardSync, copyToClipboard } from "./console/clipboard.js"
29
- import { DiagnosticsPanel } from "./debug/DiagnosticsPanel.js"
30
- import { Overlay } from "./components/Overlay.js"
29
+ import type { RendererOptions, TuiRenderer } from "./renderer-types.js"
31
30
 
32
31
  /**
33
32
  * Pipeable combinator that makes an atom persist across hot reloads.
package/src/exit.ts ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Request a clean process exit.
3
+ * This schedules process.exit() on the next tick to allow
4
+ * pending cleanup operations to complete.
5
+ */
6
+ export function requestExit(code = 0): void {
7
+ setImmediate(() => process.exit(code))
8
+ }
package/src/highlight.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { createHighlighter, type Highlighter, type BundledLanguage, type BundledTheme } from "shiki"
2
1
  import type { Color } from "@effect-tui/core"
2
+ import { type BundledLanguage, type BundledTheme, createHighlighter, type Highlighter } from "shiki"
3
3
 
4
4
  export interface HighlightTokenStyle {
5
5
  fg?: Color
@@ -1,8 +1,8 @@
1
- export { useKeyboard } from "./use-keyboard.js"
2
1
  export type { UseKeyboardOptions } from "./use-keyboard.js"
3
- export { useMouse } from "./use-mouse.js"
2
+ export { useKeyboard } from "./use-keyboard.js"
4
3
  export type { UseMouseOptions } from "./use-mouse.js"
4
+ export { useMouse } from "./use-mouse.js"
5
5
  export { usePaste } from "./use-paste.js"
6
6
  export { useQuit } from "./use-quit.js"
7
+ export type { ScrollState, UseScrollOptions, UseScrollReturn } from "./use-scroll.js"
7
8
  export { useScroll } from "./use-scroll.js"
8
- export type { UseScrollOptions, UseScrollReturn, ScrollState } from "./use-scroll.js"
@@ -1,5 +1,5 @@
1
- import { useEffect, useRef } from "react"
2
1
  import type { KeyMsg } from "@effect-tui/core"
2
+ import { useEffect, useRef } from "react"
3
3
  import { useRenderer } from "../renderer.js"
4
4
 
5
5
  export type UseKeyboardOptions = {
@@ -1,5 +1,5 @@
1
+ import type { MouseButton, MouseMsg } from "@effect-tui/core"
1
2
  import { useEffect, useRef } from "react"
2
- import type { MouseMsg, MouseButton } from "@effect-tui/core"
3
3
  import { useRenderer } from "../renderer.js"
4
4
 
5
5
  export type UseMouseOptions = {