@effect-tui/react 0.15.2 → 2.0.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.
- package/README.md +11 -2
- package/dist/src/codeblock.d.ts +1 -1
- package/dist/src/codeblock.d.ts.map +1 -1
- package/dist/src/codeblock.js +2 -2
- package/dist/src/codeblock.js.map +1 -1
- package/dist/src/components/ListView.d.ts +4 -4
- package/dist/src/components/ListView.d.ts.map +1 -1
- package/dist/src/components/ListView.js +16 -17
- package/dist/src/components/ListView.js.map +1 -1
- package/dist/src/components/Markdown.js +3 -3
- package/dist/src/components/Markdown.js.map +1 -1
- package/dist/src/components/MultilineTextInput.d.ts.map +1 -1
- package/dist/src/components/MultilineTextInput.js +133 -305
- package/dist/src/components/MultilineTextInput.js.map +1 -1
- package/dist/src/components/TextInput.d.ts.map +1 -1
- package/dist/src/components/TextInput.js +51 -98
- package/dist/src/components/TextInput.js.map +1 -1
- package/dist/src/components/text-editing.d.ts +61 -0
- package/dist/src/components/text-editing.d.ts.map +1 -1
- package/dist/src/components/text-editing.js +131 -0
- package/dist/src/components/text-editing.js.map +1 -1
- package/dist/src/console/ConsolePopover.d.ts +7 -1
- package/dist/src/console/ConsolePopover.d.ts.map +1 -1
- package/dist/src/console/ConsolePopover.js +55 -74
- package/dist/src/console/ConsolePopover.js.map +1 -1
- package/dist/src/debug/DebugOverlay.d.ts.map +1 -1
- package/dist/src/debug/DebugOverlay.js +3 -57
- package/dist/src/debug/DebugOverlay.js.map +1 -1
- package/dist/src/debug/DiagnosticsPanel.js +1 -1
- package/dist/src/debug/DiagnosticsPanel.js.map +1 -1
- package/dist/src/dev.d.ts +5 -117
- package/dist/src/dev.d.ts.map +1 -1
- package/dist/src/dev.js +3 -333
- package/dist/src/dev.js.map +1 -1
- package/dist/src/hooks/use-scroll.d.ts +31 -35
- package/dist/src/hooks/use-scroll.d.ts.map +1 -1
- package/dist/src/hooks/use-scroll.js +51 -90
- package/dist/src/hooks/use-scroll.js.map +1 -1
- package/dist/src/hosts/base.d.ts +13 -2
- package/dist/src/hosts/base.d.ts.map +1 -1
- package/dist/src/hosts/base.js +74 -2
- package/dist/src/hosts/base.js.map +1 -1
- package/dist/src/hosts/box.d.ts +2 -2
- package/dist/src/hosts/box.d.ts.map +1 -1
- package/dist/src/hosts/box.js +29 -2
- package/dist/src/hosts/box.js.map +1 -1
- package/dist/src/hosts/canvas.d.ts +24 -4
- package/dist/src/hosts/canvas.d.ts.map +1 -1
- package/dist/src/hosts/canvas.js +107 -41
- package/dist/src/hosts/canvas.js.map +1 -1
- package/dist/src/hosts/codeblock.d.ts +10 -12
- package/dist/src/hosts/codeblock.d.ts.map +1 -1
- package/dist/src/hosts/codeblock.js +38 -35
- package/dist/src/hosts/codeblock.js.map +1 -1
- package/dist/src/hosts/flex-container.d.ts +3 -3
- package/dist/src/hosts/flex-container.d.ts.map +1 -1
- package/dist/src/hosts/flex-container.js +20 -5
- package/dist/src/hosts/flex-container.js.map +1 -1
- package/dist/src/hosts/index.d.ts +3 -2
- package/dist/src/hosts/index.d.ts.map +1 -1
- package/dist/src/hosts/index.js +2 -1
- package/dist/src/hosts/index.js.map +1 -1
- package/dist/src/hosts/layout-helpers.d.ts +10 -0
- package/dist/src/hosts/layout-helpers.d.ts.map +1 -0
- package/dist/src/hosts/layout-helpers.js +10 -0
- package/dist/src/hosts/layout-helpers.js.map +1 -0
- package/dist/src/hosts/leaf.d.ts +14 -0
- package/dist/src/hosts/leaf.d.ts.map +1 -0
- package/dist/src/hosts/leaf.js +31 -0
- package/dist/src/hosts/leaf.js.map +1 -0
- package/dist/src/hosts/overlay-item.d.ts +2 -2
- package/dist/src/hosts/overlay-item.d.ts.map +1 -1
- package/dist/src/hosts/overlay-item.js +7 -2
- package/dist/src/hosts/overlay-item.js.map +1 -1
- package/dist/src/hosts/overlay.d.ts +2 -2
- package/dist/src/hosts/overlay.d.ts.map +1 -1
- package/dist/src/hosts/overlay.js +6 -9
- package/dist/src/hosts/overlay.js.map +1 -1
- package/dist/src/hosts/scroll.d.ts +54 -26
- package/dist/src/hosts/scroll.d.ts.map +1 -1
- package/dist/src/hosts/scroll.js +185 -87
- package/dist/src/hosts/scroll.js.map +1 -1
- package/dist/src/hosts/single-child.d.ts.map +1 -1
- package/dist/src/hosts/single-child.js +2 -0
- package/dist/src/hosts/single-child.js.map +1 -1
- package/dist/src/hosts/spacer.d.ts +3 -3
- package/dist/src/hosts/spacer.d.ts.map +1 -1
- package/dist/src/hosts/spacer.js +8 -3
- package/dist/src/hosts/spacer.js.map +1 -1
- package/dist/src/hosts/text.d.ts +22 -18
- package/dist/src/hosts/text.d.ts.map +1 -1
- package/dist/src/hosts/text.js +108 -131
- package/dist/src/hosts/text.js.map +1 -1
- package/dist/src/hosts/vstack.js +1 -1
- package/dist/src/hosts/vstack.js.map +1 -1
- package/dist/src/hosts/zstack.d.ts +3 -3
- package/dist/src/hosts/zstack.d.ts.map +1 -1
- package/dist/src/hosts/zstack.js +13 -8
- package/dist/src/hosts/zstack.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/internal/dev/hmr.d.ts +20 -0
- package/dist/src/internal/dev/hmr.d.ts.map +1 -0
- package/dist/src/internal/dev/hmr.js +93 -0
- package/dist/src/internal/dev/hmr.js.map +1 -0
- package/dist/src/internal/dev/runtime.d.ts +24 -0
- package/dist/src/internal/dev/runtime.d.ts.map +1 -0
- package/dist/src/internal/dev/runtime.js +135 -0
- package/dist/src/internal/dev/runtime.js.map +1 -0
- package/dist/src/internal/dev/ui.d.ts +13 -0
- package/dist/src/internal/dev/ui.d.ts.map +1 -0
- package/dist/src/internal/dev/ui.js +51 -0
- package/dist/src/internal/dev/ui.js.map +1 -0
- package/dist/src/internal/renderer/context.d.ts +9 -0
- package/dist/src/internal/renderer/context.d.ts.map +1 -0
- package/dist/src/internal/renderer/context.js +22 -0
- package/dist/src/internal/renderer/context.js.map +1 -0
- package/dist/src/internal/renderer/core/FrameBuilder.d.ts +18 -0
- package/dist/src/internal/renderer/core/FrameBuilder.d.ts.map +1 -0
- package/dist/src/internal/renderer/core/FrameBuilder.js +40 -0
- package/dist/src/internal/renderer/core/FrameBuilder.js.map +1 -0
- package/dist/src/internal/renderer/core/RendererState.d.ts +41 -0
- package/dist/src/internal/renderer/core/RendererState.d.ts.map +1 -0
- package/dist/src/internal/renderer/core/RendererState.js +70 -0
- package/dist/src/internal/renderer/core/RendererState.js.map +1 -0
- package/dist/src/internal/renderer/core/index.d.ts +3 -0
- package/dist/src/internal/renderer/core/index.d.ts.map +1 -0
- package/dist/src/internal/renderer/core/index.js +3 -0
- package/dist/src/internal/renderer/core/index.js.map +1 -0
- package/dist/src/internal/renderer/index.d.ts +40 -0
- package/dist/src/internal/renderer/index.d.ts.map +1 -0
- package/dist/src/internal/renderer/index.js +543 -0
- package/dist/src/internal/renderer/index.js.map +1 -0
- package/dist/src/internal/renderer/input/InputProcessor.d.ts +30 -0
- package/dist/src/internal/renderer/input/InputProcessor.d.ts.map +1 -0
- package/dist/src/internal/renderer/input/InputProcessor.js +122 -0
- package/dist/src/internal/renderer/input/InputProcessor.js.map +1 -0
- package/dist/src/internal/renderer/input/index.d.ts +2 -0
- package/dist/src/internal/renderer/input/index.d.ts.map +1 -0
- package/dist/src/internal/renderer/input/index.js +2 -0
- package/dist/src/internal/renderer/input/index.js.map +1 -0
- package/dist/src/internal/renderer/lifecycle/EventBus.d.ts +42 -0
- package/dist/src/internal/renderer/lifecycle/EventBus.d.ts.map +1 -0
- package/dist/src/internal/renderer/lifecycle/EventBus.js +97 -0
- package/dist/src/internal/renderer/lifecycle/EventBus.js.map +1 -0
- package/dist/src/internal/renderer/lifecycle/ProcessLifecycle.d.ts +13 -0
- package/dist/src/internal/renderer/lifecycle/ProcessLifecycle.d.ts.map +1 -0
- package/dist/src/internal/renderer/lifecycle/ProcessLifecycle.js +111 -0
- package/dist/src/internal/renderer/lifecycle/ProcessLifecycle.js.map +1 -0
- package/dist/src/internal/renderer/lifecycle/RenderCache.d.ts +3 -0
- package/dist/src/internal/renderer/lifecycle/RenderCache.d.ts.map +1 -0
- package/dist/src/internal/renderer/lifecycle/RenderCache.js +9 -0
- package/dist/src/internal/renderer/lifecycle/RenderCache.js.map +1 -0
- package/dist/src/internal/renderer/lifecycle/index.d.ts +4 -0
- package/dist/src/internal/renderer/lifecycle/index.d.ts.map +1 -0
- package/dist/src/internal/renderer/lifecycle/index.js +4 -0
- package/dist/src/internal/renderer/lifecycle/index.js.map +1 -0
- package/dist/src/internal/renderer/modes/FullscreenRenderer.d.ts +12 -0
- package/dist/src/internal/renderer/modes/FullscreenRenderer.d.ts.map +1 -0
- package/dist/src/internal/renderer/modes/FullscreenRenderer.js +54 -0
- package/dist/src/internal/renderer/modes/FullscreenRenderer.js.map +1 -0
- package/dist/src/internal/renderer/modes/InlineRenderer.d.ts +25 -0
- package/dist/src/internal/renderer/modes/InlineRenderer.d.ts.map +1 -0
- package/dist/src/internal/renderer/modes/InlineRenderer.js +166 -0
- package/dist/src/internal/renderer/modes/InlineRenderer.js.map +1 -0
- package/dist/src/internal/renderer/modes/RendererMode.d.ts +42 -0
- package/dist/src/internal/renderer/modes/RendererMode.d.ts.map +1 -0
- package/dist/src/internal/renderer/modes/RendererMode.js +2 -0
- package/dist/src/internal/renderer/modes/RendererMode.js.map +1 -0
- package/dist/src/internal/renderer/modes/StaticContentRenderer.d.ts +25 -0
- package/dist/src/internal/renderer/modes/StaticContentRenderer.d.ts.map +1 -0
- package/dist/src/internal/renderer/modes/StaticContentRenderer.js +49 -0
- package/dist/src/internal/renderer/modes/StaticContentRenderer.js.map +1 -0
- package/dist/src/internal/renderer/modes/index.d.ts +5 -0
- package/dist/src/internal/renderer/modes/index.d.ts.map +1 -0
- package/dist/src/internal/renderer/modes/index.js +4 -0
- package/dist/src/internal/renderer/modes/index.js.map +1 -0
- package/dist/src/internal/renderer/terminal/KeyboardCapabilityProbe.d.ts +13 -0
- package/dist/src/internal/renderer/terminal/KeyboardCapabilityProbe.d.ts.map +1 -0
- package/dist/src/internal/renderer/terminal/KeyboardCapabilityProbe.js +75 -0
- package/dist/src/internal/renderer/terminal/KeyboardCapabilityProbe.js.map +1 -0
- package/dist/src/internal/renderer/terminal/TerminalSetup.d.ts +29 -0
- package/dist/src/internal/renderer/terminal/TerminalSetup.d.ts.map +1 -0
- package/dist/src/internal/renderer/terminal/TerminalSetup.js +82 -0
- package/dist/src/internal/renderer/terminal/TerminalSetup.js.map +1 -0
- package/dist/src/internal/renderer/terminal/index.d.ts +3 -0
- package/dist/src/internal/renderer/terminal/index.d.ts.map +1 -0
- package/dist/src/internal/renderer/terminal/index.js +3 -0
- package/dist/src/internal/renderer/terminal/index.js.map +1 -0
- package/dist/src/internal/renderer/types.d.ts +122 -0
- package/dist/src/internal/renderer/types.d.ts.map +1 -0
- package/dist/src/internal/renderer/types.js +2 -0
- package/dist/src/internal/renderer/types.js.map +1 -0
- package/dist/src/motion/hooks.d.ts +1 -1
- package/dist/src/motion/hooks.js +1 -1
- package/dist/src/reconciler/host-config.js +2 -2
- package/dist/src/reconciler/host-config.js.map +1 -1
- package/dist/src/reconciler/types.d.ts +5 -1
- package/dist/src/reconciler/types.d.ts.map +1 -1
- package/dist/src/renderer-context.d.ts +1 -8
- package/dist/src/renderer-context.d.ts.map +1 -1
- package/dist/src/renderer-context.js +1 -21
- package/dist/src/renderer-context.js.map +1 -1
- package/dist/src/renderer-types.d.ts +1 -115
- package/dist/src/renderer-types.d.ts.map +1 -1
- package/dist/src/renderer.d.ts +1 -31
- package/dist/src/renderer.d.ts.map +1 -1
- package/dist/src/renderer.js +1 -495
- package/dist/src/renderer.js.map +1 -1
- package/dist/src/test/render-tui.d.ts +3 -3
- package/dist/src/test/render-tui.d.ts.map +1 -1
- package/dist/src/test/render-tui.js +16 -9
- package/dist/src/test/render-tui.js.map +1 -1
- package/dist/src/utils/alignment.d.ts +1 -1
- package/dist/src/utils/alignment.d.ts.map +1 -1
- package/dist/src/utils/alignment.js +0 -2
- package/dist/src/utils/alignment.js.map +1 -1
- package/dist/src/utils/border.d.ts +1 -1
- package/dist/src/utils/border.d.ts.map +1 -1
- package/dist/src/utils/border.js +2 -0
- package/dist/src/utils/border.js.map +1 -1
- package/dist/src/utils/console-helpers.d.ts +19 -0
- package/dist/src/utils/console-helpers.d.ts.map +1 -0
- package/dist/src/utils/console-helpers.js +61 -0
- package/dist/src/utils/console-helpers.js.map +1 -0
- package/dist/src/utils/index.d.ts +2 -1
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +2 -1
- package/dist/src/utils/index.js.map +1 -1
- package/dist/src/utils/styles.d.ts +8 -1
- package/dist/src/utils/styles.d.ts.map +1 -1
- package/dist/src/utils/styles.js +10 -8
- package/dist/src/utils/styles.js.map +1 -1
- package/dist/src/utils/text-layout.d.ts +22 -0
- package/dist/src/utils/text-layout.d.ts.map +1 -0
- package/dist/src/utils/text-layout.js +37 -0
- package/dist/src/utils/text-layout.js.map +1 -0
- package/dist/src/utils/text-wrap.d.ts +31 -1
- package/dist/src/utils/text-wrap.d.ts.map +1 -1
- package/dist/src/utils/text-wrap.js +205 -48
- package/dist/src/utils/text-wrap.js.map +1 -1
- package/dist/src/visualize/index.js +1 -1
- package/dist/src/visualize/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/codeblock.tsx +2 -2
- package/src/components/ListView.tsx +21 -23
- package/src/components/Markdown.tsx +3 -3
- package/src/components/MultilineTextInput.tsx +138 -344
- package/src/components/TextInput.tsx +54 -99
- package/src/components/text-editing.ts +180 -0
- package/src/console/ConsolePopover.tsx +124 -107
- package/src/debug/DebugOverlay.ts +15 -74
- package/src/debug/DiagnosticsPanel.tsx +1 -1
- package/src/dev.tsx +5 -458
- package/src/hooks/use-scroll.ts +85 -145
- package/src/hosts/base.ts +86 -3
- package/src/hosts/box.ts +37 -2
- package/src/hosts/canvas.ts +128 -42
- package/src/hosts/codeblock.ts +48 -35
- package/src/hosts/flex-container.ts +25 -6
- package/src/hosts/index.ts +11 -2
- package/src/hosts/layout-helpers.ts +20 -0
- package/src/hosts/leaf.ts +36 -0
- package/src/hosts/overlay-item.ts +8 -2
- package/src/hosts/overlay.ts +13 -11
- package/src/hosts/scroll.ts +228 -106
- package/src/hosts/single-child.ts +2 -0
- package/src/hosts/spacer.ts +8 -3
- package/src/hosts/text.ts +126 -132
- package/src/hosts/vstack.ts +1 -1
- package/src/hosts/zstack.ts +14 -9
- package/src/index.ts +2 -2
- package/src/internal/dev/hmr.ts +101 -0
- package/src/internal/dev/runtime.ts +170 -0
- package/src/internal/dev/ui.tsx +87 -0
- package/src/internal/renderer/context.ts +27 -0
- package/src/{renderer → internal/renderer}/core/FrameBuilder.ts +2 -2
- package/src/internal/renderer/index.ts +689 -0
- package/src/{renderer → internal/renderer}/input/InputProcessor.ts +10 -1
- package/src/{renderer → internal/renderer}/lifecycle/EventBus.ts +9 -1
- package/src/internal/renderer/lifecycle/ProcessLifecycle.ts +125 -0
- package/src/internal/renderer/lifecycle/index.ts +3 -0
- package/src/{renderer → internal/renderer}/modes/InlineRenderer.ts +5 -2
- package/src/{renderer → internal/renderer}/modes/RendererMode.ts +1 -1
- package/src/{renderer → internal/renderer}/modes/StaticContentRenderer.ts +5 -2
- package/src/internal/renderer/terminal/KeyboardCapabilityProbe.ts +91 -0
- package/src/{renderer/lifecycle → internal/renderer/terminal}/TerminalSetup.ts +4 -22
- package/src/internal/renderer/terminal/index.ts +2 -0
- package/src/internal/renderer/types.ts +129 -0
- package/src/motion/hooks.ts +1 -1
- package/src/reconciler/host-config.ts +2 -2
- package/src/reconciler/types.ts +7 -1
- package/src/renderer-context.ts +1 -27
- package/src/renderer-types.ts +10 -123
- package/src/renderer.ts +1 -619
- package/src/test/render-tui.ts +16 -10
- package/src/utils/alignment.ts +1 -3
- package/src/utils/border.ts +11 -1
- package/src/utils/console-helpers.ts +86 -0
- package/src/utils/index.ts +15 -1
- package/src/utils/styles.ts +16 -4
- package/src/utils/text-layout.ts +65 -0
- package/src/utils/text-wrap.ts +261 -48
- package/src/visualize/index.tsx +1 -1
- package/src/renderer/lifecycle/ResizeManager.ts +0 -65
- package/src/renderer/lifecycle/index.ts +0 -4
- /package/src/{renderer → internal/renderer}/core/RendererState.ts +0 -0
- /package/src/{renderer → internal/renderer}/core/index.ts +0 -0
- /package/src/{renderer → internal/renderer}/input/index.ts +0 -0
- /package/src/{renderer → internal/renderer}/lifecycle/RenderCache.ts +0 -0
- /package/src/{renderer → internal/renderer}/modes/FullscreenRenderer.ts +0 -0
- /package/src/{renderer → internal/renderer}/modes/index.ts +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { KeyMsg, MouseMsg } from "@effect-tui/core"
|
|
2
|
-
import type { FrameStats, PasteMsg } from "
|
|
2
|
+
import type { FrameStats, PasteMsg } from "../types.js"
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Centralized event subscription management for the renderer.
|
|
@@ -97,4 +97,12 @@ export class EventBus {
|
|
|
97
97
|
get hasFrameHandlers(): boolean {
|
|
98
98
|
return this.frameHandlers.size > 0
|
|
99
99
|
}
|
|
100
|
+
|
|
101
|
+
clear(): void {
|
|
102
|
+
this.keyHandlers.clear()
|
|
103
|
+
this.mouseHandlers.clear()
|
|
104
|
+
this.pasteHandlers.clear()
|
|
105
|
+
this.resizeHandlers.clear()
|
|
106
|
+
this.frameHandlers.clear()
|
|
107
|
+
}
|
|
100
108
|
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
type ExitHandler = () => void
|
|
2
|
+
type SignalHandler = (signal: NodeJS.Signals) => void
|
|
3
|
+
type UncaughtHandler = (err: Error) => void
|
|
4
|
+
type RejectionHandler = (reason: unknown) => void
|
|
5
|
+
|
|
6
|
+
export interface ProcessHandlers {
|
|
7
|
+
onExit?: ExitHandler
|
|
8
|
+
onSignal?: SignalHandler
|
|
9
|
+
onUncaughtException?: UncaughtHandler
|
|
10
|
+
onUnhandledRejection?: RejectionHandler
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const exitHandlers = new Set<ExitHandler>()
|
|
14
|
+
const signalHandlers = new Set<SignalHandler>()
|
|
15
|
+
const uncaughtHandlers = new Set<UncaughtHandler>()
|
|
16
|
+
const rejectionHandlers = new Set<RejectionHandler>()
|
|
17
|
+
|
|
18
|
+
let exitListenerAttached = false
|
|
19
|
+
let signalListenersAttached = false
|
|
20
|
+
let uncaughtListenerAttached = false
|
|
21
|
+
let rejectionListenerAttached = false
|
|
22
|
+
|
|
23
|
+
const dispatchExit = () => {
|
|
24
|
+
for (const handler of exitHandlers) handler()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const dispatchSignal = (signal: NodeJS.Signals) => {
|
|
28
|
+
for (const handler of signalHandlers) handler(signal)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const dispatchUncaught = (err: Error) => {
|
|
32
|
+
for (const handler of uncaughtHandlers) handler(err)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const dispatchRejection = (reason: unknown) => {
|
|
36
|
+
for (const handler of rejectionHandlers) handler(reason)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const ensureExitListener = () => {
|
|
40
|
+
if (exitListenerAttached) return
|
|
41
|
+
process.on("exit", dispatchExit)
|
|
42
|
+
exitListenerAttached = true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const ensureSignalListeners = () => {
|
|
46
|
+
if (signalListenersAttached) return
|
|
47
|
+
process.on("SIGINT", dispatchSignal)
|
|
48
|
+
process.on("SIGTERM", dispatchSignal)
|
|
49
|
+
signalListenersAttached = true
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const ensureUncaughtListener = () => {
|
|
53
|
+
if (uncaughtListenerAttached) return
|
|
54
|
+
process.on("uncaughtException", dispatchUncaught)
|
|
55
|
+
uncaughtListenerAttached = true
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const ensureRejectionListener = () => {
|
|
59
|
+
if (rejectionListenerAttached) return
|
|
60
|
+
process.on("unhandledRejection", dispatchRejection)
|
|
61
|
+
rejectionListenerAttached = true
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const maybeDetachExitListener = () => {
|
|
65
|
+
if (!exitListenerAttached || exitHandlers.size > 0) return
|
|
66
|
+
process.off("exit", dispatchExit)
|
|
67
|
+
exitListenerAttached = false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const maybeDetachSignalListeners = () => {
|
|
71
|
+
if (!signalListenersAttached || signalHandlers.size > 0) return
|
|
72
|
+
process.off("SIGINT", dispatchSignal)
|
|
73
|
+
process.off("SIGTERM", dispatchSignal)
|
|
74
|
+
signalListenersAttached = false
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const maybeDetachUncaughtListener = () => {
|
|
78
|
+
if (!uncaughtListenerAttached || uncaughtHandlers.size > 0) return
|
|
79
|
+
process.off("uncaughtException", dispatchUncaught)
|
|
80
|
+
uncaughtListenerAttached = false
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const maybeDetachRejectionListener = () => {
|
|
84
|
+
if (!rejectionListenerAttached || rejectionHandlers.size > 0) return
|
|
85
|
+
process.off("unhandledRejection", dispatchRejection)
|
|
86
|
+
rejectionListenerAttached = false
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const registerProcessHandlers = (handlers: ProcessHandlers): (() => void) => {
|
|
90
|
+
if (handlers.onExit) {
|
|
91
|
+
exitHandlers.add(handlers.onExit)
|
|
92
|
+
ensureExitListener()
|
|
93
|
+
}
|
|
94
|
+
if (handlers.onSignal) {
|
|
95
|
+
signalHandlers.add(handlers.onSignal)
|
|
96
|
+
ensureSignalListeners()
|
|
97
|
+
}
|
|
98
|
+
if (handlers.onUncaughtException) {
|
|
99
|
+
uncaughtHandlers.add(handlers.onUncaughtException)
|
|
100
|
+
ensureUncaughtListener()
|
|
101
|
+
}
|
|
102
|
+
if (handlers.onUnhandledRejection) {
|
|
103
|
+
rejectionHandlers.add(handlers.onUnhandledRejection)
|
|
104
|
+
ensureRejectionListener()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return () => {
|
|
108
|
+
if (handlers.onExit) {
|
|
109
|
+
exitHandlers.delete(handlers.onExit)
|
|
110
|
+
maybeDetachExitListener()
|
|
111
|
+
}
|
|
112
|
+
if (handlers.onSignal) {
|
|
113
|
+
signalHandlers.delete(handlers.onSignal)
|
|
114
|
+
maybeDetachSignalListeners()
|
|
115
|
+
}
|
|
116
|
+
if (handlers.onUncaughtException) {
|
|
117
|
+
uncaughtHandlers.delete(handlers.onUncaughtException)
|
|
118
|
+
maybeDetachUncaughtListener()
|
|
119
|
+
}
|
|
120
|
+
if (handlers.onUnhandledRejection) {
|
|
121
|
+
rejectionHandlers.delete(handlers.onUnhandledRejection)
|
|
122
|
+
maybeDetachRejectionListener()
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -163,12 +163,15 @@ export class InlineRenderer implements RendererMode {
|
|
|
163
163
|
return this._needsFullRerender
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
/** Clear the full rerender flag after handling */
|
|
166
|
+
/** Clear the full rerender flag after handling (keeps previousHeight for cursor tracking) */
|
|
167
167
|
clearFullRerenderFlag(): void {
|
|
168
168
|
this._needsFullRerender = false
|
|
169
|
-
|
|
169
|
+
// DON'T reset previousHeight - we need it for cursor positioning in generateOutput.
|
|
170
|
+
// After clear+replay static, the cursor is at end of static content.
|
|
171
|
+
// generateOutput will use previousHeight to know where dynamic content should go.
|
|
170
172
|
this.previousStartRow = 0
|
|
171
173
|
this.printedWidths = []
|
|
174
|
+
this._forceFullOutput = true // Force full output to resync rendering
|
|
172
175
|
}
|
|
173
176
|
|
|
174
177
|
reset(): void {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CellBuffer, emitRowWithReset, type Palette, rowContentWidth } from "@effect-tui/core"
|
|
2
|
-
import type { HostInstance } from "
|
|
3
|
-
import type { TuiWriteStream } from "
|
|
2
|
+
import type { HostInstance } from "../../../reconciler/types.js"
|
|
3
|
+
import type { TuiWriteStream } from "../types.js"
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Renders static content to scrollback (inline mode only).
|
|
@@ -31,6 +31,9 @@ export class StaticContentRenderer {
|
|
|
31
31
|
* Caller clears dynamic area first, then appends this output.
|
|
32
32
|
*/
|
|
33
33
|
render(staticNode: HostInstance, frameWidth: number): string {
|
|
34
|
+
// Pre-frame cache prep (optional)
|
|
35
|
+
staticNode.prepareFrame?.()
|
|
36
|
+
|
|
34
37
|
// Measure and layout static content
|
|
35
38
|
const staticSize = staticNode.measure(frameWidth, Number.MAX_SAFE_INTEGER)
|
|
36
39
|
staticNode.layout({ x: 0, y: 0, w: frameWidth, h: staticSize.h })
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { ANSI } from "@effect-tui/core"
|
|
2
|
+
import type { TuiWriteStream } from "../types.js"
|
|
3
|
+
|
|
4
|
+
type ProbeOptions = {
|
|
5
|
+
stdout: TuiWriteStream
|
|
6
|
+
timeoutMs?: number
|
|
7
|
+
onResolved: (supportsKitty: boolean) => void
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type KeyboardCapabilityProbe = {
|
|
11
|
+
start(): void
|
|
12
|
+
handleInput(input: string): string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const kittyResponseRe = /^\x1b\[\?\d+(?:;\d+)?u$/
|
|
16
|
+
|
|
17
|
+
export function createKeyboardCapabilityProbe(options: ProbeOptions): KeyboardCapabilityProbe {
|
|
18
|
+
const timeoutMs = options.timeoutMs ?? 150
|
|
19
|
+
let active = false
|
|
20
|
+
let resolved = false
|
|
21
|
+
let buffer = ""
|
|
22
|
+
let timer: ReturnType<typeof setTimeout> | null = null
|
|
23
|
+
|
|
24
|
+
const resolve = (supportsKitty: boolean) => {
|
|
25
|
+
if (resolved) return
|
|
26
|
+
resolved = true
|
|
27
|
+
active = false
|
|
28
|
+
buffer = ""
|
|
29
|
+
if (timer) {
|
|
30
|
+
clearTimeout(timer)
|
|
31
|
+
timer = null
|
|
32
|
+
}
|
|
33
|
+
options.onResolved(supportsKitty)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const handleCapabilitySequence = (sequence: string) => {
|
|
37
|
+
if (kittyResponseRe.test(sequence)) {
|
|
38
|
+
resolve(true)
|
|
39
|
+
} else if (sequence.includes("kitty")) {
|
|
40
|
+
resolve(true)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const handleInput = (input: string): string => {
|
|
45
|
+
if (!active) return input
|
|
46
|
+
let data = buffer + input
|
|
47
|
+
buffer = ""
|
|
48
|
+
let output = ""
|
|
49
|
+
let i = 0
|
|
50
|
+
|
|
51
|
+
while (i < data.length) {
|
|
52
|
+
if (data.startsWith("\x1b[?", i)) {
|
|
53
|
+
const end = data.indexOf("u", i + 3)
|
|
54
|
+
if (end === -1) {
|
|
55
|
+
buffer = data.slice(i)
|
|
56
|
+
break
|
|
57
|
+
}
|
|
58
|
+
const seq = data.slice(i, end + 1)
|
|
59
|
+
handleCapabilitySequence(seq)
|
|
60
|
+
i = end + 1
|
|
61
|
+
continue
|
|
62
|
+
}
|
|
63
|
+
if (data.startsWith("\x1bP>|", i)) {
|
|
64
|
+
const end = data.indexOf("\x1b\\", i + 4)
|
|
65
|
+
if (end === -1) {
|
|
66
|
+
buffer = data.slice(i)
|
|
67
|
+
break
|
|
68
|
+
}
|
|
69
|
+
const seq = data.slice(i, end + 2)
|
|
70
|
+
handleCapabilitySequence(seq)
|
|
71
|
+
i = end + 2
|
|
72
|
+
continue
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
output += data[i] as string
|
|
76
|
+
i += 1
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return output
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
start() {
|
|
84
|
+
if (resolved || active) return
|
|
85
|
+
active = true
|
|
86
|
+
options.stdout.write(ANSI.keyboard.query)
|
|
87
|
+
timer = setTimeout(() => resolve(false), timeoutMs)
|
|
88
|
+
},
|
|
89
|
+
handleInput,
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
import { ANSI, Terminal } from "@effect-tui/core"
|
|
2
|
-
import type { TuiReadStream, TuiWriteStream } from "
|
|
2
|
+
import type { TuiReadStream, TuiWriteStream } from "../types.js"
|
|
3
3
|
|
|
4
4
|
export interface TerminalSetupConfig {
|
|
5
5
|
mode: "fullscreen" | "inline"
|
|
6
6
|
enablePaste: boolean
|
|
7
7
|
enableMouse: boolean
|
|
8
8
|
skipTerminalSetup: boolean
|
|
9
|
-
/**
|
|
10
|
-
* Enable Kitty keyboard protocol for enhanced modifier detection.
|
|
11
|
-
* When enabled, Ctrl+Shift+C can be distinguished from Ctrl+C.
|
|
12
|
-
* Supported by: Kitty, iTerm2 3.5+, WezTerm, Ghostty, foot, Contour, rio.
|
|
13
|
-
* Gracefully ignored by terminals that don't support it.
|
|
14
|
-
* @default true
|
|
15
|
-
*/
|
|
16
|
-
enableKittyKeyboard?: boolean
|
|
17
9
|
}
|
|
18
10
|
|
|
19
11
|
/**
|
|
@@ -53,14 +45,6 @@ export class TerminalSetup {
|
|
|
53
45
|
this.stdout.write(ANSI.mouse.enable)
|
|
54
46
|
}
|
|
55
47
|
|
|
56
|
-
// Enable enhanced keyboard protocols for modifier detection
|
|
57
|
-
// This allows distinguishing Ctrl+Shift+C from Ctrl+C on supported terminals
|
|
58
|
-
// NOTE: Many terminals intercept Ctrl+Shift+C for their own copy function!
|
|
59
|
-
if (this.config.enableKittyKeyboard !== false) {
|
|
60
|
-
this.stdout.write(ANSI.keyboard.enable(1)) // Kitty protocol (flag 1 = disambiguate)
|
|
61
|
-
this.stdout.write(ANSI.modifyOtherKeys.enable) // xterm protocol (mode 2)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
48
|
if (this.stdin.isTTY && this.stdin.setRawMode) {
|
|
65
49
|
this.stdin.setRawMode(true)
|
|
66
50
|
this.stdin.resume?.()
|
|
@@ -85,11 +69,9 @@ export class TerminalSetup {
|
|
|
85
69
|
// This ensures all sequences are flushed together before process exit
|
|
86
70
|
let output = ""
|
|
87
71
|
|
|
88
|
-
// Disable enhanced keyboard protocols first
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
output += ANSI.modifyOtherKeys.disable
|
|
92
|
-
}
|
|
72
|
+
// Disable enhanced keyboard protocols first (safe to send regardless of support)
|
|
73
|
+
output += ANSI.keyboard.disable
|
|
74
|
+
output += ANSI.modifyOtherKeys.disable
|
|
93
75
|
|
|
94
76
|
if (this.config.enableMouse) {
|
|
95
77
|
output += ANSI.mouse.disable
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { KeyMsg, MouseMsg } from "@effect-tui/core"
|
|
2
|
+
import type { HostContext, HostInstance } from "../../reconciler/types.js"
|
|
3
|
+
|
|
4
|
+
export type PasteMsg = {
|
|
5
|
+
type: "paste"
|
|
6
|
+
text: string
|
|
7
|
+
/** Set by renderer to allow handlers to stop further propagation. */
|
|
8
|
+
defaultPrevented?: boolean
|
|
9
|
+
preventDefault?: () => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Minimal write stream interface for renderer output */
|
|
13
|
+
export interface TuiWriteStream {
|
|
14
|
+
write(s: string): void
|
|
15
|
+
columns: number
|
|
16
|
+
rows: number
|
|
17
|
+
on(event: string, cb: () => void): void
|
|
18
|
+
removeListener(event: string, cb: () => void): void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Minimal read stream interface for renderer input */
|
|
22
|
+
export interface TuiReadStream {
|
|
23
|
+
isTTY?: boolean
|
|
24
|
+
setRawMode?(mode: boolean): void
|
|
25
|
+
resume?(): void
|
|
26
|
+
on(event: string, cb: (data: Buffer) => void): void
|
|
27
|
+
removeListener(event: string, cb: (data: Buffer) => void): void
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface TuiRenderer {
|
|
31
|
+
/** Terminal width */
|
|
32
|
+
width: number
|
|
33
|
+
/** Terminal height */
|
|
34
|
+
height: number
|
|
35
|
+
/** Request a re-render */
|
|
36
|
+
requestRender(): void
|
|
37
|
+
/** Subscribe to per-frame stats (if enabled). */
|
|
38
|
+
onFrameStats?(handler: (stats: FrameStats) => void): () => void
|
|
39
|
+
/** Subscribe to keyboard events */
|
|
40
|
+
onKey(handler: (key: KeyMsg) => void): () => void
|
|
41
|
+
/** Subscribe to mouse events (clicks, scroll, etc.) */
|
|
42
|
+
onMouse(handler: (mouse: MouseMsg) => void): () => void
|
|
43
|
+
/** Subscribe to paste events (bracketed paste mode). */
|
|
44
|
+
onPaste?(handler: (paste: PasteMsg) => void): () => void
|
|
45
|
+
/** Subscribe to resize events */
|
|
46
|
+
onResize(handler: (width: number, height: number) => void): () => void
|
|
47
|
+
/** Stop the renderer */
|
|
48
|
+
stop(): void
|
|
49
|
+
/** Manually trigger one render frame (only in manualMode) */
|
|
50
|
+
renderNow(): void
|
|
51
|
+
/**
|
|
52
|
+
* Get the current screen as ANSI string (for screenshots/debugging).
|
|
53
|
+
* Returns the last rendered frame with all ANSI color codes intact.
|
|
54
|
+
*/
|
|
55
|
+
getScreenshot(): string
|
|
56
|
+
/** Dispatch a key event (for remote control) */
|
|
57
|
+
dispatchKey?(key: KeyMsg): void
|
|
58
|
+
/** Dispatch a paste event (for remote control) */
|
|
59
|
+
dispatchPaste?(text: string): void
|
|
60
|
+
/** Dispatch a resize event (for remote control) */
|
|
61
|
+
dispatchResize?(width: number, height: number): void
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Internal renderer type with container reference */
|
|
65
|
+
export interface TuiRendererInternal extends TuiRenderer {
|
|
66
|
+
_container: Container | null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface Container {
|
|
70
|
+
root: HostInstance | null
|
|
71
|
+
ctx: HostContext
|
|
72
|
+
/** @internal Static content root node (for Static component) */
|
|
73
|
+
staticRoot?: HostInstance | null
|
|
74
|
+
/** @internal Flag indicating static content needs flushing */
|
|
75
|
+
staticDirty?: boolean
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface RendererOptions {
|
|
79
|
+
fps?: number
|
|
80
|
+
stdout?: NodeJS.WriteStream | TuiWriteStream
|
|
81
|
+
stdin?: NodeJS.ReadStream | TuiReadStream
|
|
82
|
+
/** Render mode: "fullscreen" uses alternate buffer, "inline" renders in-place */
|
|
83
|
+
mode?: "fullscreen" | "inline"
|
|
84
|
+
/** Exit the process on Ctrl+C unless preventDefault was called. Defaults to true. */
|
|
85
|
+
exitOnCtrlC?: boolean
|
|
86
|
+
/** Handle SIGINT/SIGTERM and process exit cleanup. Defaults to true. */
|
|
87
|
+
handleSignals?: boolean
|
|
88
|
+
/** Exit the process after handling SIGINT/SIGTERM. Defaults to true. */
|
|
89
|
+
exitOnSignal?: boolean
|
|
90
|
+
/** Exit the process on render errors after logging to terminal. Defaults to true. */
|
|
91
|
+
exitOnRenderError?: boolean
|
|
92
|
+
/** Override exit codes for signals. Defaults: SIGINT=130, SIGTERM=143. */
|
|
93
|
+
signalExitCodes?: Partial<Record<"SIGINT" | "SIGTERM", number>>
|
|
94
|
+
/** Enable diffed rendering (per-line). Defaults to true in runtime, false in manualMode (tests). */
|
|
95
|
+
diff?: boolean
|
|
96
|
+
/** Skip automatic render loop. Call renderNow() manually to render frames. */
|
|
97
|
+
manualMode?: boolean
|
|
98
|
+
/** Skip fullscreen/raw mode setup (for testing) */
|
|
99
|
+
skipTerminalSetup?: boolean
|
|
100
|
+
/** Enable bracketed paste (default true). */
|
|
101
|
+
enablePaste?: boolean
|
|
102
|
+
/** Enable mouse mode for scroll wheel events (default true in fullscreen). */
|
|
103
|
+
enableMouse?: boolean
|
|
104
|
+
/** Enable Kitty/xterm keyboard protocols for enhanced modifier detection (default true). */
|
|
105
|
+
enableKittyKeyboard?: boolean
|
|
106
|
+
/** Emoji width handling: 1 or 2 forces width. */
|
|
107
|
+
emojiWidth?: 1 | 2
|
|
108
|
+
/** Optional per-frame diagnostics hook. Called after each frame is written. */
|
|
109
|
+
debug?: {
|
|
110
|
+
onFrame?: (stats: FrameStats) => void
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface FrameStats {
|
|
115
|
+
mode: "fullscreen" | "inline"
|
|
116
|
+
width: number
|
|
117
|
+
height: number
|
|
118
|
+
contentHeight: number
|
|
119
|
+
bytes: number
|
|
120
|
+
frameMs: number
|
|
121
|
+
phases: {
|
|
122
|
+
clear: number
|
|
123
|
+
layout: number
|
|
124
|
+
render: number
|
|
125
|
+
diffMs: number
|
|
126
|
+
write: number
|
|
127
|
+
}
|
|
128
|
+
timestamp: number
|
|
129
|
+
}
|
package/src/motion/hooks.ts
CHANGED
|
@@ -221,7 +221,7 @@ export function useColorMotionValue(initial: ColorInput): ColorMotionValue {
|
|
|
221
221
|
* // In canvas draw callback
|
|
222
222
|
* <canvas draw={(ctx) => {
|
|
223
223
|
* const { r, g, b } = colorMv.get()
|
|
224
|
-
* ctx.
|
|
224
|
+
* ctx.fillRect(0, 0, 10, 5, "█", { fg: Colors.rgb(r, g, b) })
|
|
225
225
|
* }} />
|
|
226
226
|
*/
|
|
227
227
|
export function useColorSpring(
|
|
@@ -110,8 +110,8 @@ const hostConfig = {
|
|
|
110
110
|
|
|
111
111
|
resetAfterCommit(container: Container) {
|
|
112
112
|
// If static content is dirty, flush immediately (bypassing throttle)
|
|
113
|
-
if (container.staticDirty && container.ctx.
|
|
114
|
-
container.ctx.
|
|
113
|
+
if (container.staticDirty && container.ctx.requestRenderNow) {
|
|
114
|
+
container.ctx.requestRenderNow()
|
|
115
115
|
} else {
|
|
116
116
|
container.ctx.requestRender()
|
|
117
117
|
}
|
package/src/reconciler/types.ts
CHANGED
|
@@ -32,6 +32,12 @@ export interface HostInstance {
|
|
|
32
32
|
/** Optional pre-frame hook for cache prep (called before measure/layout/render). */
|
|
33
33
|
prepareFrame?(): void
|
|
34
34
|
|
|
35
|
+
/** @internal Mark layout-related caches dirty. */
|
|
36
|
+
invalidateLayout?(): void
|
|
37
|
+
|
|
38
|
+
/** @internal Mark render-related caches dirty. */
|
|
39
|
+
invalidateRender?(): void
|
|
40
|
+
|
|
35
41
|
/** Update props from React */
|
|
36
42
|
updateProps(props: Record<string, unknown>): void
|
|
37
43
|
|
|
@@ -51,7 +57,7 @@ export interface HostInstance {
|
|
|
51
57
|
export interface HostContext {
|
|
52
58
|
requestRender(): void
|
|
53
59
|
/** @internal Trigger immediate render (bypasses throttling) for static content */
|
|
54
|
-
|
|
60
|
+
requestRenderNow?(): void
|
|
55
61
|
}
|
|
56
62
|
|
|
57
63
|
/**
|
package/src/renderer-context.ts
CHANGED
|
@@ -1,27 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import type { TuiRenderer } from "./renderer-types.js"
|
|
3
|
-
|
|
4
|
-
// Context for accessing renderer in components
|
|
5
|
-
export const RendererContext = createContext<TuiRenderer | null>(null)
|
|
6
|
-
|
|
7
|
-
export function useRenderer(): TuiRenderer {
|
|
8
|
-
const renderer = useContext(RendererContext)
|
|
9
|
-
if (!renderer) {
|
|
10
|
-
throw new Error("useRenderer must be used within a TUI renderer")
|
|
11
|
-
}
|
|
12
|
-
return renderer
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/** Hook that returns terminal size and re-renders on resize */
|
|
16
|
-
export function useTerminalSize(): { width: number; height: number } {
|
|
17
|
-
const renderer = useRenderer()
|
|
18
|
-
const [size, setSize] = useState({ width: renderer.width, height: renderer.height })
|
|
19
|
-
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
return renderer.onResize((width, height) => {
|
|
22
|
-
setSize({ width, height })
|
|
23
|
-
})
|
|
24
|
-
}, [renderer])
|
|
25
|
-
|
|
26
|
-
return size
|
|
27
|
-
}
|
|
1
|
+
export { RendererContext, useRenderer, useTerminalSize } from "./internal/renderer/context.js"
|
package/src/renderer-types.ts
CHANGED
|
@@ -1,123 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/** Minimal write stream interface for renderer output */
|
|
13
|
-
export interface TuiWriteStream {
|
|
14
|
-
write(s: string): void
|
|
15
|
-
columns: number
|
|
16
|
-
rows: number
|
|
17
|
-
on(event: string, cb: () => void): void
|
|
18
|
-
removeListener(event: string, cb: () => void): void
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** Minimal read stream interface for renderer input */
|
|
22
|
-
export interface TuiReadStream {
|
|
23
|
-
isTTY?: boolean
|
|
24
|
-
setRawMode?(mode: boolean): void
|
|
25
|
-
resume?(): void
|
|
26
|
-
on(event: string, cb: (data: Buffer) => void): void
|
|
27
|
-
removeListener(event: string, cb: (data: Buffer) => void): void
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface TuiRenderer {
|
|
31
|
-
/** Terminal width */
|
|
32
|
-
width: number
|
|
33
|
-
/** Terminal height */
|
|
34
|
-
height: number
|
|
35
|
-
/** Request a re-render */
|
|
36
|
-
requestRender(): void
|
|
37
|
-
/** Subscribe to per-frame stats (if enabled). */
|
|
38
|
-
onFrameStats?(handler: (stats: FrameStats) => void): () => void
|
|
39
|
-
/** Subscribe to keyboard events */
|
|
40
|
-
onKey(handler: (key: KeyMsg) => void): () => void
|
|
41
|
-
/** Subscribe to mouse events (clicks, scroll, etc.) */
|
|
42
|
-
onMouse(handler: (mouse: MouseMsg) => void): () => void
|
|
43
|
-
/** Subscribe to paste events (bracketed paste mode). */
|
|
44
|
-
onPaste?(handler: (paste: PasteMsg) => void): () => void
|
|
45
|
-
/** Subscribe to resize events */
|
|
46
|
-
onResize(handler: (width: number, height: number) => void): () => void
|
|
47
|
-
/** Stop the renderer */
|
|
48
|
-
stop(): void
|
|
49
|
-
/** Manually trigger one render frame (only in manualMode) */
|
|
50
|
-
flush(): void
|
|
51
|
-
/**
|
|
52
|
-
* Get the current screen as ANSI string (for screenshots/debugging).
|
|
53
|
-
* Returns the last rendered frame with all ANSI color codes intact.
|
|
54
|
-
*/
|
|
55
|
-
getScreenshot(): string
|
|
56
|
-
/** Dispatch a key event (for remote control) */
|
|
57
|
-
dispatchKey?(key: KeyMsg): void
|
|
58
|
-
/** Dispatch a paste event (for remote control) */
|
|
59
|
-
dispatchPaste?(text: string): void
|
|
60
|
-
/** Dispatch a resize event (for remote control) */
|
|
61
|
-
dispatchResize?(width: number, height: number): void
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** Internal renderer type with container reference */
|
|
65
|
-
export interface TuiRendererInternal extends TuiRenderer {
|
|
66
|
-
_container: Container | null
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface Container {
|
|
70
|
-
root: HostInstance | null
|
|
71
|
-
ctx: HostContext
|
|
72
|
-
/** @internal Static content root node (for Static component) */
|
|
73
|
-
staticRoot?: HostInstance | null
|
|
74
|
-
/** @internal Flag indicating static content needs flushing */
|
|
75
|
-
staticDirty?: boolean
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface RendererOptions {
|
|
79
|
-
fps?: number
|
|
80
|
-
stdout?: NodeJS.WriteStream | TuiWriteStream
|
|
81
|
-
stdin?: NodeJS.ReadStream | TuiReadStream
|
|
82
|
-
/** Render mode: "fullscreen" uses alternate buffer, "inline" renders in-place */
|
|
83
|
-
mode?: "fullscreen" | "inline"
|
|
84
|
-
/** Exit the process on Ctrl+C unless preventDefault was called. Defaults to true. */
|
|
85
|
-
exitOnCtrlC?: boolean
|
|
86
|
-
/** Handle SIGINT/SIGTERM and process exit cleanup. Defaults to true. */
|
|
87
|
-
handleSignals?: boolean
|
|
88
|
-
/** Exit the process after handling SIGINT/SIGTERM. Defaults to true. */
|
|
89
|
-
exitOnSignal?: boolean
|
|
90
|
-
/** Override exit codes for signals. Defaults: SIGINT=130, SIGTERM=143. */
|
|
91
|
-
signalExitCodes?: Partial<Record<"SIGINT" | "SIGTERM", number>>
|
|
92
|
-
/** Enable diffed rendering (per-line). Defaults to true in runtime, false in manualMode (tests). */
|
|
93
|
-
diff?: boolean
|
|
94
|
-
/** Skip automatic render loop. Call flush() manually to render frames. */
|
|
95
|
-
manualMode?: boolean
|
|
96
|
-
/** Skip fullscreen/raw mode setup (for testing) */
|
|
97
|
-
skipTerminalSetup?: boolean
|
|
98
|
-
/** Enable bracketed paste (default true). */
|
|
99
|
-
enablePaste?: boolean
|
|
100
|
-
/** Enable mouse mode for scroll wheel events (default true in fullscreen). */
|
|
101
|
-
enableMouse?: boolean
|
|
102
|
-
/** Optional per-frame diagnostics hook. Called after each frame is written. */
|
|
103
|
-
debug?: {
|
|
104
|
-
onFrame?: (stats: FrameStats) => void
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export interface FrameStats {
|
|
109
|
-
mode: "fullscreen" | "inline"
|
|
110
|
-
width: number
|
|
111
|
-
height: number
|
|
112
|
-
contentHeight: number
|
|
113
|
-
bytes: number
|
|
114
|
-
frameMs: number
|
|
115
|
-
phases: {
|
|
116
|
-
clear: number
|
|
117
|
-
layout: number
|
|
118
|
-
render: number
|
|
119
|
-
diffAnsi: number
|
|
120
|
-
write: number
|
|
121
|
-
}
|
|
122
|
-
timestamp: number
|
|
123
|
-
}
|
|
1
|
+
export type {
|
|
2
|
+
Container,
|
|
3
|
+
FrameStats,
|
|
4
|
+
PasteMsg,
|
|
5
|
+
RendererOptions,
|
|
6
|
+
TuiReadStream,
|
|
7
|
+
TuiRenderer,
|
|
8
|
+
TuiRendererInternal,
|
|
9
|
+
TuiWriteStream,
|
|
10
|
+
} from "./internal/renderer/types.js"
|