@effect-tui/react 0.1.1 → 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.
- package/dist/jsx-runtime.d.ts +13 -0
- package/dist/jsx-runtime.d.ts.map +1 -1
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/src/codeblock.d.ts.map +1 -1
- package/dist/src/codeblock.js.map +1 -1
- package/dist/src/components/Divider.d.ts +18 -0
- package/dist/src/components/Divider.d.ts.map +1 -0
- package/dist/src/components/Divider.js +17 -0
- package/dist/src/components/Divider.js.map +1 -0
- package/dist/src/components/Markdown.d.ts +66 -0
- package/dist/src/components/Markdown.d.ts.map +1 -0
- package/dist/src/components/Markdown.js +226 -0
- package/dist/src/components/Markdown.js.map +1 -0
- package/dist/src/components/MultilineTextInput.d.ts +65 -0
- package/dist/src/components/MultilineTextInput.d.ts.map +1 -0
- package/dist/src/components/MultilineTextInput.js +607 -0
- package/dist/src/components/MultilineTextInput.js.map +1 -0
- package/dist/src/components/Overlay.d.ts +46 -0
- package/dist/src/components/Overlay.d.ts.map +1 -0
- package/dist/src/components/Overlay.js +11 -0
- package/dist/src/components/Overlay.js.map +1 -0
- package/dist/src/components/Static.d.ts +44 -0
- package/dist/src/components/Static.d.ts.map +1 -0
- package/dist/src/components/Static.js +53 -0
- package/dist/src/components/Static.js.map +1 -0
- package/dist/src/components/TextInput.d.ts +53 -0
- package/dist/src/components/TextInput.d.ts.map +1 -0
- package/dist/src/components/TextInput.js +210 -0
- package/dist/src/components/TextInput.js.map +1 -0
- package/dist/src/components/index.d.ts +7 -0
- package/dist/src/components/index.d.ts.map +1 -0
- package/dist/src/components/index.js +7 -0
- package/dist/src/components/index.js.map +1 -0
- package/dist/src/components/text-editing.d.ts +62 -0
- package/dist/src/components/text-editing.d.ts.map +1 -0
- package/dist/src/components/text-editing.js +385 -0
- package/dist/src/components/text-editing.js.map +1 -0
- package/dist/src/console/ConsoleCapture.d.ts +36 -0
- package/dist/src/console/ConsoleCapture.d.ts.map +1 -0
- package/dist/src/console/ConsoleCapture.js +210 -0
- package/dist/src/console/ConsoleCapture.js.map +1 -0
- package/dist/src/console/ConsolePopover.d.ts +18 -0
- package/dist/src/console/ConsolePopover.d.ts.map +1 -0
- package/dist/src/console/ConsolePopover.js +324 -0
- package/dist/src/console/ConsolePopover.js.map +1 -0
- package/dist/src/console/clipboard.d.ts +10 -0
- package/dist/src/console/clipboard.d.ts.map +1 -0
- package/dist/src/console/clipboard.js +74 -0
- package/dist/src/console/clipboard.js.map +1 -0
- package/dist/src/console/index.d.ts +5 -0
- package/dist/src/console/index.d.ts.map +1 -0
- package/dist/src/console/index.js +33 -0
- package/dist/src/console/index.js.map +1 -0
- package/dist/src/console/useConsole.d.ts +44 -0
- package/dist/src/console/useConsole.d.ts.map +1 -0
- package/dist/src/console/useConsole.js +91 -0
- package/dist/src/console/useConsole.js.map +1 -0
- package/dist/src/debug/DebugOverlay.d.ts +49 -0
- package/dist/src/debug/DebugOverlay.d.ts.map +1 -0
- package/dist/src/debug/DebugOverlay.js +438 -0
- package/dist/src/debug/DebugOverlay.js.map +1 -0
- package/dist/src/debug/DiagnosticsPanel.d.ts.map +1 -1
- package/dist/src/debug/DiagnosticsPanel.js.map +1 -1
- package/dist/src/dev/Toast.d.ts +19 -0
- package/dist/src/dev/Toast.d.ts.map +1 -0
- package/dist/src/dev/Toast.js +72 -0
- package/dist/src/dev/Toast.js.map +1 -0
- package/dist/src/dev/index.d.ts +2 -0
- package/dist/src/dev/index.d.ts.map +1 -0
- package/dist/src/dev/index.js +3 -0
- package/dist/src/dev/index.js.map +1 -0
- package/dist/src/dev.d.ts +114 -0
- package/dist/src/dev.d.ts.map +1 -0
- package/dist/src/dev.js +373 -0
- package/dist/src/dev.js.map +1 -0
- package/dist/src/highlight.d.ts +3 -3
- package/dist/src/highlight.d.ts.map +1 -1
- package/dist/src/highlight.js.map +1 -1
- package/dist/src/hmr-plugin.d.ts +2 -0
- package/dist/src/hmr-plugin.d.ts.map +1 -0
- package/dist/src/hmr-plugin.js +53 -0
- package/dist/src/hmr-plugin.js.map +1 -0
- package/dist/src/hooks/index.d.ts +4 -0
- package/dist/src/hooks/index.d.ts.map +1 -1
- package/dist/src/hooks/index.js +2 -0
- package/dist/src/hooks/index.js.map +1 -1
- package/dist/src/hooks/use-keyboard.d.ts +11 -0
- package/dist/src/hooks/use-keyboard.d.ts.map +1 -1
- package/dist/src/hooks/use-keyboard.js +22 -4
- package/dist/src/hooks/use-keyboard.js.map +1 -1
- package/dist/src/hooks/use-mouse.d.ts +24 -0
- package/dist/src/hooks/use-mouse.d.ts.map +1 -0
- package/dist/src/hooks/use-mouse.js +41 -0
- package/dist/src/hooks/use-mouse.js.map +1 -0
- package/dist/src/hooks/use-paste.d.ts +11 -0
- package/dist/src/hooks/use-paste.d.ts.map +1 -1
- package/dist/src/hooks/use-paste.js +17 -3
- package/dist/src/hooks/use-paste.js.map +1 -1
- package/dist/src/hooks/use-scroll.d.ts +79 -0
- package/dist/src/hooks/use-scroll.d.ts.map +1 -0
- package/dist/src/hooks/use-scroll.js +239 -0
- package/dist/src/hooks/use-scroll.js.map +1 -0
- package/dist/src/hooks/useFrameStats.js.map +1 -1
- package/dist/src/hosts/base.d.ts +62 -1
- package/dist/src/hosts/base.d.ts.map +1 -1
- package/dist/src/hosts/base.js +118 -5
- package/dist/src/hosts/base.js.map +1 -1
- package/dist/src/hosts/box.d.ts +7 -7
- package/dist/src/hosts/box.d.ts.map +1 -1
- package/dist/src/hosts/box.js +31 -26
- package/dist/src/hosts/box.js.map +1 -1
- package/dist/src/hosts/canvas.d.ts +8 -8
- package/dist/src/hosts/canvas.d.ts.map +1 -1
- package/dist/src/hosts/canvas.js +13 -22
- package/dist/src/hosts/canvas.js.map +1 -1
- package/dist/src/hosts/codeblock.d.ts +7 -7
- package/dist/src/hosts/codeblock.d.ts.map +1 -1
- package/dist/src/hosts/codeblock.js +11 -20
- package/dist/src/hosts/codeblock.js.map +1 -1
- package/dist/src/hosts/flex-container.d.ts +45 -0
- package/dist/src/hosts/flex-container.d.ts.map +1 -0
- package/dist/src/hosts/flex-container.js +90 -0
- package/dist/src/hosts/flex-container.js.map +1 -0
- package/dist/src/hosts/hstack.d.ts +6 -11
- package/dist/src/hosts/hstack.d.ts.map +1 -1
- package/dist/src/hosts/hstack.js +6 -41
- package/dist/src/hosts/hstack.js.map +1 -1
- package/dist/src/hosts/index.d.ts +4 -0
- package/dist/src/hosts/index.d.ts.map +1 -1
- package/dist/src/hosts/index.js +10 -0
- package/dist/src/hosts/index.js.map +1 -1
- package/dist/src/hosts/overlay-item.d.ts +32 -0
- package/dist/src/hosts/overlay-item.d.ts.map +1 -0
- package/dist/src/hosts/overlay-item.js +54 -0
- package/dist/src/hosts/overlay-item.js.map +1 -0
- package/dist/src/hosts/overlay.d.ts +30 -0
- package/dist/src/hosts/overlay.d.ts.map +1 -0
- package/dist/src/hosts/overlay.js +105 -0
- package/dist/src/hosts/overlay.js.map +1 -0
- package/dist/src/hosts/scroll.d.ts +56 -0
- package/dist/src/hosts/scroll.d.ts.map +1 -0
- package/dist/src/hosts/scroll.js +204 -0
- package/dist/src/hosts/scroll.js.map +1 -0
- package/dist/src/hosts/single-child.d.ts +16 -0
- package/dist/src/hosts/single-child.d.ts.map +1 -0
- package/dist/src/hosts/single-child.js +45 -0
- package/dist/src/hosts/single-child.js.map +1 -0
- package/dist/src/hosts/spacer.d.ts.map +1 -1
- package/dist/src/hosts/spacer.js +7 -3
- package/dist/src/hosts/spacer.js.map +1 -1
- package/dist/src/hosts/text.d.ts +9 -6
- package/dist/src/hosts/text.d.ts.map +1 -1
- package/dist/src/hosts/text.js +49 -22
- package/dist/src/hosts/text.js.map +1 -1
- package/dist/src/hosts/vstack.d.ts +6 -11
- package/dist/src/hosts/vstack.d.ts.map +1 -1
- package/dist/src/hosts/vstack.js +6 -41
- package/dist/src/hosts/vstack.js.map +1 -1
- package/dist/src/hosts/zstack.d.ts.map +1 -1
- package/dist/src/hosts/zstack.js +16 -5
- package/dist/src/hosts/zstack.js.map +1 -1
- package/dist/src/index.d.ts +9 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +10 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/inline/index.d.ts.map +1 -1
- package/dist/src/inline/index.js.map +1 -1
- package/dist/src/motion/color-motion-value.d.ts.map +1 -1
- package/dist/src/motion/color-motion-value.js.map +1 -1
- package/dist/src/motion/color.d.ts +1 -29
- package/dist/src/motion/color.d.ts.map +1 -1
- package/dist/src/motion/color.js +2 -170
- package/dist/src/motion/color.js.map +1 -1
- package/dist/src/motion/color.test.js.map +1 -1
- package/dist/src/motion/event-emitter.d.ts.map +1 -1
- package/dist/src/motion/event-emitter.js.map +1 -1
- package/dist/src/motion/frame.js.map +1 -1
- package/dist/src/motion/hooks.d.ts.map +1 -1
- package/dist/src/motion/hooks.js +8 -3
- package/dist/src/motion/hooks.js.map +1 -1
- package/dist/src/motion/index.d.ts.map +1 -1
- package/dist/src/motion/index.js.map +1 -1
- package/dist/src/motion/motion-value.d.ts.map +1 -1
- package/dist/src/motion/motion-value.js.map +1 -1
- package/dist/src/motion/motion-value.test.js.map +1 -1
- package/dist/src/motion/spring-math.d.ts +6 -1
- package/dist/src/motion/spring-math.d.ts.map +1 -1
- package/dist/src/motion/spring-math.js +6 -1
- package/dist/src/motion/spring-math.js.map +1 -1
- package/dist/src/motion/types.d.ts.map +1 -1
- package/dist/src/motion/types.js.map +1 -1
- package/dist/src/profiler.js.map +1 -1
- package/dist/src/reconciler/host-config.d.ts +5 -5
- package/dist/src/reconciler/host-config.d.ts.map +1 -1
- package/dist/src/reconciler/host-config.js +43 -51
- package/dist/src/reconciler/host-config.js.map +1 -1
- package/dist/src/reconciler/noop-methods.d.ts +29 -0
- package/dist/src/reconciler/noop-methods.d.ts.map +1 -0
- package/dist/src/reconciler/noop-methods.js +43 -0
- package/dist/src/reconciler/noop-methods.js.map +1 -0
- package/dist/src/reconciler/types.d.ts +68 -14
- package/dist/src/reconciler/types.d.ts.map +1 -1
- package/dist/src/remote/Procedures.d.ts +22 -0
- package/dist/src/remote/Procedures.d.ts.map +1 -0
- package/dist/src/remote/Procedures.js +42 -0
- package/dist/src/remote/Procedures.js.map +1 -0
- package/dist/src/remote/Router.d.ts +20 -0
- package/dist/src/remote/Router.d.ts.map +1 -0
- package/dist/src/remote/Router.js +26 -0
- package/dist/src/remote/Router.js.map +1 -0
- package/dist/src/remote/Server.d.ts +6 -0
- package/dist/src/remote/Server.d.ts.map +1 -0
- package/dist/src/remote/Server.js +53 -0
- package/dist/src/remote/Server.js.map +1 -0
- package/dist/src/remote/index.d.ts +18 -0
- package/dist/src/remote/index.d.ts.map +1 -0
- package/dist/src/remote/index.js +74 -0
- package/dist/src/remote/index.js.map +1 -0
- package/dist/src/renderer/core/FrameBuilder.d.ts +18 -0
- package/dist/src/renderer/core/FrameBuilder.d.ts.map +1 -0
- package/dist/src/renderer/core/FrameBuilder.js +38 -0
- package/dist/src/renderer/core/FrameBuilder.js.map +1 -0
- package/dist/src/renderer/core/RendererState.d.ts +41 -0
- package/dist/src/renderer/core/RendererState.d.ts.map +1 -0
- package/dist/src/renderer/core/RendererState.js +70 -0
- package/dist/src/renderer/core/RendererState.js.map +1 -0
- package/dist/src/renderer/core/index.d.ts +3 -0
- package/dist/src/renderer/core/index.d.ts.map +1 -0
- package/dist/src/renderer/core/index.js +3 -0
- package/dist/src/renderer/core/index.js.map +1 -0
- package/dist/src/renderer/input/InputProcessor.d.ts +25 -0
- package/dist/src/renderer/input/InputProcessor.d.ts.map +1 -0
- package/dist/src/renderer/input/InputProcessor.js +81 -0
- package/dist/src/renderer/input/InputProcessor.js.map +1 -0
- package/dist/src/renderer/input/index.d.ts +2 -0
- package/dist/src/renderer/input/index.d.ts.map +1 -0
- package/dist/src/renderer/input/index.js +2 -0
- package/dist/src/renderer/input/index.js.map +1 -0
- package/dist/src/renderer/lifecycle/EventBus.d.ts +41 -0
- package/dist/src/renderer/lifecycle/EventBus.d.ts.map +1 -0
- package/dist/src/renderer/lifecycle/EventBus.js +78 -0
- package/dist/src/renderer/lifecycle/EventBus.js.map +1 -0
- package/dist/src/renderer/lifecycle/ResizeManager.d.ts +34 -0
- package/dist/src/renderer/lifecycle/ResizeManager.d.ts.map +1 -0
- package/dist/src/renderer/lifecycle/ResizeManager.js +47 -0
- package/dist/src/renderer/lifecycle/ResizeManager.js.map +1 -0
- package/dist/src/renderer/lifecycle/TerminalSetup.d.ts +36 -0
- package/dist/src/renderer/lifecycle/TerminalSetup.d.ts.map +1 -0
- package/dist/src/renderer/lifecycle/TerminalSetup.js +82 -0
- package/dist/src/renderer/lifecycle/TerminalSetup.js.map +1 -0
- package/dist/src/renderer/lifecycle/index.d.ts +4 -0
- package/dist/src/renderer/lifecycle/index.d.ts.map +1 -0
- package/dist/src/renderer/lifecycle/index.js +4 -0
- package/dist/src/renderer/lifecycle/index.js.map +1 -0
- package/dist/src/renderer/modes/FullscreenRenderer.d.ts +12 -0
- package/dist/src/renderer/modes/FullscreenRenderer.d.ts.map +1 -0
- package/dist/src/renderer/modes/FullscreenRenderer.js +52 -0
- package/dist/src/renderer/modes/FullscreenRenderer.js.map +1 -0
- package/dist/src/renderer/modes/InlineRenderer.d.ts +22 -0
- package/dist/src/renderer/modes/InlineRenderer.d.ts.map +1 -0
- package/dist/src/renderer/modes/InlineRenderer.js +154 -0
- package/dist/src/renderer/modes/InlineRenderer.js.map +1 -0
- package/dist/src/renderer/modes/RendererMode.d.ts +42 -0
- package/dist/src/renderer/modes/RendererMode.d.ts.map +1 -0
- package/dist/src/renderer/modes/RendererMode.js +2 -0
- package/dist/src/renderer/modes/RendererMode.js.map +1 -0
- package/dist/src/renderer/modes/StaticContentRenderer.d.ts +25 -0
- package/dist/src/renderer/modes/StaticContentRenderer.d.ts.map +1 -0
- package/dist/src/renderer/modes/StaticContentRenderer.js +47 -0
- package/dist/src/renderer/modes/StaticContentRenderer.js.map +1 -0
- package/dist/src/renderer/modes/index.d.ts +5 -0
- package/dist/src/renderer/modes/index.d.ts.map +1 -0
- package/dist/src/renderer/modes/index.js +4 -0
- package/dist/src/renderer/modes/index.js.map +1 -0
- package/dist/src/renderer-context.d.ts +9 -0
- package/dist/src/renderer-context.d.ts.map +1 -0
- package/dist/src/renderer-context.js +22 -0
- package/dist/src/renderer-context.js.map +1 -0
- package/dist/src/renderer-types.d.ts +103 -0
- package/dist/src/renderer-types.d.ts.map +1 -0
- package/dist/src/renderer-types.js +2 -0
- package/dist/src/renderer-types.js.map +1 -0
- package/dist/src/renderer.d.ts +4 -86
- package/dist/src/renderer.d.ts.map +1 -1
- package/dist/src/renderer.js +213 -384
- package/dist/src/renderer.js.map +1 -1
- package/dist/src/test/index.d.ts.map +1 -1
- package/dist/src/test/index.js.map +1 -1
- package/dist/src/test/mock-streams.d.ts.map +1 -1
- package/dist/src/test/mock-streams.js.map +1 -1
- package/dist/src/test/render-tui.d.ts.map +1 -1
- package/dist/src/test/render-tui.js +2 -5
- package/dist/src/test/render-tui.js.map +1 -1
- package/dist/src/trace/SpanTree.d.ts.map +1 -1
- package/dist/src/trace/SpanTree.js +21 -11
- package/dist/src/trace/SpanTree.js.map +1 -1
- package/dist/src/trace/format-value.d.ts +15 -0
- package/dist/src/trace/format-value.d.ts.map +1 -0
- package/dist/src/trace/format-value.js +77 -0
- package/dist/src/trace/format-value.js.map +1 -0
- package/dist/src/trace/index.d.ts.map +1 -1
- package/dist/src/trace/index.js.map +1 -1
- package/dist/src/trace/location.js +1 -1
- package/dist/src/trace/location.js.map +1 -1
- package/dist/src/trace/span-processor.d.ts.map +1 -1
- package/dist/src/trace/span-processor.js.map +1 -1
- package/dist/src/trace/span-state.d.ts +19 -2
- package/dist/src/trace/span-state.d.ts.map +1 -1
- package/dist/src/trace/span-state.js +62 -31
- package/dist/src/trace/span-state.js.map +1 -1
- package/dist/src/trace/tui-logger.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 +6 -0
- package/dist/src/utils/border.js.map +1 -1
- package/dist/src/utils/flex-layout.d.ts +2 -1
- package/dist/src/utils/flex-layout.d.ts.map +1 -1
- package/dist/src/utils/flex-layout.js +22 -33
- package/dist/src/utils/flex-layout.js.map +1 -1
- package/dist/src/utils/index.d.ts +1 -1
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +1 -1
- package/dist/src/utils/index.js.map +1 -1
- package/dist/src/utils/padding.d.ts.map +1 -1
- package/dist/src/utils/padding.js.map +1 -1
- package/dist/src/utils/styles.d.ts +20 -1
- package/dist/src/utils/styles.d.ts.map +1 -1
- package/dist/src/utils/styles.js +36 -1
- package/dist/src/utils/styles.js.map +1 -1
- package/dist/src/visualize/index.d.ts +8 -19
- package/dist/src/visualize/index.d.ts.map +1 -1
- package/dist/src/visualize/index.js +11 -25
- package/dist/src/visualize/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/jsx-dev-runtime.ts +5 -0
- package/jsx-runtime.ts +54 -0
- package/package.json +124 -92
- package/src/codeblock.tsx +34 -34
- package/src/components/Divider.tsx +23 -0
- package/src/components/Markdown.tsx +380 -0
- package/src/components/MultilineTextInput.tsx +749 -0
- package/src/components/Overlay.tsx +56 -0
- package/src/components/Static.tsx +68 -0
- package/src/components/TextInput.tsx +285 -0
- package/src/components/index.ts +6 -0
- package/src/components/text-editing.ts +464 -0
- package/src/console/ConsoleCapture.ts +272 -0
- package/src/console/ConsolePopover.tsx +487 -0
- package/src/console/clipboard.ts +81 -0
- package/src/console/index.ts +42 -0
- package/src/console/useConsole.ts +129 -0
- package/src/debug/DebugOverlay.ts +557 -0
- package/src/debug/DiagnosticsPanel.tsx +27 -27
- package/src/dev/Toast.tsx +117 -0
- package/src/dev/index.ts +2 -0
- package/src/dev.tsx +489 -0
- package/src/highlight.ts +46 -46
- package/src/hmr-plugin.ts +61 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/use-keyboard.ts +44 -24
- package/src/hooks/use-mouse.ts +51 -0
- package/src/hooks/use-paste.ts +21 -6
- package/src/hooks/use-scroll.ts +386 -0
- package/src/hooks/useFrameStats.ts +17 -17
- package/src/hosts/base.ts +180 -59
- package/src/hosts/box.ts +117 -96
- package/src/hosts/canvas.ts +137 -141
- package/src/hosts/codeblock.ts +117 -133
- package/src/hosts/flex-container.ts +124 -0
- package/src/hosts/hstack.ts +11 -59
- package/src/hosts/index.ts +24 -14
- package/src/hosts/overlay-item.ts +72 -0
- package/src/hosts/overlay.ts +125 -0
- package/src/hosts/scroll.ts +255 -0
- package/src/hosts/single-child.ts +52 -0
- package/src/hosts/spacer.ts +30 -26
- package/src/hosts/text.ts +198 -164
- package/src/hosts/vstack.ts +11 -59
- package/src/hosts/zstack.ts +79 -67
- package/src/index.ts +44 -19
- package/src/inline/index.tsx +123 -123
- package/src/motion/color-motion-value.ts +67 -67
- package/src/motion/color.test.ts +107 -107
- package/src/motion/color.ts +9 -190
- package/src/motion/event-emitter.ts +20 -20
- package/src/motion/frame.ts +35 -35
- package/src/motion/hooks.ts +144 -139
- package/src/motion/index.ts +10 -10
- package/src/motion/motion-value.test.ts +207 -207
- package/src/motion/motion-value.ts +112 -112
- package/src/motion/spring-math.ts +88 -83
- package/src/motion/types.ts +25 -25
- package/src/profiler.ts +50 -50
- package/src/reconciler/host-config.ts +152 -174
- package/src/reconciler/noop-methods.ts +55 -0
- package/src/reconciler/types.ts +112 -46
- package/src/remote/Procedures.ts +52 -0
- package/src/remote/Router.ts +58 -0
- package/src/remote/Server.ts +76 -0
- package/src/remote/index.ts +90 -0
- package/src/renderer/core/FrameBuilder.ts +49 -0
- package/src/renderer/core/RendererState.ts +80 -0
- package/src/renderer/core/index.ts +2 -0
- package/src/renderer/input/InputProcessor.ts +94 -0
- package/src/renderer/input/index.ts +1 -0
- package/src/renderer/lifecycle/EventBus.ts +90 -0
- package/src/renderer/lifecycle/ResizeManager.ts +65 -0
- package/src/renderer/lifecycle/TerminalSetup.ts +105 -0
- package/src/renderer/lifecycle/index.ts +3 -0
- package/src/renderer/modes/FullscreenRenderer.ts +53 -0
- package/src/renderer/modes/InlineRenderer.ts +178 -0
- package/src/renderer/modes/RendererMode.ts +46 -0
- package/src/renderer/modes/StaticContentRenderer.ts +56 -0
- package/src/renderer/modes/index.ts +4 -0
- package/src/renderer-context.ts +27 -0
- package/src/renderer-types.ts +109 -0
- package/src/renderer.ts +391 -642
- package/src/test/index.ts +5 -5
- package/src/test/mock-streams.ts +115 -115
- package/src/test/render-tui.ts +84 -87
- package/src/utils/border.ts +79 -73
- package/src/utils/flex-layout.ts +80 -93
- package/src/utils/index.ts +1 -1
- package/src/utils/padding.ts +27 -27
- package/src/utils/styles.ts +50 -7
- package/src/visualize/index.tsx +225 -240
- package/dist/src/output.d.ts +0 -47
- package/dist/src/output.d.ts.map +0 -1
- package/dist/src/output.js +0 -125
- package/dist/src/output.js.map +0 -1
- package/dist/src/terminal.d.ts +0 -37
- package/dist/src/terminal.d.ts.map +0 -1
- package/dist/src/terminal.js +0 -65
- package/dist/src/terminal.js.map +0 -1
- package/src/output.ts +0 -156
- package/src/terminal.ts +0 -67
- package/src/trace/SpanTree.tsx +0 -195
- package/src/trace/index.tsx +0 -205
- package/src/trace/location.ts +0 -90
- package/src/trace/span-processor.ts +0 -65
- package/src/trace/span-state.ts +0 -286
- package/src/trace/tui-logger.ts +0 -72
package/dist/src/renderer.js
CHANGED
|
@@ -1,31 +1,16 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {} from "react";
|
|
2
2
|
import { performance } from "node:perf_hooks";
|
|
3
|
-
import {
|
|
4
|
-
import { reconciler } from "./reconciler/host-config.js";
|
|
5
|
-
import { ANSI, Terminal } from "./terminal.js";
|
|
3
|
+
import { ANSI, bufferToString } from "@effect-tui/core";
|
|
4
|
+
import { reconciler, flushSync } from "./reconciler/host-config.js";
|
|
6
5
|
import * as Prof from "./profiler.js";
|
|
7
6
|
import { DEFAULT_FPS } from "./constants.js";
|
|
8
|
-
import {
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
return renderer;
|
|
17
|
-
}
|
|
18
|
-
/** Hook that returns terminal size and re-renders on resize */
|
|
19
|
-
export function useTerminalSize() {
|
|
20
|
-
const renderer = useRenderer();
|
|
21
|
-
const [size, setSize] = useState({ width: renderer.width, height: renderer.height });
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
return renderer.onResize((width, height) => {
|
|
24
|
-
setSize({ width, height });
|
|
25
|
-
});
|
|
26
|
-
}, [renderer]);
|
|
27
|
-
return size;
|
|
28
|
-
}
|
|
7
|
+
import { RendererContext } from "./renderer-context.js";
|
|
8
|
+
// Extracted modules
|
|
9
|
+
import { RendererState, FrameBuilder } from "./renderer/core/index.js";
|
|
10
|
+
import { InputProcessor } from "./renderer/input/index.js";
|
|
11
|
+
import { EventBus, TerminalSetup } from "./renderer/lifecycle/index.js";
|
|
12
|
+
import { FullscreenRenderer, InlineRenderer, StaticContentRenderer } from "./renderer/modes/index.js";
|
|
13
|
+
export { RendererContext, useRenderer, useTerminalSize } from "./renderer-context.js";
|
|
29
14
|
export function createRenderer(options) {
|
|
30
15
|
const fps = options?.fps ?? DEFAULT_FPS;
|
|
31
16
|
const stdout = options?.stdout ?? process.stdout;
|
|
@@ -34,388 +19,247 @@ export function createRenderer(options) {
|
|
|
34
19
|
const exitOnCtrlC = options?.exitOnCtrlC ?? true;
|
|
35
20
|
const manualMode = options?.manualMode ?? false;
|
|
36
21
|
const enableDiff = options?.diff ?? !manualMode;
|
|
37
|
-
const enableDiffInline = options?.diffInline ?? false;
|
|
38
22
|
const skipTerminalSetup = options?.skipTerminalSetup ?? false;
|
|
39
23
|
const enablePaste = options?.enablePaste ?? true;
|
|
24
|
+
const enableMouse = options?.enableMouse ?? mode === "fullscreen";
|
|
40
25
|
const debugHook = options?.debug?.onFrame;
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
stdout.write(PASTE_DISABLE);
|
|
73
|
-
}
|
|
74
|
-
stdout.write(Terminal.showCursor);
|
|
75
|
-
if (stdin.isTTY && stdin.setRawMode) {
|
|
76
|
-
stdin.setRawMode(false);
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
// The actual render logic, extracted for manual flushing
|
|
26
|
+
// Initialize state
|
|
27
|
+
const state = new RendererState(stdout.columns || 80, stdout.rows || 24);
|
|
28
|
+
const events = new EventBus();
|
|
29
|
+
const frameBuilder = new FrameBuilder();
|
|
30
|
+
// Terminal setup/teardown
|
|
31
|
+
const terminal = new TerminalSetup(stdout, stdin, {
|
|
32
|
+
mode,
|
|
33
|
+
enablePaste,
|
|
34
|
+
enableMouse,
|
|
35
|
+
skipTerminalSetup,
|
|
36
|
+
});
|
|
37
|
+
// Render mode (fullscreen or inline)
|
|
38
|
+
const renderMode = mode === "fullscreen" ? new FullscreenRenderer() : new InlineRenderer();
|
|
39
|
+
// Static content renderer (inline mode only)
|
|
40
|
+
const staticRenderer = mode === "inline" ? new StaticContentRenderer(stdout, state.palette) : null;
|
|
41
|
+
// Input processing
|
|
42
|
+
const inputProcessor = new InputProcessor({
|
|
43
|
+
exitOnCtrlC,
|
|
44
|
+
dispatchKey: (key) => {
|
|
45
|
+
events.dispatchKey(key);
|
|
46
|
+
return key.defaultPrevented ?? false;
|
|
47
|
+
},
|
|
48
|
+
dispatchMouse: (mouse) => events.dispatchMouse(mouse),
|
|
49
|
+
dispatchPaste: (text) => events.dispatchPaste(text),
|
|
50
|
+
flushSync: (fn) => flushSync(fn) ?? undefined,
|
|
51
|
+
onInputProcessed: () => {
|
|
52
|
+
if (!manualMode)
|
|
53
|
+
renderFrame();
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
// The render frame logic
|
|
80
57
|
const renderFrame = () => {
|
|
81
58
|
const frameStart = Prof.startFrame();
|
|
82
59
|
const frameStartMs = performance.now();
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
let
|
|
86
|
-
let diffAnsiMs = 0;
|
|
87
|
-
let writeMs = 0;
|
|
88
|
-
let contentH = height;
|
|
60
|
+
const frameWidth = state.width;
|
|
61
|
+
const frameHeight = state.height;
|
|
62
|
+
let contentH = frameHeight;
|
|
89
63
|
const container = renderer._container;
|
|
90
64
|
const root = container?.root ?? null;
|
|
91
|
-
if
|
|
65
|
+
// Must render if dirty OR if static content needs flushing
|
|
66
|
+
if ((!state.dirty && !container?.staticDirty) || !root)
|
|
92
67
|
return;
|
|
93
|
-
dirty = false;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
nextBuffer.clear(0);
|
|
106
|
-
clearMs = performance.now() - t0;
|
|
107
|
-
}
|
|
108
|
-
Prof.endPhase("clear", t);
|
|
109
|
-
// Layout
|
|
110
|
-
t = Prof.startPhase();
|
|
111
|
-
{
|
|
112
|
-
const t0 = performance.now();
|
|
113
|
-
root.measure(width, height);
|
|
114
|
-
root.layout({ x: 0, y: 0, w: width, h: height });
|
|
115
|
-
layoutMs = performance.now() - t0;
|
|
116
|
-
}
|
|
117
|
-
Prof.endPhase("layout", t);
|
|
118
|
-
// Render
|
|
119
|
-
t = Prof.startPhase();
|
|
120
|
-
{
|
|
121
|
-
const t0 = performance.now();
|
|
122
|
-
root.render(nextBuffer, palette);
|
|
123
|
-
renderMs = performance.now() - t0;
|
|
124
|
-
}
|
|
125
|
-
Prof.endPhase("render", t);
|
|
126
|
-
// Output based on mode
|
|
127
|
-
t = Prof.startPhase();
|
|
128
|
-
const diffStartMs = performance.now();
|
|
129
|
-
let output = "";
|
|
130
|
-
if (mode === "fullscreen") {
|
|
131
|
-
// Fullscreen: optionally diff per line for minimal writes
|
|
132
|
-
if (enableDiff && prevBuffer) {
|
|
133
|
-
for (let y = 0; y < height; y++) {
|
|
134
|
-
if (!rowChanged(prevBuffer, nextBuffer, y, width))
|
|
135
|
-
continue;
|
|
136
|
-
output += ANSI.cursor.to(1, y + 1);
|
|
137
|
-
// Clear the row using default style to avoid carrying stale backgrounds.
|
|
138
|
-
output += palette.sgr(0) + ANSI.line.clear;
|
|
139
|
-
output += emitRowWithReset(nextBuffer, palette, y, width);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
// Full redraw (tests/manual mode)
|
|
144
|
-
stdout.write(ANSI.cursor.to(1, 1) + palette.sgr(0));
|
|
145
|
-
for (let y = 0; y < height; y++) {
|
|
146
|
-
output += emitRowWithReset(nextBuffer, palette, y, width);
|
|
147
|
-
if (y < height - 1)
|
|
148
|
-
output += "\r\n";
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
// ============================================================
|
|
154
|
-
// INLINE MODE RENDERING
|
|
155
|
-
// ============================================================
|
|
156
|
-
// Renders in-place without alternate buffer. Key insights from Ink:
|
|
157
|
-
// - Track previousHeight to know how many lines to erase
|
|
158
|
-
// - Trim trailing spaces to prevent wrap on terminal shrink
|
|
159
|
-
// - Safety valve: clear terminal if content >= terminal height
|
|
160
|
-
// ============================================================
|
|
161
|
-
const newHeight = contentHeight(nextBuffer, width, height);
|
|
162
|
-
contentH = newHeight;
|
|
163
|
-
// Safety valve: if previous content would overflow, clear terminal first
|
|
164
|
-
if (previousHeight >= height) {
|
|
165
|
-
stdout.write(ANSI.screen.clear + ANSI.cursor.to(1, 1));
|
|
166
|
-
previousHeight = 0;
|
|
167
|
-
}
|
|
168
|
-
// Move cursor up to start of previous output (eraseLines pattern)
|
|
169
|
-
if (previousHeight > 0) {
|
|
170
|
-
output += ANSI.cursor.up(previousHeight);
|
|
171
|
-
output += ANSI.cursor.startOfLine;
|
|
172
|
-
}
|
|
173
|
-
if (enableDiffInline && prevBuffer) {
|
|
174
|
-
// Diff-based inline rendering: only update changed regions
|
|
175
|
-
const rowsToProcess = Math.max(newHeight, previousHeight);
|
|
176
|
-
for (let y = 0; y < rowsToProcess; y++) {
|
|
177
|
-
// Rows beyond newHeight: clear if previously printed
|
|
178
|
-
if (y >= newHeight) {
|
|
179
|
-
if ((printedWidths.get(y) ?? 0) > 0) {
|
|
180
|
-
output += ANSI.cursor.to(y + 1, 1) + palette.sgr(0) + ANSI.line.clear;
|
|
181
|
-
printedWidths.set(y, 0);
|
|
182
|
-
}
|
|
183
|
-
continue;
|
|
184
|
-
}
|
|
185
|
-
const change = findChangeWindow(prevBuffer, nextBuffer, y, width);
|
|
186
|
-
const newW = rowContentWidth(nextBuffer, y, width);
|
|
187
|
-
const prevW = printedWidths.get(y) ?? 0;
|
|
188
|
-
if (!change) {
|
|
189
|
-
// No change; maybe need to clear tail if content shrunk
|
|
190
|
-
if (prevW > newW) {
|
|
191
|
-
output += ANSI.cursor.to(y + 1, newW + 1) + palette.sgr(0) + ANSI.line.clearToEnd;
|
|
192
|
-
printedWidths.set(y, newW);
|
|
193
|
-
}
|
|
194
|
-
continue;
|
|
68
|
+
state.dirty = false;
|
|
69
|
+
try {
|
|
70
|
+
// Handle full rerender on resize (Ink-style: clear everything + replay static)
|
|
71
|
+
if (mode === "inline" && staticRenderer) {
|
|
72
|
+
const inlineMode = renderMode;
|
|
73
|
+
if (inlineMode.needsFullRerender()) {
|
|
74
|
+
// Clear screen + scrollback + cursor home
|
|
75
|
+
stdout.write(ANSI.screen.clear + ANSI.screen.clearScrollback + ANSI.cursor.home);
|
|
76
|
+
// Replay all cached static content
|
|
77
|
+
const cachedStatic = staticRenderer.getCachedOutput();
|
|
78
|
+
if (cachedStatic) {
|
|
79
|
+
stdout.write(cachedStatic);
|
|
195
80
|
}
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
// Clear tail if shrunk
|
|
200
|
-
const effectiveW = Math.max(newW, change.right + 1);
|
|
201
|
-
if (prevW > effectiveW) {
|
|
202
|
-
output += ANSI.cursor.to(y + 1, effectiveW + 1) + ANSI.line.clearToEnd;
|
|
203
|
-
}
|
|
204
|
-
printedWidths.set(y, effectiveW);
|
|
81
|
+
// Reset state
|
|
82
|
+
inlineMode.clearFullRerenderFlag();
|
|
83
|
+
state.invalidateBuffers();
|
|
205
84
|
}
|
|
206
|
-
previousHeight = newHeight;
|
|
207
85
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
86
|
+
// Handle static content: clear dynamic area, append static, then fresh dynamic render
|
|
87
|
+
// Note: IL (insert lines) won't work here because inline mode uses relative positioning
|
|
88
|
+
// and IL would desync the screen state from our buffer tracking.
|
|
89
|
+
let staticOutput = "";
|
|
90
|
+
if (mode === "inline" && container?.staticDirty && container?.staticRoot && staticRenderer) {
|
|
91
|
+
const inlineMode = renderMode;
|
|
92
|
+
const prevHeight = inlineMode.getPreviousHeight();
|
|
93
|
+
// Step 1: Clear the dynamic area (move up + clear to end of screen)
|
|
94
|
+
if (prevHeight > 0) {
|
|
95
|
+
staticOutput += ANSI.cursor.up(prevHeight) + ANSI.cursor.startOfLine + ANSI.screen.clearToEnd;
|
|
215
96
|
}
|
|
216
|
-
//
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
output += ANSI.cursor.up(previousHeight - newHeight);
|
|
223
|
-
}
|
|
224
|
-
previousHeight = newHeight;
|
|
97
|
+
// Step 2: Append static content (cursor ends at bottom of static)
|
|
98
|
+
staticOutput += staticRenderer.render(container.staticRoot, frameWidth);
|
|
99
|
+
// Step 3: Reset previousHeight to 0 (we cleared dynamic, starting fresh)
|
|
100
|
+
inlineMode.reset();
|
|
101
|
+
state.invalidateBuffers();
|
|
102
|
+
container.staticDirty = false;
|
|
225
103
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
104
|
+
// For inline mode, measure content unconstrained to handle overflow
|
|
105
|
+
let actualContentHeight = frameHeight;
|
|
106
|
+
if (mode === "inline") {
|
|
107
|
+
const size = root.measure(frameWidth, Number.MAX_SAFE_INTEGER);
|
|
108
|
+
actualContentHeight = size.h;
|
|
109
|
+
}
|
|
110
|
+
// Buffer height: content height for inline (to capture all content), terminal height for fullscreen
|
|
111
|
+
const bufferHeight = mode === "inline" ? Math.max(actualContentHeight, frameHeight) : frameHeight;
|
|
112
|
+
// Ensure buffers exist
|
|
113
|
+
state.ensureBuffers(frameWidth, bufferHeight);
|
|
114
|
+
if (!state.nextBuffer)
|
|
115
|
+
return;
|
|
116
|
+
// Build frame (clear, layout, render)
|
|
117
|
+
const timings = frameBuilder.build(root, state.nextBuffer, state.palette, frameWidth, bufferHeight);
|
|
118
|
+
// Generate output
|
|
119
|
+
const t = Prof.startPhase();
|
|
120
|
+
const diffStartMs = performance.now();
|
|
121
|
+
const { output: modeOutput, contentHeight } = renderMode.generateOutput({
|
|
122
|
+
nextBuffer: state.nextBuffer,
|
|
123
|
+
prevBuffer: state.prevBuffer,
|
|
124
|
+
palette: state.palette,
|
|
125
|
+
frameWidth,
|
|
126
|
+
frameHeight,
|
|
127
|
+
contentHeight: actualContentHeight,
|
|
128
|
+
enableDiff,
|
|
129
|
+
stdout,
|
|
130
|
+
});
|
|
131
|
+
// Combine static + dynamic output for atomic write
|
|
132
|
+
let output = staticOutput + modeOutput + state.palette.sgr(0);
|
|
133
|
+
contentH = contentHeight;
|
|
134
|
+
const diffAnsiMs = performance.now() - diffStartMs;
|
|
135
|
+
Prof.endPhase("diff+ansi", t);
|
|
136
|
+
// Write output (single atomic write prevents visual glitches)
|
|
137
|
+
const writeT = Prof.startPhase();
|
|
138
|
+
const writeStart = performance.now();
|
|
233
139
|
stdout.write(output);
|
|
234
|
-
writeMs = performance.now() -
|
|
140
|
+
const writeMs = performance.now() - writeStart;
|
|
141
|
+
Prof.endPhase("write", writeT);
|
|
142
|
+
Prof.endFrame(frameStart);
|
|
143
|
+
const frameMs = performance.now() - frameStartMs;
|
|
144
|
+
// Swap buffers
|
|
145
|
+
state.swapBuffers();
|
|
146
|
+
// Build stats
|
|
147
|
+
const stats = {
|
|
148
|
+
mode,
|
|
149
|
+
width: state.width,
|
|
150
|
+
height: state.height,
|
|
151
|
+
contentHeight: contentH,
|
|
152
|
+
bytes: Buffer.byteLength(output, "utf8"),
|
|
153
|
+
frameMs,
|
|
154
|
+
phases: {
|
|
155
|
+
clear: timings.clear,
|
|
156
|
+
layout: timings.layout,
|
|
157
|
+
render: timings.render,
|
|
158
|
+
diffAnsi: diffAnsiMs,
|
|
159
|
+
write: writeMs,
|
|
160
|
+
},
|
|
161
|
+
timestamp: performance.now(),
|
|
162
|
+
};
|
|
163
|
+
if (debugHook)
|
|
164
|
+
debugHook(stats);
|
|
165
|
+
if (events.hasFrameHandlers)
|
|
166
|
+
events.dispatchFrame(stats);
|
|
235
167
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
// Swap buffers
|
|
240
|
-
const tmp = prevBuffer;
|
|
241
|
-
prevBuffer = nextBuffer;
|
|
242
|
-
nextBuffer = tmp;
|
|
243
|
-
const stats = {
|
|
244
|
-
mode,
|
|
245
|
-
width,
|
|
246
|
-
height,
|
|
247
|
-
contentHeight: contentH,
|
|
248
|
-
bytes: Buffer.byteLength(output, "utf8"),
|
|
249
|
-
frameMs,
|
|
250
|
-
phases: {
|
|
251
|
-
clear: clearMs,
|
|
252
|
-
layout: layoutMs,
|
|
253
|
-
render: renderMs,
|
|
254
|
-
diffAnsi: diffAnsiMs,
|
|
255
|
-
write: writeMs,
|
|
256
|
-
},
|
|
257
|
-
timestamp: performance.now(),
|
|
258
|
-
};
|
|
259
|
-
if (debugHook)
|
|
260
|
-
debugHook(stats);
|
|
261
|
-
if (frameHandlers.size > 0) {
|
|
262
|
-
for (const handler of frameHandlers)
|
|
263
|
-
handler(stats);
|
|
168
|
+
catch (err) {
|
|
169
|
+
console.error("[effect-tui] Render error:", err);
|
|
170
|
+
state.markDirty();
|
|
264
171
|
}
|
|
265
172
|
};
|
|
173
|
+
// Build renderer object
|
|
266
174
|
const renderer = {
|
|
267
175
|
get width() {
|
|
268
|
-
return width;
|
|
176
|
+
return state.width;
|
|
269
177
|
},
|
|
270
178
|
get height() {
|
|
271
|
-
return height;
|
|
179
|
+
return state.height;
|
|
272
180
|
},
|
|
273
181
|
requestRender() {
|
|
274
|
-
|
|
275
|
-
},
|
|
276
|
-
onKey(handler) {
|
|
277
|
-
keyHandlers.add(handler);
|
|
278
|
-
return () => keyHandlers.delete(handler);
|
|
279
|
-
},
|
|
280
|
-
onPaste(handler) {
|
|
281
|
-
pasteHandlers.add(handler);
|
|
282
|
-
return () => pasteHandlers.delete(handler);
|
|
283
|
-
},
|
|
284
|
-
onResize(handler) {
|
|
285
|
-
resizeHandlers.add(handler);
|
|
286
|
-
return () => resizeHandlers.delete(handler);
|
|
287
|
-
},
|
|
288
|
-
onFrameStats(handler) {
|
|
289
|
-
frameHandlers.add(handler);
|
|
290
|
-
return () => frameHandlers.delete(handler);
|
|
182
|
+
state.markDirty();
|
|
291
183
|
},
|
|
184
|
+
onKey: (handler) => events.onKey(handler),
|
|
185
|
+
onMouse: (handler) => events.onMouse(handler),
|
|
186
|
+
onPaste: (handler) => events.onPaste(handler),
|
|
187
|
+
onResize: (handler) => events.onResize(handler),
|
|
188
|
+
onFrameStats: (handler) => events.onFrameStats(handler),
|
|
292
189
|
stop() {
|
|
293
|
-
running = false;
|
|
294
|
-
if (loop) {
|
|
295
|
-
clearInterval(loop);
|
|
296
|
-
loop = null;
|
|
190
|
+
state.running = false;
|
|
191
|
+
if (state.loop) {
|
|
192
|
+
clearInterval(state.loop);
|
|
193
|
+
state.loop = null;
|
|
194
|
+
}
|
|
195
|
+
if (state.inputHandler) {
|
|
196
|
+
stdin.removeListener("data", state.inputHandler);
|
|
197
|
+
state.inputHandler = null;
|
|
198
|
+
}
|
|
199
|
+
if (state.resizeHandler) {
|
|
200
|
+
stdout.removeListener("resize", state.resizeHandler);
|
|
201
|
+
state.resizeHandler = null;
|
|
297
202
|
}
|
|
298
|
-
teardown();
|
|
203
|
+
terminal.teardown();
|
|
299
204
|
},
|
|
300
205
|
flush() {
|
|
301
206
|
renderFrame();
|
|
302
207
|
},
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
stdout.write(Terminal.enterFullscreen);
|
|
308
|
-
}
|
|
309
|
-
// Hide cursor during rendering (both modes)
|
|
310
|
-
stdout.write(Terminal.hideCursor);
|
|
311
|
-
if (enablePaste)
|
|
312
|
-
stdout.write(PASTE_ENABLE);
|
|
313
|
-
if (stdin.isTTY && stdin.setRawMode) {
|
|
314
|
-
stdin.setRawMode(true);
|
|
315
|
-
stdin.resume?.();
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
// Handle keyboard input (and bracketed paste)
|
|
319
|
-
stdin.on("data", (data) => {
|
|
320
|
-
let chunk = data.toString("utf8");
|
|
321
|
-
const emitKeys = (str) => {
|
|
322
|
-
if (!str)
|
|
323
|
-
return;
|
|
324
|
-
const keys = decodeKeys(Buffer.from(str, "utf8"));
|
|
325
|
-
for (const key of keys) {
|
|
326
|
-
const wrapped = {
|
|
327
|
-
...key,
|
|
328
|
-
defaultPrevented: false,
|
|
329
|
-
preventDefault() {
|
|
330
|
-
wrapped.defaultPrevented = true;
|
|
331
|
-
},
|
|
332
|
-
};
|
|
333
|
-
for (const handler of keyHandlers) {
|
|
334
|
-
if (wrapped.defaultPrevented)
|
|
335
|
-
break;
|
|
336
|
-
handler(wrapped);
|
|
337
|
-
}
|
|
338
|
-
// Default Ctrl+C handling - exit unless user called preventDefault()
|
|
339
|
-
if (exitOnCtrlC && !wrapped.defaultPrevented && key.ctrl && key.text === "c") {
|
|
340
|
-
process.exit(0);
|
|
341
|
-
}
|
|
208
|
+
getScreenshot() {
|
|
209
|
+
// Return the previous buffer as ANSI string (it has the last rendered frame)
|
|
210
|
+
if (state.prevBuffer) {
|
|
211
|
+
return bufferToString(state.prevBuffer, state.palette, state.width, state.height);
|
|
342
212
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
emitKeys(chunk);
|
|
372
|
-
chunk = "";
|
|
373
|
-
}
|
|
374
|
-
dirty = true;
|
|
375
|
-
});
|
|
376
|
-
// Handle resize - render synchronously like Ink does
|
|
377
|
-
stdout.on("resize", () => {
|
|
213
|
+
return "";
|
|
214
|
+
},
|
|
215
|
+
dispatchKey(key) {
|
|
216
|
+
events.dispatchKey(key);
|
|
217
|
+
if (!manualMode)
|
|
218
|
+
renderFrame();
|
|
219
|
+
},
|
|
220
|
+
dispatchPaste(text) {
|
|
221
|
+
events.dispatchPaste(text);
|
|
222
|
+
if (!manualMode)
|
|
223
|
+
renderFrame();
|
|
224
|
+
},
|
|
225
|
+
dispatchResize(width, height) {
|
|
226
|
+
state.updateDimensions(width, height);
|
|
227
|
+
state.invalidateBuffers();
|
|
228
|
+
state.markDirty();
|
|
229
|
+
events.dispatchResize(width, height);
|
|
230
|
+
if (!manualMode)
|
|
231
|
+
renderFrame();
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
// Terminal setup
|
|
235
|
+
terminal.setup();
|
|
236
|
+
// Input handling
|
|
237
|
+
state.inputHandler = (data) => inputProcessor.process(data);
|
|
238
|
+
stdin.on("data", state.inputHandler);
|
|
239
|
+
// Resize handling
|
|
240
|
+
state.resizeHandler = () => {
|
|
378
241
|
const newWidth = stdout.columns || 80;
|
|
379
242
|
const newHeight = stdout.rows || 24;
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
stdout.write(ANSI.cursor.up(previousHeight) + ANSI.cursor.startOfLine);
|
|
389
|
-
stdout.write(ANSI.screen.clearToEnd);
|
|
390
|
-
previousHeight = 0;
|
|
391
|
-
}
|
|
392
|
-
width = newWidth;
|
|
393
|
-
height = newHeight;
|
|
394
|
-
lastWidth = newWidth;
|
|
395
|
-
prevBuffer = null;
|
|
396
|
-
nextBuffer = null;
|
|
397
|
-
dirty = true;
|
|
398
|
-
// Notify resize handlers
|
|
399
|
-
for (const handler of resizeHandlers) {
|
|
400
|
-
handler(newWidth, newHeight);
|
|
401
|
-
}
|
|
402
|
-
// Render immediately on resize (like Ink) to prevent cursor corruption
|
|
403
|
-
renderFrame();
|
|
404
|
-
});
|
|
405
|
-
// Automatic render loop (skip in manual mode)
|
|
243
|
+
renderMode.handleResize(newWidth, newHeight, state.lastWidth);
|
|
244
|
+
state.updateDimensions(newWidth, newHeight);
|
|
245
|
+
state.invalidateBuffers();
|
|
246
|
+
state.markDirty();
|
|
247
|
+
events.dispatchResize(newWidth, newHeight);
|
|
248
|
+
};
|
|
249
|
+
stdout.on("resize", state.resizeHandler);
|
|
250
|
+
// Render loop
|
|
406
251
|
if (!manualMode) {
|
|
407
252
|
const frameMs = 1000 / fps;
|
|
408
|
-
loop = setInterval(() => {
|
|
409
|
-
if (!running) {
|
|
410
|
-
if (loop)
|
|
411
|
-
clearInterval(loop);
|
|
412
|
-
teardown();
|
|
253
|
+
state.loop = setInterval(() => {
|
|
254
|
+
if (!state.running) {
|
|
255
|
+
if (state.loop)
|
|
256
|
+
clearInterval(state.loop);
|
|
257
|
+
terminal.teardown();
|
|
413
258
|
return;
|
|
414
259
|
}
|
|
415
260
|
renderFrame();
|
|
416
261
|
}, frameMs);
|
|
417
262
|
}
|
|
418
|
-
// Store container reference for direct root access
|
|
419
263
|
;
|
|
420
264
|
renderer._container = null;
|
|
421
265
|
return renderer;
|
|
@@ -423,29 +267,19 @@ export function createRenderer(options) {
|
|
|
423
267
|
export function createRoot(renderer) {
|
|
424
268
|
const hostContext = {
|
|
425
269
|
requestRender: () => renderer.requestRender(),
|
|
270
|
+
requestImmediateRender: () => renderer.flush(),
|
|
426
271
|
};
|
|
427
272
|
const container = {
|
|
428
273
|
root: null,
|
|
429
274
|
ctx: hostContext,
|
|
430
275
|
};
|
|
431
|
-
const fiberRoot = reconciler.createContainer(container, 0,
|
|
432
|
-
null, // hydrationCallbacks
|
|
433
|
-
false, // isStrictMode
|
|
434
|
-
null, // concurrentUpdatesByDefaultOverride
|
|
435
|
-
"", // identifierPrefix
|
|
436
|
-
(err) => console.error(err), // onUncaughtError
|
|
437
|
-
(err) => console.error(err), // onCaughtError
|
|
438
|
-
(err) => console.error(err), // onRecoverableError
|
|
439
|
-
() => { }, // onDefaultTransitionIndicator
|
|
440
|
-
null);
|
|
276
|
+
const fiberRoot = reconciler.createContainer(container, 0, null, false, null, "", (err) => console.error(err), (err) => console.error(err), (err) => console.error(err), () => { }, null);
|
|
441
277
|
renderer._container = container;
|
|
442
|
-
const reconcilerAny = reconciler;
|
|
443
|
-
const runSync = reconcilerAny.flushSync?.bind(reconcilerAny) ?? ((fn) => fn());
|
|
444
278
|
return {
|
|
445
279
|
render(element, sync = false) {
|
|
446
280
|
const wrapped = React.createElement(RendererContext.Provider, { value: renderer }, element);
|
|
447
281
|
if (sync) {
|
|
448
|
-
|
|
282
|
+
flushSync(() => {
|
|
449
283
|
reconciler.updateContainer(wrapped, fiberRoot, null, null);
|
|
450
284
|
});
|
|
451
285
|
renderer.requestRender();
|
|
@@ -463,14 +297,9 @@ export function createRoot(renderer) {
|
|
|
463
297
|
},
|
|
464
298
|
};
|
|
465
299
|
}
|
|
466
|
-
/**
|
|
467
|
-
* Render a React tree to the terminal in one call.
|
|
468
|
-
* Returns helpers similar to Ink: rerender, unmount, waitUntilExit.
|
|
469
|
-
*/
|
|
470
300
|
export function render(element, options) {
|
|
471
301
|
const renderer = createRenderer(options);
|
|
472
302
|
const root = createRoot(renderer);
|
|
473
|
-
// Initial render (sync to avoid flicker before the loop runs)
|
|
474
303
|
root.render(element, true);
|
|
475
304
|
let resolved = false;
|
|
476
305
|
let resolveExit = null;
|