@effect-tui/react 0.1.3 → 0.1.5
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 +55 -0
- package/dist/src/components/TextInput.d.ts.map +1 -0
- package/dist/src/components/TextInput.js +277 -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 +30 -23
- package/dist/src/hosts/box.js.map +1 -1
- package/dist/src/hosts/canvas.d.ts +16 -8
- package/dist/src/hosts/canvas.d.ts.map +1 -1
- package/dist/src/hosts/canvas.js +27 -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 +25 -0
- package/dist/src/renderer/modes/InlineRenderer.d.ts.map +1 -0
- package/dist/src/renderer/modes/InlineRenderer.js +161 -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 +214 -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 +356 -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 -94
- package/src/hosts/canvas.ts +170 -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 +186 -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 +392 -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,248 @@ 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
|
-
|
|
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
|
+
inlineMode.forceFullOutputOnce(); // Force full output to resync cursor tracking after static
|
|
102
|
+
state.invalidateBuffers();
|
|
103
|
+
container.staticDirty = false;
|
|
225
104
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
105
|
+
// For inline mode, measure content unconstrained to handle overflow
|
|
106
|
+
let actualContentHeight = frameHeight;
|
|
107
|
+
if (mode === "inline") {
|
|
108
|
+
const size = root.measure(frameWidth, Number.MAX_SAFE_INTEGER);
|
|
109
|
+
actualContentHeight = size.h;
|
|
110
|
+
}
|
|
111
|
+
// Buffer height: content height for inline (to capture all content), terminal height for fullscreen
|
|
112
|
+
const bufferHeight = mode === "inline" ? Math.max(actualContentHeight, frameHeight) : frameHeight;
|
|
113
|
+
// Ensure buffers exist
|
|
114
|
+
state.ensureBuffers(frameWidth, bufferHeight);
|
|
115
|
+
if (!state.nextBuffer)
|
|
116
|
+
return;
|
|
117
|
+
// Build frame (clear, layout, render)
|
|
118
|
+
const timings = frameBuilder.build(root, state.nextBuffer, state.palette, frameWidth, bufferHeight);
|
|
119
|
+
// Generate output
|
|
120
|
+
const t = Prof.startPhase();
|
|
121
|
+
const diffStartMs = performance.now();
|
|
122
|
+
const { output: modeOutput, contentHeight } = renderMode.generateOutput({
|
|
123
|
+
nextBuffer: state.nextBuffer,
|
|
124
|
+
prevBuffer: state.prevBuffer,
|
|
125
|
+
palette: state.palette,
|
|
126
|
+
frameWidth,
|
|
127
|
+
frameHeight,
|
|
128
|
+
contentHeight: actualContentHeight,
|
|
129
|
+
enableDiff,
|
|
130
|
+
stdout,
|
|
131
|
+
});
|
|
132
|
+
// Combine static + dynamic output for atomic write
|
|
133
|
+
let output = staticOutput + modeOutput + state.palette.sgr(0);
|
|
134
|
+
contentH = contentHeight;
|
|
135
|
+
const diffAnsiMs = performance.now() - diffStartMs;
|
|
136
|
+
Prof.endPhase("diff+ansi", t);
|
|
137
|
+
// Write output (single atomic write prevents visual glitches)
|
|
138
|
+
const writeT = Prof.startPhase();
|
|
139
|
+
const writeStart = performance.now();
|
|
233
140
|
stdout.write(output);
|
|
234
|
-
writeMs = performance.now() -
|
|
141
|
+
const writeMs = performance.now() - writeStart;
|
|
142
|
+
Prof.endPhase("write", writeT);
|
|
143
|
+
Prof.endFrame(frameStart);
|
|
144
|
+
const frameMs = performance.now() - frameStartMs;
|
|
145
|
+
// Swap buffers
|
|
146
|
+
state.swapBuffers();
|
|
147
|
+
// Build stats
|
|
148
|
+
const stats = {
|
|
149
|
+
mode,
|
|
150
|
+
width: state.width,
|
|
151
|
+
height: state.height,
|
|
152
|
+
contentHeight: contentH,
|
|
153
|
+
bytes: Buffer.byteLength(output, "utf8"),
|
|
154
|
+
frameMs,
|
|
155
|
+
phases: {
|
|
156
|
+
clear: timings.clear,
|
|
157
|
+
layout: timings.layout,
|
|
158
|
+
render: timings.render,
|
|
159
|
+
diffAnsi: diffAnsiMs,
|
|
160
|
+
write: writeMs,
|
|
161
|
+
},
|
|
162
|
+
timestamp: performance.now(),
|
|
163
|
+
};
|
|
164
|
+
if (debugHook)
|
|
165
|
+
debugHook(stats);
|
|
166
|
+
if (events.hasFrameHandlers)
|
|
167
|
+
events.dispatchFrame(stats);
|
|
235
168
|
}
|
|
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);
|
|
169
|
+
catch (err) {
|
|
170
|
+
console.error("[effect-tui] Render error:", err);
|
|
171
|
+
state.markDirty();
|
|
264
172
|
}
|
|
265
173
|
};
|
|
174
|
+
// Build renderer object
|
|
266
175
|
const renderer = {
|
|
267
176
|
get width() {
|
|
268
|
-
return width;
|
|
177
|
+
return state.width;
|
|
269
178
|
},
|
|
270
179
|
get height() {
|
|
271
|
-
return height;
|
|
180
|
+
return state.height;
|
|
272
181
|
},
|
|
273
182
|
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);
|
|
183
|
+
state.markDirty();
|
|
291
184
|
},
|
|
185
|
+
onKey: (handler) => events.onKey(handler),
|
|
186
|
+
onMouse: (handler) => events.onMouse(handler),
|
|
187
|
+
onPaste: (handler) => events.onPaste(handler),
|
|
188
|
+
onResize: (handler) => events.onResize(handler),
|
|
189
|
+
onFrameStats: (handler) => events.onFrameStats(handler),
|
|
292
190
|
stop() {
|
|
293
|
-
running = false;
|
|
294
|
-
if (loop) {
|
|
295
|
-
clearInterval(loop);
|
|
296
|
-
loop = null;
|
|
191
|
+
state.running = false;
|
|
192
|
+
if (state.loop) {
|
|
193
|
+
clearInterval(state.loop);
|
|
194
|
+
state.loop = null;
|
|
195
|
+
}
|
|
196
|
+
if (state.inputHandler) {
|
|
197
|
+
stdin.removeListener("data", state.inputHandler);
|
|
198
|
+
state.inputHandler = null;
|
|
199
|
+
}
|
|
200
|
+
if (state.resizeHandler) {
|
|
201
|
+
stdout.removeListener("resize", state.resizeHandler);
|
|
202
|
+
state.resizeHandler = null;
|
|
297
203
|
}
|
|
298
|
-
teardown();
|
|
204
|
+
terminal.teardown();
|
|
299
205
|
},
|
|
300
206
|
flush() {
|
|
301
207
|
renderFrame();
|
|
302
208
|
},
|
|
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
|
-
}
|
|
209
|
+
getScreenshot() {
|
|
210
|
+
// Return the previous buffer as ANSI string (it has the last rendered frame)
|
|
211
|
+
if (state.prevBuffer) {
|
|
212
|
+
return bufferToString(state.prevBuffer, state.palette, state.width, state.height);
|
|
342
213
|
}
|
|
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", () => {
|
|
214
|
+
return "";
|
|
215
|
+
},
|
|
216
|
+
dispatchKey(key) {
|
|
217
|
+
events.dispatchKey(key);
|
|
218
|
+
if (!manualMode)
|
|
219
|
+
renderFrame();
|
|
220
|
+
},
|
|
221
|
+
dispatchPaste(text) {
|
|
222
|
+
events.dispatchPaste(text);
|
|
223
|
+
if (!manualMode)
|
|
224
|
+
renderFrame();
|
|
225
|
+
},
|
|
226
|
+
dispatchResize(width, height) {
|
|
227
|
+
state.updateDimensions(width, height);
|
|
228
|
+
state.invalidateBuffers();
|
|
229
|
+
state.markDirty();
|
|
230
|
+
events.dispatchResize(width, height);
|
|
231
|
+
if (!manualMode)
|
|
232
|
+
renderFrame();
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
// Terminal setup
|
|
236
|
+
terminal.setup();
|
|
237
|
+
// Input handling
|
|
238
|
+
state.inputHandler = (data) => inputProcessor.process(data);
|
|
239
|
+
stdin.on("data", state.inputHandler);
|
|
240
|
+
// Resize handling
|
|
241
|
+
state.resizeHandler = () => {
|
|
378
242
|
const newWidth = stdout.columns || 80;
|
|
379
243
|
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)
|
|
244
|
+
renderMode.handleResize(newWidth, newHeight, state.lastWidth);
|
|
245
|
+
state.updateDimensions(newWidth, newHeight);
|
|
246
|
+
state.invalidateBuffers();
|
|
247
|
+
state.markDirty();
|
|
248
|
+
events.dispatchResize(newWidth, newHeight);
|
|
249
|
+
};
|
|
250
|
+
stdout.on("resize", state.resizeHandler);
|
|
251
|
+
// Render loop
|
|
406
252
|
if (!manualMode) {
|
|
407
253
|
const frameMs = 1000 / fps;
|
|
408
|
-
loop = setInterval(() => {
|
|
409
|
-
if (!running) {
|
|
410
|
-
if (loop)
|
|
411
|
-
clearInterval(loop);
|
|
412
|
-
teardown();
|
|
254
|
+
state.loop = setInterval(() => {
|
|
255
|
+
if (!state.running) {
|
|
256
|
+
if (state.loop)
|
|
257
|
+
clearInterval(state.loop);
|
|
258
|
+
terminal.teardown();
|
|
413
259
|
return;
|
|
414
260
|
}
|
|
415
261
|
renderFrame();
|
|
416
262
|
}, frameMs);
|
|
417
263
|
}
|
|
418
|
-
// Store container reference for direct root access
|
|
419
264
|
;
|
|
420
265
|
renderer._container = null;
|
|
421
266
|
return renderer;
|
|
@@ -423,29 +268,19 @@ export function createRenderer(options) {
|
|
|
423
268
|
export function createRoot(renderer) {
|
|
424
269
|
const hostContext = {
|
|
425
270
|
requestRender: () => renderer.requestRender(),
|
|
271
|
+
requestImmediateRender: () => renderer.flush(),
|
|
426
272
|
};
|
|
427
273
|
const container = {
|
|
428
274
|
root: null,
|
|
429
275
|
ctx: hostContext,
|
|
430
276
|
};
|
|
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);
|
|
277
|
+
const fiberRoot = reconciler.createContainer(container, 0, null, false, null, "", (err) => console.error(err), (err) => console.error(err), (err) => console.error(err), () => { }, null);
|
|
441
278
|
renderer._container = container;
|
|
442
|
-
const reconcilerAny = reconciler;
|
|
443
|
-
const runSync = reconcilerAny.flushSync?.bind(reconcilerAny) ?? ((fn) => fn());
|
|
444
279
|
return {
|
|
445
280
|
render(element, sync = false) {
|
|
446
281
|
const wrapped = React.createElement(RendererContext.Provider, { value: renderer }, element);
|
|
447
282
|
if (sync) {
|
|
448
|
-
|
|
283
|
+
flushSync(() => {
|
|
449
284
|
reconciler.updateContainer(wrapped, fiberRoot, null, null);
|
|
450
285
|
});
|
|
451
286
|
renderer.requestRender();
|
|
@@ -463,14 +298,9 @@ export function createRoot(renderer) {
|
|
|
463
298
|
},
|
|
464
299
|
};
|
|
465
300
|
}
|
|
466
|
-
/**
|
|
467
|
-
* Render a React tree to the terminal in one call.
|
|
468
|
-
* Returns helpers similar to Ink: rerender, unmount, waitUntilExit.
|
|
469
|
-
*/
|
|
470
301
|
export function render(element, options) {
|
|
471
302
|
const renderer = createRenderer(options);
|
|
472
303
|
const root = createRoot(renderer);
|
|
473
|
-
// Initial render (sync to avoid flicker before the loop runs)
|
|
474
304
|
root.render(element, true);
|
|
475
305
|
let resolved = false;
|
|
476
306
|
let resolveExit = null;
|