@effect-tui/react 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/jsx-runtime.d.ts +6 -6
- package/dist/jsx-runtime.d.ts.map +1 -1
- package/dist/src/codeblock.js.map +1 -1
- package/dist/src/components/Divider.d.ts.map +1 -1
- package/dist/src/components/Divider.js +1 -1
- package/dist/src/components/Divider.js.map +1 -1
- package/dist/src/components/Markdown.d.ts.map +1 -1
- package/dist/src/components/Markdown.js +1 -1
- package/dist/src/components/Markdown.js.map +1 -1
- package/dist/src/components/MultilineTextInput.d.ts.map +1 -1
- package/dist/src/components/MultilineTextInput.js +2 -2
- package/dist/src/components/MultilineTextInput.js.map +1 -1
- package/dist/src/components/Static.d.ts.map +1 -1
- package/dist/src/components/Static.js +1 -1
- package/dist/src/components/Static.js.map +1 -1
- package/dist/src/components/TextInput.d.ts.map +1 -1
- package/dist/src/components/TextInput.js +3 -3
- package/dist/src/components/TextInput.js.map +1 -1
- package/dist/src/components/index.d.ts +4 -4
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +4 -4
- package/dist/src/components/index.js.map +1 -1
- package/dist/src/console/ConsoleCapture.d.ts.map +1 -1
- package/dist/src/console/ConsoleCapture.js +1 -1
- package/dist/src/console/ConsoleCapture.js.map +1 -1
- package/dist/src/console/ConsolePopover.d.ts.map +1 -1
- package/dist/src/console/ConsolePopover.js +11 -13
- package/dist/src/console/ConsolePopover.js.map +1 -1
- package/dist/src/console/index.d.ts +1 -1
- package/dist/src/console/index.d.ts.map +1 -1
- package/dist/src/console/index.js +1 -1
- package/dist/src/console/index.js.map +1 -1
- package/dist/src/console/useConsole.d.ts.map +1 -1
- package/dist/src/console/useConsole.js +2 -2
- package/dist/src/console/useConsole.js.map +1 -1
- package/dist/src/debug/DebugOverlay.d.ts +1 -1
- package/dist/src/debug/DebugOverlay.d.ts.map +1 -1
- package/dist/src/debug/DebugOverlay.js +1 -1
- package/dist/src/debug/DebugOverlay.js.map +1 -1
- package/dist/src/dev/Toast.d.ts.map +1 -1
- package/dist/src/dev/Toast.js +2 -2
- package/dist/src/dev/Toast.js.map +1 -1
- package/dist/src/dev/index.d.ts +1 -1
- package/dist/src/dev/index.d.ts.map +1 -1
- package/dist/src/dev/index.js +1 -1
- package/dist/src/dev/index.js.map +1 -1
- package/dist/src/dev.d.ts +1 -2
- package/dist/src/dev.d.ts.map +1 -1
- package/dist/src/dev.js +10 -10
- package/dist/src/dev.js.map +1 -1
- package/dist/src/exit.d.ts +7 -0
- package/dist/src/exit.d.ts.map +1 -0
- package/dist/src/exit.js +9 -0
- package/dist/src/exit.js.map +1 -0
- package/dist/src/highlight.d.ts +1 -1
- package/dist/src/highlight.d.ts.map +1 -1
- package/dist/src/highlight.js.map +1 -1
- package/dist/src/hooks/index.d.ts +3 -3
- package/dist/src/hooks/index.d.ts.map +1 -1
- package/dist/src/hooks/index.js.map +1 -1
- package/dist/src/hooks/use-keyboard.d.ts.map +1 -1
- package/dist/src/hooks/use-keyboard.js.map +1 -1
- package/dist/src/hooks/use-mouse.d.ts +1 -1
- package/dist/src/hooks/use-mouse.d.ts.map +1 -1
- package/dist/src/hooks/use-mouse.js.map +1 -1
- package/dist/src/hooks/use-quit.d.ts.map +1 -1
- package/dist/src/hooks/use-quit.js +2 -1
- package/dist/src/hooks/use-quit.js.map +1 -1
- package/dist/src/hooks/use-scroll.d.ts.map +1 -1
- package/dist/src/hooks/use-scroll.js +2 -2
- package/dist/src/hooks/use-scroll.js.map +1 -1
- package/dist/src/hooks/useFrameStats.d.ts.map +1 -1
- package/dist/src/hooks/useFrameStats.js.map +1 -1
- package/dist/src/hosts/base.d.ts +2 -2
- package/dist/src/hosts/base.d.ts.map +1 -1
- package/dist/src/hosts/box.d.ts +3 -3
- package/dist/src/hosts/box.d.ts.map +1 -1
- package/dist/src/hosts/box.js +1 -1
- package/dist/src/hosts/box.js.map +1 -1
- package/dist/src/hosts/canvas.d.ts +6 -3
- package/dist/src/hosts/canvas.d.ts.map +1 -1
- package/dist/src/hosts/canvas.js +9 -1
- package/dist/src/hosts/canvas.js.map +1 -1
- package/dist/src/hosts/codeblock.d.ts +2 -2
- package/dist/src/hosts/codeblock.d.ts.map +1 -1
- package/dist/src/hosts/codeblock.js +1 -1
- package/dist/src/hosts/codeblock.js.map +1 -1
- package/dist/src/hosts/flex-container.d.ts +3 -3
- package/dist/src/hosts/flex-container.d.ts.map +1 -1
- package/dist/src/hosts/flex-container.js +1 -1
- package/dist/src/hosts/flex-container.js.map +1 -1
- package/dist/src/hosts/hstack.d.ts +1 -1
- package/dist/src/hosts/index.d.ts +8 -8
- package/dist/src/hosts/index.d.ts.map +1 -1
- package/dist/src/hosts/index.js +13 -13
- package/dist/src/hosts/index.js.map +1 -1
- package/dist/src/hosts/overlay-item.d.ts +1 -1
- package/dist/src/hosts/overlay.d.ts +1 -1
- package/dist/src/hosts/overlay.d.ts.map +1 -1
- package/dist/src/hosts/overlay.js +1 -1
- package/dist/src/hosts/overlay.js.map +1 -1
- package/dist/src/hosts/scroll.d.ts +2 -2
- package/dist/src/hosts/scroll.d.ts.map +1 -1
- package/dist/src/hosts/scroll.js +1 -1
- package/dist/src/hosts/scroll.js.map +1 -1
- package/dist/src/hosts/single-child.d.ts +1 -1
- package/dist/src/hosts/single-child.d.ts.map +1 -1
- package/dist/src/hosts/spacer.d.ts +1 -1
- package/dist/src/hosts/spacer.d.ts.map +1 -1
- package/dist/src/hosts/text.d.ts +2 -2
- package/dist/src/hosts/text.d.ts.map +1 -1
- package/dist/src/hosts/text.js +1 -1
- package/dist/src/hosts/text.js.map +1 -1
- package/dist/src/hosts/vstack.d.ts +1 -1
- package/dist/src/hosts/zstack.d.ts +2 -2
- package/dist/src/hosts/zstack.d.ts.map +1 -1
- package/dist/src/hosts/zstack.js +1 -1
- package/dist/src/hosts/zstack.js.map +1 -1
- package/dist/src/index.d.ts +17 -21
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +11 -15
- package/dist/src/index.js.map +1 -1
- package/dist/src/inline/index.d.ts.map +1 -1
- package/dist/src/inline/index.js +1 -1
- package/dist/src/inline/index.js.map +1 -1
- package/dist/src/motion/color-motion-value.d.ts +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 -1
- package/dist/src/motion/color.d.ts.map +1 -1
- package/dist/src/motion/color.js +1 -1
- package/dist/src/motion/color.js.map +1 -1
- package/dist/src/motion/color.test.js +2 -2
- package/dist/src/motion/color.test.js.map +1 -1
- package/dist/src/motion/hooks.d.ts +3 -3
- package/dist/src/motion/hooks.d.ts.map +1 -1
- package/dist/src/motion/hooks.js +1 -1
- package/dist/src/motion/hooks.js.map +1 -1
- package/dist/src/motion/index.d.ts +2 -2
- package/dist/src/motion/index.d.ts.map +1 -1
- package/dist/src/motion/index.js +3 -3
- package/dist/src/motion/index.js.map +1 -1
- package/dist/src/motion/motion-value.d.ts +5 -5
- package/dist/src/motion/motion-value.d.ts.map +1 -1
- package/dist/src/motion/motion-value.js +4 -4
- package/dist/src/motion/motion-value.js.map +1 -1
- package/dist/src/motion/motion-value.test.js +1 -1
- package/dist/src/motion/motion-value.test.js.map +1 -1
- package/dist/src/reconciler/host-config.d.ts +1 -1
- package/dist/src/reconciler/host-config.d.ts.map +1 -1
- package/dist/src/reconciler/host-config.js +1 -1
- package/dist/src/reconciler/host-config.js.map +1 -1
- package/dist/src/reconciler/types.d.ts +1 -1
- package/dist/src/remote/Procedures.d.ts.map +1 -1
- package/dist/src/remote/Procedures.js.map +1 -1
- package/dist/src/remote/Router.d.ts +1 -1
- package/dist/src/remote/Router.d.ts.map +1 -1
- package/dist/src/remote/Router.js +1 -1
- package/dist/src/remote/Router.js.map +1 -1
- package/dist/src/remote/Server.d.ts +1 -1
- package/dist/src/remote/Server.d.ts.map +1 -1
- package/dist/src/remote/Server.js +3 -3
- package/dist/src/remote/Server.js.map +1 -1
- package/dist/src/remote/index.d.ts +2 -2
- package/dist/src/remote/index.d.ts.map +1 -1
- package/dist/src/remote/index.js +5 -5
- package/dist/src/remote/index.js.map +1 -1
- package/dist/src/renderer/core/FrameBuilder.d.ts.map +1 -1
- package/dist/src/renderer/core/FrameBuilder.js.map +1 -1
- package/dist/src/renderer/input/InputProcessor.js +1 -1
- package/dist/src/renderer/input/InputProcessor.js.map +1 -1
- package/dist/src/renderer/lifecycle/TerminalSetup.d.ts +1 -1
- package/dist/src/renderer/lifecycle/TerminalSetup.d.ts.map +1 -1
- package/dist/src/renderer/lifecycle/index.d.ts +1 -1
- package/dist/src/renderer/lifecycle/index.d.ts.map +1 -1
- package/dist/src/renderer/lifecycle/index.js +1 -1
- package/dist/src/renderer/lifecycle/index.js.map +1 -1
- package/dist/src/renderer/modes/FullscreenRenderer.d.ts +1 -1
- package/dist/src/renderer/modes/FullscreenRenderer.d.ts.map +1 -1
- package/dist/src/renderer/modes/InlineRenderer.d.ts +1 -1
- package/dist/src/renderer/modes/InlineRenderer.d.ts.map +1 -1
- package/dist/src/renderer/modes/InlineRenderer.js +1 -1
- package/dist/src/renderer/modes/InlineRenderer.js.map +1 -1
- package/dist/src/renderer/modes/StaticContentRenderer.d.ts.map +1 -1
- package/dist/src/renderer/modes/StaticContentRenderer.js.map +1 -1
- package/dist/src/renderer/modes/index.d.ts +1 -1
- package/dist/src/renderer/modes/index.d.ts.map +1 -1
- package/dist/src/renderer/modes/index.js.map +1 -1
- package/dist/src/renderer-context.js +1 -1
- package/dist/src/renderer-context.js.map +1 -1
- package/dist/src/renderer-types.d.ts +7 -1
- package/dist/src/renderer-types.d.ts.map +1 -1
- package/dist/src/renderer.d.ts +2 -2
- package/dist/src/renderer.d.ts.map +1 -1
- package/dist/src/renderer.js +41 -16
- package/dist/src/renderer.js.map +1 -1
- package/dist/src/test/index.d.ts +2 -2
- package/dist/src/test/index.d.ts.map +1 -1
- package/dist/src/test/index.js +1 -1
- package/dist/src/test/index.js.map +1 -1
- package/dist/src/test/render-tui.d.ts +2 -2
- package/dist/src/test/render-tui.d.ts.map +1 -1
- package/dist/src/test/render-tui.js +2 -2
- package/dist/src/test/render-tui.js.map +1 -1
- package/dist/src/utils/flex-layout.d.ts +15 -1
- package/dist/src/utils/flex-layout.d.ts.map +1 -1
- package/dist/src/utils/flex-layout.js +79 -24
- package/dist/src/utils/flex-layout.js.map +1 -1
- package/dist/src/utils/index.d.ts +4 -4
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +2 -2
- package/dist/src/utils/index.js.map +1 -1
- package/dist/src/utils/styles.d.ts.map +1 -1
- package/dist/src/utils/styles.js.map +1 -1
- package/dist/src/visualize/index.js +2 -2
- package/dist/src/visualize/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/jsx-runtime.ts +6 -6
- package/package.json +2 -2
- package/src/codeblock.tsx +1 -1
- package/src/components/Divider.tsx +1 -1
- package/src/components/Markdown.tsx +2 -2
- package/src/components/MultilineTextInput.tsx +9 -9
- package/src/components/Static.tsx +1 -1
- package/src/components/TextInput.tsx +9 -9
- package/src/components/index.ts +4 -4
- package/src/console/ConsoleCapture.ts +1 -1
- package/src/console/ConsolePopover.tsx +112 -119
- package/src/console/index.ts +1 -3
- package/src/console/useConsole.ts +2 -2
- package/src/debug/DebugOverlay.ts +3 -6
- package/src/dev/Toast.tsx +12 -10
- package/src/dev/index.ts +1 -1
- package/src/dev.tsx +11 -12
- package/src/exit.ts +8 -0
- package/src/highlight.ts +1 -1
- package/src/hooks/index.ts +3 -3
- package/src/hooks/use-keyboard.ts +1 -1
- package/src/hooks/use-mouse.ts +1 -1
- package/src/hooks/use-quit.ts +2 -1
- package/src/hooks/use-scroll.ts +9 -11
- package/src/hooks/useFrameStats.ts +1 -1
- package/src/hosts/base.ts +2 -2
- package/src/hosts/box.ts +4 -4
- package/src/hosts/canvas.ts +14 -3
- package/src/hosts/codeblock.ts +3 -3
- package/src/hosts/flex-container.ts +3 -3
- package/src/hosts/hstack.ts +1 -1
- package/src/hosts/index.ts +14 -14
- package/src/hosts/overlay-item.ts +1 -1
- package/src/hosts/overlay.ts +2 -2
- package/src/hosts/scroll.ts +3 -3
- package/src/hosts/single-child.ts +1 -1
- package/src/hosts/spacer.ts +1 -1
- package/src/hosts/text.ts +3 -3
- package/src/hosts/vstack.ts +1 -1
- package/src/hosts/zstack.ts +2 -2
- package/src/index.ts +60 -60
- package/src/inline/index.tsx +1 -1
- package/src/motion/color-motion-value.ts +1 -1
- package/src/motion/color.test.ts +2 -2
- package/src/motion/color.ts +2 -2
- package/src/motion/hooks.ts +3 -3
- package/src/motion/index.ts +8 -8
- package/src/motion/motion-value.test.ts +1 -1
- package/src/motion/motion-value.ts +11 -11
- package/src/reconciler/host-config.ts +3 -3
- package/src/reconciler/types.ts +1 -1
- package/src/remote/Procedures.ts +1 -7
- package/src/remote/Router.ts +3 -7
- package/src/remote/Server.ts +7 -12
- package/src/remote/index.ts +6 -10
- package/src/renderer/core/FrameBuilder.ts +1 -1
- package/src/renderer/input/InputProcessor.ts +1 -1
- package/src/renderer/lifecycle/TerminalSetup.ts +1 -1
- package/src/renderer/lifecycle/index.ts +1 -1
- package/src/renderer/modes/FullscreenRenderer.ts +1 -1
- package/src/renderer/modes/InlineRenderer.ts +2 -2
- package/src/renderer/modes/StaticContentRenderer.ts +1 -1
- package/src/renderer/modes/index.ts +1 -1
- package/src/renderer-context.ts +1 -1
- package/src/renderer-types.ts +7 -1
- package/src/renderer.ts +53 -28
- package/src/test/index.ts +4 -4
- package/src/test/render-tui.ts +3 -3
- package/src/utils/flex-layout.ts +83 -24
- package/src/utils/index.ts +8 -8
- package/src/utils/styles.ts +2 -2
- package/src/visualize/index.tsx +2 -2
package/src/remote/Router.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// RPC handlers for remote session control
|
|
2
2
|
import type { Rpc } from "@effect/rpc"
|
|
3
|
-
import { Effect, Layer, Context } from "effect"
|
|
4
3
|
import type { KeyMsg } from "@effect-tui/core"
|
|
4
|
+
import { Context, Effect, type Layer } from "effect"
|
|
5
5
|
import { TuiRpcs } from "./Procedures.js"
|
|
6
6
|
|
|
7
7
|
// Service interface for the TUI session
|
|
@@ -19,10 +19,7 @@ export interface TuiSessionImpl {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export class TuiSession extends Context.Tag("TuiSession")<
|
|
23
|
-
TuiSession,
|
|
24
|
-
TuiSessionImpl
|
|
25
|
-
>() {}
|
|
22
|
+
export class TuiSession extends Context.Tag("TuiSession")<TuiSession, TuiSessionImpl>() {}
|
|
26
23
|
|
|
27
24
|
// Create the RPC handlers layer
|
|
28
25
|
export const HandlersLive: Layer.Layer<
|
|
@@ -55,8 +52,7 @@ export const HandlersLive: Layer.Layer<
|
|
|
55
52
|
|
|
56
53
|
Paste: ({ text }) => Effect.sync(() => session.dispatchPaste(text)),
|
|
57
54
|
|
|
58
|
-
Resize: ({ width, height }) =>
|
|
59
|
-
Effect.sync(() => session.dispatchResize(width, height)),
|
|
55
|
+
Resize: ({ width, height }) => Effect.sync(() => session.dispatchResize(width, height)),
|
|
60
56
|
|
|
61
57
|
Info: () => Effect.sync(() => session.getInfo()),
|
|
62
58
|
}
|
package/src/remote/Server.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// Remote server that exposes TUI session via Unix socket
|
|
2
|
-
|
|
3
|
-
import { RpcSerialization, RpcServer } from "@effect/rpc"
|
|
4
|
-
import { BunSocketServer } from "@effect/platform-bun"
|
|
2
|
+
|
|
5
3
|
import * as fs from "node:fs"
|
|
6
4
|
import * as path from "node:path"
|
|
5
|
+
import { BunSocketServer } from "@effect/platform-bun"
|
|
6
|
+
import { RpcSerialization, RpcServer } from "@effect/rpc"
|
|
7
|
+
import { Effect, Layer } from "effect"
|
|
7
8
|
import { TuiRpcs } from "./Procedures.js"
|
|
8
9
|
import { HandlersLive, TuiSession, type TuiSessionImpl } from "./Router.js"
|
|
9
10
|
|
|
@@ -18,8 +19,7 @@ const ensureSocketDir = Effect.sync(() => {
|
|
|
18
19
|
})
|
|
19
20
|
|
|
20
21
|
// Get socket path for current process
|
|
21
|
-
export const getSocketPath = (pid?: number) =>
|
|
22
|
-
path.join(SOCKET_DIR, `${pid ?? process.pid}.sock`)
|
|
22
|
+
export const getSocketPath = (pid?: number) => path.join(SOCKET_DIR, `${pid ?? process.pid}.sock`)
|
|
23
23
|
|
|
24
24
|
// Clean up socket file
|
|
25
25
|
const cleanupSocket = (socketPath: string) =>
|
|
@@ -34,10 +34,7 @@ const cleanupSocket = (socketPath: string) =>
|
|
|
34
34
|
})
|
|
35
35
|
|
|
36
36
|
// Create the server layer
|
|
37
|
-
export const makeServerLayer = (
|
|
38
|
-
sessionImpl: TuiSessionImpl,
|
|
39
|
-
socketPath?: string,
|
|
40
|
-
) => {
|
|
37
|
+
export const makeServerLayer = (sessionImpl: TuiSessionImpl, socketPath?: string) => {
|
|
41
38
|
const actualPath = socketPath ?? getSocketPath()
|
|
42
39
|
|
|
43
40
|
// Setup layer - creates directory, cleans stale socket
|
|
@@ -52,9 +49,7 @@ export const makeServerLayer = (
|
|
|
52
49
|
)
|
|
53
50
|
|
|
54
51
|
// RPC handlers layer (needs TuiSession)
|
|
55
|
-
const HandlersLayer = HandlersLive.pipe(
|
|
56
|
-
Layer.provide(Layer.succeed(TuiSession, sessionImpl)),
|
|
57
|
-
)
|
|
52
|
+
const HandlersLayer = HandlersLive.pipe(Layer.provide(Layer.succeed(TuiSession, sessionImpl)))
|
|
58
53
|
|
|
59
54
|
// Full RPC server stack:
|
|
60
55
|
// 1. RpcServer.layer creates the RPC server, needs handlers
|
package/src/remote/index.ts
CHANGED
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
// 2. Connect using etui CLI or raw socket at /tmp/effect-tui-sessions/<pid>.sock
|
|
9
9
|
|
|
10
10
|
export { TuiRpcs } from "./Procedures.js"
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
11
|
+
export { HandlersLive, TuiSession } from "./Router.js"
|
|
12
|
+
export { getSocketPath, makeServerLayer } from "./Server.js"
|
|
13
13
|
|
|
14
|
-
import { Effect, Exit, Layer, Scope } from "effect"
|
|
15
14
|
import * as fs from "node:fs"
|
|
15
|
+
import { Effect, Exit, Layer, Scope } from "effect"
|
|
16
16
|
import type { TuiRenderer } from "../renderer-types.js"
|
|
17
17
|
import type { TuiSessionImpl } from "./Router.js"
|
|
18
|
-
import {
|
|
18
|
+
import { getSocketPath, makeServerLayer } from "./Server.js"
|
|
19
19
|
|
|
20
20
|
export interface EnableRemoteOptions {
|
|
21
21
|
/** Custom socket path (defaults to /tmp/effect-tui-sessions/<pid>.sock) */
|
|
@@ -55,13 +55,9 @@ function deriveSessionName(entryPath: string): string {
|
|
|
55
55
|
* @param options - Socket path and entry path for session identification
|
|
56
56
|
* @returns A cleanup function to stop the server
|
|
57
57
|
*/
|
|
58
|
-
export function enableRemote(
|
|
59
|
-
renderer: TuiRenderer,
|
|
60
|
-
options?: EnableRemoteOptions | string,
|
|
61
|
-
): () => void {
|
|
58
|
+
export function enableRemote(renderer: TuiRenderer, options?: EnableRemoteOptions | string): () => void {
|
|
62
59
|
// Support old API: enableRemote(renderer, socketPath?)
|
|
63
|
-
const opts: EnableRemoteOptions =
|
|
64
|
-
typeof options === "string" ? { socketPath: options } : options ?? {}
|
|
60
|
+
const opts: EnableRemoteOptions = typeof options === "string" ? { socketPath: options } : (options ?? {})
|
|
65
61
|
const actualPath = opts.socketPath ?? getSocketPath()
|
|
66
62
|
|
|
67
63
|
// Derive session name from entry path
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { performance } from "node:perf_hooks"
|
|
2
2
|
import type { CellBuffer, Palette } from "@effect-tui/core"
|
|
3
|
-
import type { HostInstance } from "../../reconciler/types.js"
|
|
4
3
|
import * as Prof from "../../profiler.js"
|
|
4
|
+
import type { HostInstance } from "../../reconciler/types.js"
|
|
5
5
|
|
|
6
6
|
export interface FrameTimings {
|
|
7
7
|
clear: number
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ANSI, Terminal } from "@effect-tui/core"
|
|
2
|
-
import type {
|
|
2
|
+
import type { TuiReadStream, TuiWriteStream } from "../../renderer-types.js"
|
|
3
3
|
|
|
4
4
|
export interface TerminalSetupConfig {
|
|
5
5
|
mode: "fullscreen" | "inline"
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { EventBus } from "./EventBus.js"
|
|
2
|
+
export { ResizeManager, type ResizeResult, type ResizeState } from "./ResizeManager.js"
|
|
2
3
|
export { TerminalSetup, type TerminalSetupConfig } from "./TerminalSetup.js"
|
|
3
|
-
export { ResizeManager, type ResizeState, type ResizeResult } from "./ResizeManager.js"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ANSI, emitRowWithReset, rowChanged } from "@effect-tui/core"
|
|
2
|
-
import type {
|
|
2
|
+
import type { RenderContext, RendererMode, RenderOutput } from "./RendererMode.js"
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Fullscreen rendering mode using alternate buffer.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ANSI, emitRowWithReset,
|
|
2
|
-
import type {
|
|
1
|
+
import { ANSI, emitRowWithReset, findChangeWindow, rowContentWidth } from "@effect-tui/core"
|
|
2
|
+
import type { RenderContext, RendererMode, RenderOutput } from "./RendererMode.js"
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Inline rendering mode that renders in-place without alternate buffer.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CellBuffer, emitRowWithReset,
|
|
1
|
+
import { CellBuffer, emitRowWithReset, type Palette, rowContentWidth } from "@effect-tui/core"
|
|
2
2
|
import type { HostInstance } from "../../reconciler/types.js"
|
|
3
3
|
import type { TuiWriteStream } from "../../renderer-types.js"
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { RendererMode, RenderContext, RenderOutput } from "./RendererMode.js"
|
|
2
1
|
export { FullscreenRenderer } from "./FullscreenRenderer.js"
|
|
3
2
|
export { InlineRenderer } from "./InlineRenderer.js"
|
|
3
|
+
export type { RenderContext, RendererMode, RenderOutput } from "./RendererMode.js"
|
|
4
4
|
export { StaticContentRenderer } from "./StaticContentRenderer.js"
|
package/src/renderer-context.ts
CHANGED
package/src/renderer-types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { KeyMsg, MouseMsg } from "@effect-tui/core"
|
|
2
|
-
import type {
|
|
2
|
+
import type { HostContext, HostInstance } from "./reconciler/types.js"
|
|
3
3
|
|
|
4
4
|
/** Minimal write stream interface for renderer output */
|
|
5
5
|
export interface TuiWriteStream {
|
|
@@ -75,6 +75,12 @@ export interface RendererOptions {
|
|
|
75
75
|
mode?: "fullscreen" | "inline"
|
|
76
76
|
/** Exit the process on Ctrl+C unless preventDefault was called. Defaults to true. */
|
|
77
77
|
exitOnCtrlC?: boolean
|
|
78
|
+
/** Handle SIGINT/SIGTERM and restore terminal. Defaults to true. */
|
|
79
|
+
handleSignals?: boolean
|
|
80
|
+
/** Exit the process after handling SIGINT/SIGTERM. Defaults to true. */
|
|
81
|
+
exitOnSignal?: boolean
|
|
82
|
+
/** Override exit codes for signals. Defaults: SIGINT=130, SIGTERM=143. */
|
|
83
|
+
signalExitCodes?: Partial<Record<"SIGINT" | "SIGTERM", number>>
|
|
78
84
|
/** Enable diffed rendering (per-line). Defaults to true in runtime, false in manualMode (tests). */
|
|
79
85
|
diff?: boolean
|
|
80
86
|
/** Skip automatic render loop. Call flush() manually to render frames. */
|
package/src/renderer.ts
CHANGED
|
@@ -1,30 +1,32 @@
|
|
|
1
|
-
import React, { type ReactNode } from "react"
|
|
2
1
|
import { performance } from "node:perf_hooks"
|
|
3
|
-
import { ANSI, type KeyMsg, type MouseMsg
|
|
4
|
-
import {
|
|
5
|
-
import type { HostContext } from "./reconciler/types.js"
|
|
6
|
-
import * as Prof from "./profiler.js"
|
|
2
|
+
import { ANSI, bufferToString, type KeyMsg, type MouseMsg } from "@effect-tui/core"
|
|
3
|
+
import React, { type ReactNode } from "react"
|
|
7
4
|
import { DEFAULT_FPS } from "./constants.js"
|
|
5
|
+
import { requestExit } from "./exit.js"
|
|
6
|
+
import * as Prof from "./profiler.js"
|
|
7
|
+
import { flushSync, reconciler } from "./reconciler/host-config.js"
|
|
8
|
+
import type { HostContext } from "./reconciler/types.js"
|
|
9
|
+
// Extracted modules
|
|
10
|
+
import { FrameBuilder, RendererState } from "./renderer/core/index.js"
|
|
11
|
+
import { InputProcessor } from "./renderer/input/index.js"
|
|
12
|
+
import { EventBus, TerminalSetup } from "./renderer/lifecycle/index.js"
|
|
13
|
+
import { FullscreenRenderer, InlineRenderer, StaticContentRenderer } from "./renderer/modes/index.js"
|
|
14
|
+
import { RendererContext } from "./renderer-context.js"
|
|
8
15
|
import type {
|
|
9
|
-
|
|
16
|
+
Container,
|
|
17
|
+
FrameStats,
|
|
18
|
+
RendererOptions,
|
|
10
19
|
TuiReadStream,
|
|
11
20
|
TuiRenderer,
|
|
12
21
|
TuiRendererInternal,
|
|
13
|
-
|
|
14
|
-
RendererOptions,
|
|
15
|
-
FrameStats,
|
|
22
|
+
TuiWriteStream,
|
|
16
23
|
} from "./renderer-types.js"
|
|
17
|
-
import { RendererContext } from "./renderer-context.js"
|
|
18
|
-
|
|
19
|
-
// Extracted modules
|
|
20
|
-
import { RendererState, FrameBuilder } from "./renderer/core/index.js"
|
|
21
|
-
import { InputProcessor } from "./renderer/input/index.js"
|
|
22
|
-
import { EventBus, TerminalSetup } from "./renderer/lifecycle/index.js"
|
|
23
|
-
import { FullscreenRenderer, InlineRenderer, StaticContentRenderer } from "./renderer/modes/index.js"
|
|
24
24
|
|
|
25
|
-
// Re-export types and context for backwards compatibility
|
|
26
|
-
export type { TuiWriteStream, TuiReadStream, TuiRenderer, RendererOptions, FrameStats } from "./renderer-types.js"
|
|
27
25
|
export { RendererContext, useRenderer, useTerminalSize } from "./renderer-context.js"
|
|
26
|
+
// Re-export types and context for backwards compatibility
|
|
27
|
+
export type { FrameStats, RendererOptions, TuiReadStream, TuiRenderer, TuiWriteStream } from "./renderer-types.js"
|
|
28
|
+
|
|
29
|
+
type HandledSignal = "SIGINT" | "SIGTERM"
|
|
28
30
|
|
|
29
31
|
export function createRenderer(options?: RendererOptions): TuiRenderer {
|
|
30
32
|
const fps = options?.fps ?? DEFAULT_FPS
|
|
@@ -32,6 +34,13 @@ export function createRenderer(options?: RendererOptions): TuiRenderer {
|
|
|
32
34
|
const stdin: TuiReadStream = options?.stdin ?? process.stdin
|
|
33
35
|
const mode = options?.mode ?? "fullscreen"
|
|
34
36
|
const exitOnCtrlC = options?.exitOnCtrlC ?? true
|
|
37
|
+
const handleSignals = options?.handleSignals ?? true
|
|
38
|
+
const exitOnSignal = options?.exitOnSignal ?? true
|
|
39
|
+
const signalExitCodes: Record<HandledSignal, number> = {
|
|
40
|
+
SIGINT: 130,
|
|
41
|
+
SIGTERM: 143,
|
|
42
|
+
...options?.signalExitCodes,
|
|
43
|
+
}
|
|
35
44
|
const manualMode = options?.manualMode ?? false
|
|
36
45
|
const enableDiff = options?.diff ?? !manualMode
|
|
37
46
|
const skipTerminalSetup = options?.skipTerminalSetup ?? false
|
|
@@ -74,7 +83,7 @@ export function createRenderer(options?: RendererOptions): TuiRenderer {
|
|
|
74
83
|
onQuit: () => {
|
|
75
84
|
// Clean up terminal state before exiting
|
|
76
85
|
renderer.stop()
|
|
77
|
-
|
|
86
|
+
requestExit(0)
|
|
78
87
|
},
|
|
79
88
|
})
|
|
80
89
|
|
|
@@ -167,7 +176,7 @@ export function createRenderer(options?: RendererOptions): TuiRenderer {
|
|
|
167
176
|
})
|
|
168
177
|
|
|
169
178
|
// Combine static + dynamic output for atomic write
|
|
170
|
-
|
|
179
|
+
const output = staticOutput + modeOutput + state.palette.sgr(0)
|
|
171
180
|
contentH = contentHeight
|
|
172
181
|
const diffAnsiMs = performance.now() - diffStartMs
|
|
173
182
|
Prof.endPhase("diff+ansi", t)
|
|
@@ -211,6 +220,9 @@ export function createRenderer(options?: RendererOptions): TuiRenderer {
|
|
|
211
220
|
}
|
|
212
221
|
}
|
|
213
222
|
|
|
223
|
+
let onExit: (() => void) | null = null
|
|
224
|
+
let onSignal: ((signal: NodeJS.Signals) => void) | null = null
|
|
225
|
+
|
|
214
226
|
// Build renderer object
|
|
215
227
|
const renderer: TuiRenderer = {
|
|
216
228
|
get width() {
|
|
@@ -229,6 +241,15 @@ export function createRenderer(options?: RendererOptions): TuiRenderer {
|
|
|
229
241
|
onFrameStats: (handler: (stats: FrameStats) => void) => events.onFrameStats(handler),
|
|
230
242
|
stop() {
|
|
231
243
|
state.running = false
|
|
244
|
+
if (onExit) {
|
|
245
|
+
process.off("exit", onExit)
|
|
246
|
+
onExit = null
|
|
247
|
+
}
|
|
248
|
+
if (onSignal) {
|
|
249
|
+
process.off("SIGINT", onSignal)
|
|
250
|
+
process.off("SIGTERM", onSignal)
|
|
251
|
+
onSignal = null
|
|
252
|
+
}
|
|
232
253
|
if (state.loop) {
|
|
233
254
|
clearInterval(state.loop)
|
|
234
255
|
state.loop = null
|
|
@@ -315,16 +336,20 @@ export function createRenderer(options?: RendererOptions): TuiRenderer {
|
|
|
315
336
|
}
|
|
316
337
|
|
|
317
338
|
// Handle normal process exit (synchronous - runs before exit completes)
|
|
318
|
-
|
|
339
|
+
onExit = () => cleanup()
|
|
319
340
|
process.on("exit", onExit)
|
|
320
341
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
342
|
+
if (handleSignals) {
|
|
343
|
+
// Handle SIGINT (Ctrl+C from shell, not from TUI input) and SIGTERM
|
|
344
|
+
onSignal = (signal: NodeJS.Signals) => {
|
|
345
|
+
cleanup()
|
|
346
|
+
if (!exitOnSignal) return
|
|
347
|
+
const code = signalExitCodes[signal as HandledSignal] ?? 0
|
|
348
|
+
requestExit(code)
|
|
349
|
+
}
|
|
350
|
+
process.on("SIGINT", onSignal)
|
|
351
|
+
process.on("SIGTERM", onSignal)
|
|
325
352
|
}
|
|
326
|
-
process.on("SIGINT", onSignal)
|
|
327
|
-
process.on("SIGTERM", onSignal)
|
|
328
353
|
|
|
329
354
|
;(renderer as TuiRendererInternal)._container = null
|
|
330
355
|
return renderer
|
|
@@ -436,7 +461,7 @@ export function render(element: ReactNode, options?: RendererOptions): RenderIns
|
|
|
436
461
|
// The createRenderer exit handler will also run, but it's idempotent
|
|
437
462
|
const quit = (code = 0) => {
|
|
438
463
|
renderer.stop()
|
|
439
|
-
|
|
464
|
+
requestExit(code)
|
|
440
465
|
}
|
|
441
466
|
|
|
442
467
|
return {
|
package/src/test/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { renderTUI, type RenderTUIOptions, type RenderTUIResult } from "./render-tui.js"
|
|
2
1
|
export {
|
|
3
|
-
MockStdout,
|
|
4
|
-
MockStdin,
|
|
5
2
|
encodeKey,
|
|
6
|
-
stripAnsi,
|
|
7
3
|
getVisibleLines,
|
|
4
|
+
MockStdin,
|
|
5
|
+
MockStdout,
|
|
6
|
+
stripAnsi,
|
|
8
7
|
} from "./mock-streams.js"
|
|
8
|
+
export { type RenderTUIOptions, type RenderTUIResult, renderTUI } from "./render-tui.js"
|
package/src/test/render-tui.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { ReactElement } from "react"
|
|
2
1
|
import type { KeyMsg } from "@effect-tui/core"
|
|
3
|
-
import {
|
|
2
|
+
import type { ReactElement } from "react"
|
|
4
3
|
import { flushPassiveEffects, flushSync } from "../reconciler/host-config.js"
|
|
5
|
-
import {
|
|
4
|
+
import { createRenderer, createRoot } from "../renderer.js"
|
|
5
|
+
import { getVisibleLines, MockStdin, MockStdout, stripAnsi } from "./mock-streams.js"
|
|
6
6
|
|
|
7
7
|
export interface RenderTUIOptions {
|
|
8
8
|
width?: number
|
package/src/utils/flex-layout.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Generic flex layout algorithm for VStack and HStack.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type
|
|
5
|
+
import { type Axis, crossDim, crossPos, crossSize, mainDim, mainPos, mainSize, makeRect } from "@effect-tui/core"
|
|
6
6
|
import type { BaseHost } from "../hosts/base.js"
|
|
7
|
-
import
|
|
7
|
+
import type { HostInstance, Rect, Size } from "../reconciler/types.js"
|
|
8
8
|
|
|
9
9
|
export type FlexAxis = Axis
|
|
10
10
|
export type FlexAlignment = "start" | "center" | "end"
|
|
@@ -17,6 +17,13 @@ export interface FlexMeasureResult {
|
|
|
17
17
|
/**
|
|
18
18
|
* Measure children along a flex axis.
|
|
19
19
|
* Returns cached sizes and total size.
|
|
20
|
+
*
|
|
21
|
+
* SwiftUI-style measure:
|
|
22
|
+
* 1. First measure all non-greedy children with full available space
|
|
23
|
+
* 2. Then measure greedy children with remaining space
|
|
24
|
+
*
|
|
25
|
+
* This ensures non-greedy elements always get their natural size,
|
|
26
|
+
* even when sibling greedy elements have large content.
|
|
20
27
|
*/
|
|
21
28
|
export function measureFlex(
|
|
22
29
|
axis: FlexAxis,
|
|
@@ -25,26 +32,58 @@ export function measureFlex(
|
|
|
25
32
|
maxMain: number,
|
|
26
33
|
maxCross: number,
|
|
27
34
|
): FlexMeasureResult {
|
|
28
|
-
const sizes: Size[] =
|
|
29
|
-
let totalMain = 0
|
|
35
|
+
const sizes: Size[] = new Array(children.length)
|
|
30
36
|
let maxChildCross = 0
|
|
37
|
+
const totalSpacing = Math.max(0, (children.length - 1) * spacing)
|
|
31
38
|
|
|
39
|
+
// Pass 1: Measure non-greedy children first with full available space
|
|
40
|
+
let nonGreedyTotal = 0
|
|
32
41
|
for (let i = 0; i < children.length; i++) {
|
|
33
42
|
const child = children[i]
|
|
34
|
-
const
|
|
43
|
+
const greedyWeight = getGreedyWeight(child)
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
45
|
+
if (greedyWeight === 0) {
|
|
46
|
+
// Non-greedy: measure with full available space
|
|
47
|
+
const childMaxW = axis === "vertical" ? maxCross : maxMain
|
|
48
|
+
const childMaxH = axis === "vertical" ? maxMain : maxCross
|
|
49
|
+
const size = child.measure(childMaxW, childMaxH)
|
|
50
|
+
sizes[i] = size
|
|
51
|
+
nonGreedyTotal += mainSize(axis, size)
|
|
52
|
+
maxChildCross = Math.max(maxChildCross, crossSize(axis, size))
|
|
53
|
+
}
|
|
54
|
+
}
|
|
39
55
|
|
|
40
|
-
|
|
41
|
-
|
|
56
|
+
// Pass 2: Measure greedy children with remaining space
|
|
57
|
+
const remainingForGreedy = Math.max(0, maxMain - nonGreedyTotal - totalSpacing)
|
|
58
|
+
let totalGreedyWeight = 0
|
|
59
|
+
for (let i = 0; i < children.length; i++) {
|
|
60
|
+
const greedyWeight = getGreedyWeight(children[i])
|
|
61
|
+
if (greedyWeight > 0) totalGreedyWeight += greedyWeight
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let greedyMeasuredTotal = 0
|
|
65
|
+
for (let i = 0; i < children.length; i++) {
|
|
66
|
+
const child = children[i]
|
|
67
|
+
const greedyWeight = getGreedyWeight(child)
|
|
42
68
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
69
|
+
if (greedyWeight > 0) {
|
|
70
|
+
// Greedy: measure with proportional share of remaining space
|
|
71
|
+
const greedyMain = totalGreedyWeight > 0
|
|
72
|
+
? (remainingForGreedy * greedyWeight) / totalGreedyWeight
|
|
73
|
+
: remainingForGreedy
|
|
74
|
+
const childMaxW = axis === "vertical" ? maxCross : greedyMain
|
|
75
|
+
const childMaxH = axis === "vertical" ? greedyMain : maxCross
|
|
76
|
+
const size = child.measure(childMaxW, childMaxH)
|
|
77
|
+
sizes[i] = size
|
|
78
|
+
greedyMeasuredTotal += mainSize(axis, size)
|
|
79
|
+
maxChildCross = Math.max(maxChildCross, crossSize(axis, size))
|
|
80
|
+
}
|
|
46
81
|
}
|
|
47
82
|
|
|
83
|
+
// Calculate total main dimension
|
|
84
|
+
// Use actual measured sizes, not the constraint
|
|
85
|
+
let totalMain = nonGreedyTotal + greedyMeasuredTotal + totalSpacing
|
|
86
|
+
|
|
48
87
|
// Build total size from main/cross dimensions
|
|
49
88
|
const totalW = axis === "vertical" ? maxChildCross : totalMain
|
|
50
89
|
const totalH = axis === "vertical" ? totalMain : maxChildCross
|
|
@@ -68,6 +107,13 @@ function getGreedyWeight(child: HostInstance): number {
|
|
|
68
107
|
|
|
69
108
|
/**
|
|
70
109
|
* Layout children along a flex axis using cached sizes.
|
|
110
|
+
*
|
|
111
|
+
* SwiftUI-style layout:
|
|
112
|
+
* 1. Non-greedy children get their natural (measured) size
|
|
113
|
+
* 2. Greedy children share the REMAINING space proportionally
|
|
114
|
+
*
|
|
115
|
+
* This ensures non-greedy elements (like footers) are always visible,
|
|
116
|
+
* even when greedy elements (like scroll views) have overflowing content.
|
|
71
117
|
*/
|
|
72
118
|
export function layoutFlex(
|
|
73
119
|
axis: FlexAxis,
|
|
@@ -78,23 +124,29 @@ export function layoutFlex(
|
|
|
78
124
|
alignment: FlexAlignment,
|
|
79
125
|
stretchCross: boolean,
|
|
80
126
|
): void {
|
|
81
|
-
// Calculate totals
|
|
82
|
-
let totalNaturalMain = 0
|
|
83
|
-
let totalGreedyWeight = 0
|
|
84
127
|
const totalSpacing = Math.max(0, (children.length - 1) * spacing)
|
|
128
|
+
const availableMain = mainDim(axis, rect)
|
|
129
|
+
|
|
130
|
+
// Pass 1: Calculate space needed by non-greedy children
|
|
131
|
+
let nonGreedyTotal = 0
|
|
132
|
+
let totalGreedyWeight = 0
|
|
85
133
|
|
|
86
134
|
for (let i = 0; i < children.length; i++) {
|
|
87
135
|
const child = children[i]
|
|
88
136
|
const size = cachedSizes[i] ?? child.measure(rect.w, rect.h)
|
|
89
|
-
|
|
90
|
-
|
|
137
|
+
const greedyWeight = getGreedyWeight(child)
|
|
138
|
+
|
|
139
|
+
if (greedyWeight === 0) {
|
|
140
|
+
// Non-greedy: use natural size
|
|
141
|
+
nonGreedyTotal += mainSize(axis, size)
|
|
142
|
+
}
|
|
143
|
+
totalGreedyWeight += greedyWeight
|
|
91
144
|
}
|
|
92
145
|
|
|
93
|
-
//
|
|
94
|
-
const
|
|
95
|
-
const extraSpace = Math.max(0, availableMain - totalNaturalMain - totalSpacing)
|
|
146
|
+
// Remaining space for greedy children (after non-greedy + spacing)
|
|
147
|
+
const remainingForGreedy = Math.max(0, availableMain - nonGreedyTotal - totalSpacing)
|
|
96
148
|
|
|
97
|
-
// Layout children
|
|
149
|
+
// Pass 2: Layout all children
|
|
98
150
|
let curMainPos = mainPos(axis, rect)
|
|
99
151
|
const crossStartPos = crossPos(axis, rect)
|
|
100
152
|
const crossDimVal = crossDim(axis, rect)
|
|
@@ -103,9 +155,16 @@ export function layoutFlex(
|
|
|
103
155
|
const child = children[i]
|
|
104
156
|
const size = cachedSizes[i] ?? { w: 0, h: 0 }
|
|
105
157
|
const greedyWeight = getGreedyWeight(child)
|
|
106
|
-
const greedyExtra = totalGreedyWeight > 0 ? (extraSpace * greedyWeight) / totalGreedyWeight : 0
|
|
107
158
|
|
|
108
|
-
|
|
159
|
+
let childMainDim: number
|
|
160
|
+
if (greedyWeight > 0 && totalGreedyWeight > 0) {
|
|
161
|
+
// Greedy: gets proportional share of remaining space
|
|
162
|
+
childMainDim = (remainingForGreedy * greedyWeight) / totalGreedyWeight
|
|
163
|
+
} else {
|
|
164
|
+
// Non-greedy: gets natural size
|
|
165
|
+
childMainDim = mainSize(axis, size)
|
|
166
|
+
}
|
|
167
|
+
|
|
109
168
|
const childCrossDim = crossSize(axis, size)
|
|
110
169
|
|
|
111
170
|
// Calculate cross position based on alignment
|
package/src/utils/index.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export { type HAlign, type VAlign
|
|
2
|
-
export { type
|
|
1
|
+
export { alignInRect, type HAlign, type VAlign } from "./alignment.js"
|
|
2
|
+
export { type BorderChars, type BorderKind, borderChars, type ClipRect, drawBorder } from "./border.js"
|
|
3
|
+
export { type FlexAlignment, type FlexAxis, type FlexMeasureResult, layoutFlex, measureFlex } from "./flex-layout.js"
|
|
3
4
|
export { type Padding, type PaddingInput, resolvePadding } from "./padding.js"
|
|
4
5
|
export {
|
|
5
|
-
type StyleOptions,
|
|
6
|
-
type StyleInput,
|
|
7
|
-
toColorValue,
|
|
8
|
-
styleSpecFromProps,
|
|
9
|
-
styleIdFromProps,
|
|
10
6
|
resolveBgStyle,
|
|
11
7
|
resolveInheritedBgStyle,
|
|
8
|
+
type StyleInput,
|
|
9
|
+
type StyleOptions,
|
|
10
|
+
styleIdFromProps,
|
|
11
|
+
styleSpecFromProps,
|
|
12
|
+
toColorValue,
|
|
12
13
|
} from "./styles.js"
|
|
13
|
-
export { type FlexAxis, type FlexAlignment, type FlexMeasureResult, measureFlex, layoutFlex } from "./flex-layout.js"
|
package/src/utils/styles.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Style utilities for building palette-compatible style objects.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { type Color, type ColorValue, type Palette, parseColor, type StyleSpec } from "@effect-tui/core"
|
|
6
6
|
|
|
7
7
|
export interface StyleOptions {
|
|
8
8
|
fg?: ColorValue
|
|
@@ -56,8 +56,8 @@ export function resolveBgStyle(palette: Palette, bg?: Color): { value?: ColorVal
|
|
|
56
56
|
return { value, styleId }
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
import type { HostInstance } from "../reconciler/types.js"
|
|
60
59
|
import { getInheritedBg } from "../hosts/base.js"
|
|
60
|
+
import type { HostInstance } from "../reconciler/types.js"
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Resolve background style, inheriting from parent if not explicitly set.
|
package/src/visualize/index.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Effect visualization wrapper using React
|
|
2
2
|
// Uses Effect Layer for proper terminal state management across multiple calls
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { ANSI, Colors } from "@effect-tui/core"
|
|
5
5
|
import { Cause, Context, Duration, Effect, Exit, Fiber, Layer, Option } from "effect"
|
|
6
|
-
import {
|
|
6
|
+
import { useEffect, useState } from "react"
|
|
7
7
|
import { createRenderer, createRoot } from "../renderer.js"
|
|
8
8
|
|
|
9
9
|
const SPINNER_FRAMES = ["⠋", "⠙", "⠸", "⠴", "⠦", "⠇"] as const
|