@effect-tui/react 0.1.0-alpha.1
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/LICENSE +21 -0
- package/README.md +138 -0
- package/dist/jsx-dev-runtime.d.ts +3 -0
- package/dist/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/jsx-dev-runtime.js +3 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.d.ts +47 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +6 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/src/codeblock.d.ts +9 -0
- package/dist/src/codeblock.d.ts.map +1 -0
- package/dist/src/codeblock.js +24 -0
- package/dist/src/codeblock.js.map +1 -0
- package/dist/src/constants.d.ts +3 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +3 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/debug/DiagnosticsPanel.d.ts +7 -0
- package/dist/src/debug/DiagnosticsPanel.d.ts.map +1 -0
- package/dist/src/debug/DiagnosticsPanel.js +13 -0
- package/dist/src/debug/DiagnosticsPanel.js.map +1 -0
- package/dist/src/highlight.d.ts +20 -0
- package/dist/src/highlight.d.ts.map +1 -0
- package/dist/src/highlight.js +51 -0
- package/dist/src/highlight.js.map +1 -0
- package/dist/src/hooks/index.d.ts +4 -0
- package/dist/src/hooks/index.d.ts.map +1 -0
- package/dist/src/hooks/index.js +3 -0
- package/dist/src/hooks/index.js.map +1 -0
- package/dist/src/hooks/use-keyboard.d.ts +18 -0
- package/dist/src/hooks/use-keyboard.d.ts.map +1 -0
- package/dist/src/hooks/use-keyboard.js +26 -0
- package/dist/src/hooks/use-keyboard.js.map +1 -0
- package/dist/src/hooks/use-paste.d.ts +5 -0
- package/dist/src/hooks/use-paste.d.ts.map +1 -0
- package/dist/src/hooks/use-paste.js +14 -0
- package/dist/src/hooks/use-paste.js.map +1 -0
- package/dist/src/hooks/useFrameStats.d.ts +7 -0
- package/dist/src/hooks/useFrameStats.d.ts.map +1 -0
- package/dist/src/hooks/useFrameStats.js +28 -0
- package/dist/src/hooks/useFrameStats.js.map +1 -0
- package/dist/src/hosts/base.d.ts +22 -0
- package/dist/src/hosts/base.d.ts.map +1 -0
- package/dist/src/hosts/base.js +53 -0
- package/dist/src/hosts/base.js.map +1 -0
- package/dist/src/hosts/box.d.ts +26 -0
- package/dist/src/hosts/box.d.ts.map +1 -0
- package/dist/src/hosts/box.js +84 -0
- package/dist/src/hosts/box.js.map +1 -0
- package/dist/src/hosts/canvas.d.ts +48 -0
- package/dist/src/hosts/canvas.d.ts.map +1 -0
- package/dist/src/hosts/canvas.js +109 -0
- package/dist/src/hosts/canvas.js.map +1 -0
- package/dist/src/hosts/codeblock.d.ts +32 -0
- package/dist/src/hosts/codeblock.d.ts.map +1 -0
- package/dist/src/hosts/codeblock.js +118 -0
- package/dist/src/hosts/codeblock.js.map +1 -0
- package/dist/src/hosts/hstack.d.ts +18 -0
- package/dist/src/hosts/hstack.d.ts.map +1 -0
- package/dist/src/hosts/hstack.js +45 -0
- package/dist/src/hosts/hstack.js.map +1 -0
- package/dist/src/hosts/index.d.ts +16 -0
- package/dist/src/hosts/index.d.ts.map +1 -0
- package/dist/src/hosts/index.js +40 -0
- package/dist/src/hosts/index.js.map +1 -0
- package/dist/src/hosts/spacer.d.ts +19 -0
- package/dist/src/hosts/spacer.d.ts.map +1 -0
- package/dist/src/hosts/spacer.js +28 -0
- package/dist/src/hosts/spacer.js.map +1 -0
- package/dist/src/hosts/text.d.ts +43 -0
- package/dist/src/hosts/text.d.ts.map +1 -0
- package/dist/src/hosts/text.js +148 -0
- package/dist/src/hosts/text.js.map +1 -0
- package/dist/src/hosts/vstack.d.ts +18 -0
- package/dist/src/hosts/vstack.d.ts.map +1 -0
- package/dist/src/hosts/vstack.js +45 -0
- package/dist/src/hosts/vstack.js.map +1 -0
- package/dist/src/hosts/zstack.d.ts +20 -0
- package/dist/src/hosts/zstack.d.ts.map +1 -0
- package/dist/src/hosts/zstack.js +65 -0
- package/dist/src/hosts/zstack.js.map +1 -0
- package/dist/src/index.d.ts +20 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +20 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/inline/index.d.ts +32 -0
- package/dist/src/inline/index.d.ts.map +1 -0
- package/dist/src/inline/index.js +111 -0
- package/dist/src/inline/index.js.map +1 -0
- package/dist/src/jsx.d.ts +2 -0
- package/dist/src/jsx.d.ts.map +1 -0
- package/dist/src/jsx.js +4 -0
- package/dist/src/jsx.js.map +1 -0
- package/dist/src/motion/color-motion-value.d.ts +32 -0
- package/dist/src/motion/color-motion-value.d.ts.map +1 -0
- package/dist/src/motion/color-motion-value.js +80 -0
- package/dist/src/motion/color-motion-value.js.map +1 -0
- package/dist/src/motion/color.d.ts +30 -0
- package/dist/src/motion/color.d.ts.map +1 -0
- package/dist/src/motion/color.js +172 -0
- package/dist/src/motion/color.js.map +1 -0
- package/dist/src/motion/color.test.d.ts +2 -0
- package/dist/src/motion/color.test.d.ts.map +1 -0
- package/dist/src/motion/color.test.js +97 -0
- package/dist/src/motion/color.test.js.map +1 -0
- package/dist/src/motion/event-emitter.d.ts +18 -0
- package/dist/src/motion/event-emitter.d.ts.map +1 -0
- package/dist/src/motion/event-emitter.js +30 -0
- package/dist/src/motion/event-emitter.js.map +1 -0
- package/dist/src/motion/frame.d.ts +9 -0
- package/dist/src/motion/frame.d.ts.map +1 -0
- package/dist/src/motion/frame.js +51 -0
- package/dist/src/motion/frame.js.map +1 -0
- package/dist/src/motion/hooks.d.ts +75 -0
- package/dist/src/motion/hooks.d.ts.map +1 -0
- package/dist/src/motion/hooks.js +190 -0
- package/dist/src/motion/hooks.js.map +1 -0
- package/dist/src/motion/index.d.ts +4 -0
- package/dist/src/motion/index.d.ts.map +1 -0
- package/dist/src/motion/index.js +7 -0
- package/dist/src/motion/index.js.map +1 -0
- package/dist/src/motion/motion-value.d.ts +40 -0
- package/dist/src/motion/motion-value.d.ts.map +1 -0
- package/dist/src/motion/motion-value.js +109 -0
- package/dist/src/motion/motion-value.js.map +1 -0
- package/dist/src/motion/motion-value.test.d.ts +2 -0
- package/dist/src/motion/motion-value.test.d.ts.map +1 -0
- package/dist/src/motion/motion-value.test.js +177 -0
- package/dist/src/motion/motion-value.test.js.map +1 -0
- package/dist/src/motion/spring-math.d.ts +28 -0
- package/dist/src/motion/spring-math.d.ts.map +1 -0
- package/dist/src/motion/spring-math.js +81 -0
- package/dist/src/motion/spring-math.js.map +1 -0
- package/dist/src/motion/types.d.ts +25 -0
- package/dist/src/motion/types.d.ts.map +1 -0
- package/dist/src/motion/types.js +13 -0
- package/dist/src/motion/types.js.map +1 -0
- package/dist/src/output.d.ts +47 -0
- package/dist/src/output.d.ts.map +1 -0
- package/dist/src/output.js +125 -0
- package/dist/src/output.js.map +1 -0
- package/dist/src/profiler.d.ts +6 -0
- package/dist/src/profiler.d.ts.map +1 -0
- package/dist/src/profiler.js +73 -0
- package/dist/src/profiler.js.map +1 -0
- package/dist/src/reconciler/host-config.d.ts +16 -0
- package/dist/src/reconciler/host-config.d.ts.map +1 -0
- package/dist/src/reconciler/host-config.js +174 -0
- package/dist/src/reconciler/host-config.js.map +1 -0
- package/dist/src/reconciler/types.d.ts +52 -0
- package/dist/src/reconciler/types.d.ts.map +1 -0
- package/dist/src/reconciler/types.js +2 -0
- package/dist/src/reconciler/types.js.map +1 -0
- package/dist/src/renderer.d.ts +101 -0
- package/dist/src/renderer.d.ts.map +1 -0
- package/dist/src/renderer.js +509 -0
- package/dist/src/renderer.js.map +1 -0
- package/dist/src/terminal.d.ts +37 -0
- package/dist/src/terminal.d.ts.map +1 -0
- package/dist/src/terminal.js +65 -0
- package/dist/src/terminal.js.map +1 -0
- package/dist/src/test/index.d.ts +3 -0
- package/dist/src/test/index.d.ts.map +1 -0
- package/dist/src/test/index.js +3 -0
- package/dist/src/test/index.js.map +1 -0
- package/dist/src/test/mock-streams.d.ts +44 -0
- package/dist/src/test/mock-streams.d.ts.map +1 -0
- package/dist/src/test/mock-streams.js +136 -0
- package/dist/src/test/mock-streams.js.map +1 -0
- package/dist/src/test/render-tui.d.ts +47 -0
- package/dist/src/test/render-tui.d.ts.map +1 -0
- package/dist/src/test/render-tui.js +76 -0
- package/dist/src/test/render-tui.js.map +1 -0
- package/dist/src/trace/SpanTree.d.ts +10 -0
- package/dist/src/trace/SpanTree.d.ts.map +1 -0
- package/dist/src/trace/SpanTree.js +104 -0
- package/dist/src/trace/SpanTree.js.map +1 -0
- package/dist/src/trace/index.d.ts +30 -0
- package/dist/src/trace/index.d.ts.map +1 -0
- package/dist/src/trace/index.js +142 -0
- package/dist/src/trace/index.js.map +1 -0
- package/dist/src/trace/location.d.ts +9 -0
- package/dist/src/trace/location.d.ts.map +1 -0
- package/dist/src/trace/location.js +88 -0
- package/dist/src/trace/location.js.map +1 -0
- package/dist/src/trace/span-processor.d.ts +16 -0
- package/dist/src/trace/span-processor.d.ts.map +1 -0
- package/dist/src/trace/span-processor.js +54 -0
- package/dist/src/trace/span-processor.js.map +1 -0
- package/dist/src/trace/span-state.d.ts +79 -0
- package/dist/src/trace/span-state.d.ts.map +1 -0
- package/dist/src/trace/span-state.js +229 -0
- package/dist/src/trace/span-state.js.map +1 -0
- package/dist/src/trace/tui-logger.d.ts +8 -0
- package/dist/src/trace/tui-logger.d.ts.map +1 -0
- package/dist/src/trace/tui-logger.js +70 -0
- package/dist/src/trace/tui-logger.js.map +1 -0
- package/dist/src/utils/border.d.ts +31 -0
- package/dist/src/utils/border.d.ts.map +1 -0
- package/dist/src/utils/border.js +81 -0
- package/dist/src/utils/border.js.map +1 -0
- package/dist/src/utils/flex-layout.d.ts +20 -0
- package/dist/src/utils/flex-layout.d.ts.map +1 -0
- package/dist/src/utils/flex-layout.js +85 -0
- package/dist/src/utils/flex-layout.js.map +1 -0
- package/dist/src/utils/index.d.ts +5 -0
- package/dist/src/utils/index.d.ts.map +1 -0
- package/dist/src/utils/index.js +5 -0
- package/dist/src/utils/index.js.map +1 -0
- package/dist/src/utils/padding.d.ts +26 -0
- package/dist/src/utils/padding.d.ts.map +1 -0
- package/dist/src/utils/padding.js +34 -0
- package/dist/src/utils/padding.js.map +1 -0
- package/dist/src/utils/styles.d.ts +13 -0
- package/dist/src/utils/styles.d.ts.map +1 -0
- package/dist/src/utils/styles.js +5 -0
- package/dist/src/utils/styles.js.map +1 -0
- package/dist/src/visualize/index.d.ts +50 -0
- package/dist/src/visualize/index.d.ts.map +1 -0
- package/dist/src/visualize/index.js +194 -0
- package/dist/src/visualize/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +94 -0
- package/src/codeblock.tsx +47 -0
- package/src/constants.ts +2 -0
- package/src/debug/DiagnosticsPanel.tsx +38 -0
- package/src/highlight.ts +76 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/use-keyboard.ts +37 -0
- package/src/hooks/use-paste.ts +14 -0
- package/src/hooks/useFrameStats.ts +32 -0
- package/src/hosts/base.ts +65 -0
- package/src/hosts/box.ts +105 -0
- package/src/hosts/canvas.ts +155 -0
- package/src/hosts/codeblock.ts +145 -0
- package/src/hosts/hstack.ts +64 -0
- package/src/hosts/index.ts +45 -0
- package/src/hosts/spacer.ts +40 -0
- package/src/hosts/text.ts +175 -0
- package/src/hosts/vstack.ts +64 -0
- package/src/hosts/zstack.ts +77 -0
- package/src/index.ts +62 -0
- package/src/inline/index.tsx +181 -0
- package/src/jsx.ts +3 -0
- package/src/motion/color-motion-value.ts +90 -0
- package/src/motion/color.test.ts +115 -0
- package/src/motion/color.ts +191 -0
- package/src/motion/event-emitter.ts +35 -0
- package/src/motion/frame.ts +59 -0
- package/src/motion/hooks.ts +237 -0
- package/src/motion/index.ts +17 -0
- package/src/motion/motion-value.test.ts +222 -0
- package/src/motion/motion-value.ts +140 -0
- package/src/motion/spring-math.ts +114 -0
- package/src/motion/types.ts +34 -0
- package/src/output.ts +156 -0
- package/src/profiler.ts +88 -0
- package/src/reconciler/host-config.ts +277 -0
- package/src/reconciler/types.ts +66 -0
- package/src/renderer.ts +661 -0
- package/src/terminal.ts +67 -0
- package/src/test/index.ts +8 -0
- package/src/test/mock-streams.ts +149 -0
- package/src/test/render-tui.ts +118 -0
- package/src/trace/SpanTree.tsx +195 -0
- package/src/trace/index.tsx +205 -0
- package/src/trace/location.ts +90 -0
- package/src/trace/span-processor.ts +65 -0
- package/src/trace/span-state.ts +286 -0
- package/src/trace/tui-logger.ts +72 -0
- package/src/utils/border.ts +108 -0
- package/src/utils/flex-layout.ts +125 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/padding.ts +45 -0
- package/src/utils/styles.ts +14 -0
- package/src/visualize/index.tsx +305 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Colors,
|
|
3
|
+
displayWidth,
|
|
4
|
+
parseColor,
|
|
5
|
+
type CellBuffer,
|
|
6
|
+
type ColorLike,
|
|
7
|
+
type Palette,
|
|
8
|
+
type ColorValue,
|
|
9
|
+
} from "@effect-tui/core"
|
|
10
|
+
import type { HighlightLine } from "../highlight.js"
|
|
11
|
+
import type { HostContext, Rect, Size, CommonProps } from "../reconciler/types.js"
|
|
12
|
+
import { BaseHost } from "./base.js"
|
|
13
|
+
import { type Padding, type PaddingInput, resolvePadding } from "../utils/index.js"
|
|
14
|
+
|
|
15
|
+
export interface CodeBlockProps extends CommonProps {
|
|
16
|
+
lines: HighlightLine[]
|
|
17
|
+
lineNumbers?: boolean
|
|
18
|
+
padding?: PaddingInput
|
|
19
|
+
background?: ColorLike
|
|
20
|
+
lineNumberColor?: ColorLike
|
|
21
|
+
lineNumberBackground?: ColorLike
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function normalizeColor(c: unknown): ColorValue | undefined {
|
|
25
|
+
if (c === undefined || c === null) return undefined
|
|
26
|
+
if (typeof c === "number" || typeof c === "object") return c as ColorValue
|
|
27
|
+
return parseColor(c as string)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function lineDisplayWidth(line: HighlightLine): number {
|
|
31
|
+
return line.reduce((w, token) => w + displayWidth(token.text), 0)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class CodeBlockHost extends BaseHost {
|
|
35
|
+
lines: HighlightLine[] = [[]]
|
|
36
|
+
lineNumbers = false
|
|
37
|
+
padding: Padding = { top: 0, right: 0, bottom: 0, left: 0 }
|
|
38
|
+
background?: ColorLike
|
|
39
|
+
lineNumberColor?: ColorLike
|
|
40
|
+
lineNumberBackground?: ColorLike
|
|
41
|
+
|
|
42
|
+
private cachedLineWidths: number[] = []
|
|
43
|
+
private gutterWidth = 0
|
|
44
|
+
|
|
45
|
+
constructor(props: CodeBlockProps, ctx: HostContext) {
|
|
46
|
+
super("codeblock", props, ctx)
|
|
47
|
+
this.updateProps(props)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private computeGutterWidth(): number {
|
|
51
|
+
if (!this.lineNumbers) return 0
|
|
52
|
+
// Fix width so layout doesn't shift when moving from 1→2 digits.
|
|
53
|
+
const digits = Math.max(2, String(Math.max(1, this.lines.length)).length)
|
|
54
|
+
// digits plus a trailing space
|
|
55
|
+
return digits + 1
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private get insetX(): number {
|
|
59
|
+
return this.padding.left + this.padding.right + this.gutterWidth
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private get insetY(): number {
|
|
63
|
+
return this.padding.top + this.padding.bottom
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
measure(maxW: number, maxH: number): Size {
|
|
67
|
+
this.cachedLineWidths = this.lines.map((l) => lineDisplayWidth(l))
|
|
68
|
+
this.gutterWidth = this.computeGutterWidth()
|
|
69
|
+
|
|
70
|
+
const maxLineW = this.cachedLineWidths.reduce((max, w) => (w > max ? w : max), 0)
|
|
71
|
+
const contentW = maxLineW + this.insetX
|
|
72
|
+
|
|
73
|
+
const innerHeight = Math.max(1, this.lines.length) + this.insetY
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
w: Math.min(maxW, contentW),
|
|
77
|
+
h: Math.min(maxH, innerHeight),
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
override layout(rect: Rect): void {
|
|
82
|
+
super.layout(rect)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
render(buffer: CellBuffer, palette: Palette): void {
|
|
86
|
+
if (!this.rect) return
|
|
87
|
+
|
|
88
|
+
const { x, y, w, h } = this.rect
|
|
89
|
+
const contentWidth = Math.max(0, w - this.insetX)
|
|
90
|
+
const maxLines = Math.max(0, Math.min(this.lines.length, h - this.insetY))
|
|
91
|
+
const startX = x + this.padding.left + this.gutterWidth
|
|
92
|
+
const startY = y + this.padding.top
|
|
93
|
+
|
|
94
|
+
if (this.background !== undefined && w > 0 && h > 0) {
|
|
95
|
+
const bgStyle = palette.id({ bg: normalizeColor(this.background) })
|
|
96
|
+
buffer.fillRect(x, y, w, h, " ".codePointAt(0)!, bgStyle)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
for (let i = 0; i < maxLines; i++) {
|
|
100
|
+
const lineY = startY + i
|
|
101
|
+
let drawX = startX
|
|
102
|
+
|
|
103
|
+
if (this.lineNumbers) {
|
|
104
|
+
const gutterStyle = palette.id({
|
|
105
|
+
fg: normalizeColor(this.lineNumberColor) ?? Colors.gray(11),
|
|
106
|
+
bg: normalizeColor(this.lineNumberBackground ?? this.background),
|
|
107
|
+
})
|
|
108
|
+
const digits = String(i + 1).padStart(this.gutterWidth - 1, " ")
|
|
109
|
+
buffer.drawText(x + this.padding.left, lineY, `${digits} `, gutterStyle, this.gutterWidth)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const line = this.lines[i] ?? []
|
|
113
|
+
for (const token of line) {
|
|
114
|
+
if (contentWidth <= 0) break
|
|
115
|
+
const remaining = x + w - drawX
|
|
116
|
+
if (remaining <= 0) break
|
|
117
|
+
|
|
118
|
+
const style = token.style ?? {}
|
|
119
|
+
const fg = normalizeColor(style.fg)
|
|
120
|
+
const bg = normalizeColor(style.bg ?? this.background)
|
|
121
|
+
const styleId = palette.id({
|
|
122
|
+
fg,
|
|
123
|
+
bg,
|
|
124
|
+
bold: style.bold,
|
|
125
|
+
italic: style.italic,
|
|
126
|
+
underline: style.underline,
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
buffer.drawText(drawX, lineY, token.text, styleId, remaining)
|
|
130
|
+
drawX += displayWidth(token.text)
|
|
131
|
+
if (drawX >= x + w) break
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
override updateProps(props: Record<string, unknown>): void {
|
|
137
|
+
super.updateProps(props)
|
|
138
|
+
if (props.lines !== undefined) this.lines = props.lines as HighlightLine[]
|
|
139
|
+
if (props.lineNumbers !== undefined) this.lineNumbers = !!props.lineNumbers
|
|
140
|
+
if (props.padding !== undefined) this.padding = resolvePadding(props.padding as CodeBlockProps["padding"])
|
|
141
|
+
if (props.background !== undefined) this.background = props.background as ColorLike
|
|
142
|
+
if (props.lineNumberColor !== undefined) this.lineNumberColor = props.lineNumberColor as ColorLike
|
|
143
|
+
if (props.lineNumberBackground !== undefined) this.lineNumberBackground = props.lineNumberBackground as ColorLike
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { CellBuffer, Palette } from "@effect-tui/core"
|
|
2
|
+
import type { HostContext, Rect, Size, CommonProps } from "../reconciler/types.js"
|
|
3
|
+
import { BaseHost } from "./base.js"
|
|
4
|
+
import { measureFlex, layoutFlex, type FlexAlignment } from "../utils/index.js"
|
|
5
|
+
|
|
6
|
+
export interface HStackProps extends CommonProps {
|
|
7
|
+
spacing?: number
|
|
8
|
+
alignment?: "top" | "center" | "bottom"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Map HStack alignment names to generic flex alignment
|
|
12
|
+
function toFlexAlignment(alignment: "top" | "center" | "bottom"): FlexAlignment {
|
|
13
|
+
switch (alignment) {
|
|
14
|
+
case "top":
|
|
15
|
+
return "start"
|
|
16
|
+
case "center":
|
|
17
|
+
return "center"
|
|
18
|
+
case "bottom":
|
|
19
|
+
return "end"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class HStackHost extends BaseHost {
|
|
24
|
+
spacing = 0
|
|
25
|
+
alignment: "top" | "center" | "bottom" = "top"
|
|
26
|
+
private cachedSizes: Size[] = []
|
|
27
|
+
|
|
28
|
+
constructor(props: HStackProps, ctx: HostContext) {
|
|
29
|
+
super("hstack", props, ctx)
|
|
30
|
+
this.updateProps(props)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
measure(maxW: number, maxH: number): Size {
|
|
34
|
+
const result = measureFlex("horizontal", this.children, this.spacing, maxW, maxH)
|
|
35
|
+
this.cachedSizes = result.sizes
|
|
36
|
+
return result.totalSize
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override layout(rect: Rect): void {
|
|
40
|
+
super.layout(rect)
|
|
41
|
+
const stretchCross = this.alignment === "top"
|
|
42
|
+
layoutFlex(
|
|
43
|
+
"horizontal",
|
|
44
|
+
this.children,
|
|
45
|
+
this.cachedSizes,
|
|
46
|
+
rect,
|
|
47
|
+
this.spacing,
|
|
48
|
+
toFlexAlignment(this.alignment),
|
|
49
|
+
stretchCross,
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
render(buffer: CellBuffer, palette: Palette): void {
|
|
54
|
+
for (const child of this.children) {
|
|
55
|
+
child.render(buffer, palette)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
override updateProps(props: Record<string, unknown>): void {
|
|
60
|
+
super.updateProps(props)
|
|
61
|
+
if (props.spacing !== undefined) this.spacing = props.spacing as number
|
|
62
|
+
if (props.alignment !== undefined) this.alignment = props.alignment as "top" | "center" | "bottom"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { HostContext, CommonProps } from "../reconciler/types.js"
|
|
2
|
+
import type { BaseHost } from "./base.js"
|
|
3
|
+
import { TextHost, RawTextHost } from "./text.js"
|
|
4
|
+
import { SpacerHost } from "./spacer.js"
|
|
5
|
+
import { VStackHost } from "./vstack.js"
|
|
6
|
+
import { HStackHost } from "./hstack.js"
|
|
7
|
+
import { ZStackHost } from "./zstack.js"
|
|
8
|
+
import { BoxHost } from "./box.js"
|
|
9
|
+
import { CanvasHost } from "./canvas.js"
|
|
10
|
+
import { CodeBlockHost } from "./codeblock.js"
|
|
11
|
+
|
|
12
|
+
export { BaseHost } from "./base.js"
|
|
13
|
+
export { TextHost, RawTextHost, type TextProps } from "./text.js"
|
|
14
|
+
export { SpacerHost, type SpacerProps } from "./spacer.js"
|
|
15
|
+
export { VStackHost, type VStackProps } from "./vstack.js"
|
|
16
|
+
export { HStackHost, type HStackProps } from "./hstack.js"
|
|
17
|
+
export { ZStackHost, type ZStackProps } from "./zstack.js"
|
|
18
|
+
export { BoxHost, type BoxProps } from "./box.js"
|
|
19
|
+
export { CanvasHost, type CanvasProps, type DrawContext } from "./canvas.js"
|
|
20
|
+
export { CodeBlockHost, type CodeBlockProps } from "./codeblock.js"
|
|
21
|
+
|
|
22
|
+
// Use any to allow specialized props on each host type
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
|
+
export const hostRegistry: Record<string, new (props: any, ctx: HostContext) => BaseHost> = {
|
|
25
|
+
text: TextHost,
|
|
26
|
+
spacer: SpacerHost,
|
|
27
|
+
vstack: VStackHost,
|
|
28
|
+
hstack: HStackHost,
|
|
29
|
+
zstack: ZStackHost,
|
|
30
|
+
box: BoxHost,
|
|
31
|
+
canvas: CanvasHost,
|
|
32
|
+
codeblock: CodeBlockHost,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function createHostInstance(type: string, props: CommonProps, ctx: HostContext): BaseHost {
|
|
36
|
+
const Host = hostRegistry[type]
|
|
37
|
+
if (!Host) {
|
|
38
|
+
throw new Error(`Unknown host component type: ${type}`)
|
|
39
|
+
}
|
|
40
|
+
return new Host(props, ctx)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function createTextInstance(text: string, ctx: HostContext): RawTextHost {
|
|
44
|
+
return new RawTextHost(text, ctx)
|
|
45
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { CellBuffer, Palette } from "@effect-tui/core"
|
|
2
|
+
import type { HostContext, Rect, Size, CommonProps } from "../reconciler/types.js"
|
|
3
|
+
import { BaseHost } from "./base.js"
|
|
4
|
+
|
|
5
|
+
export interface SpacerProps extends CommonProps {
|
|
6
|
+
/** Minimum width (default 0) */
|
|
7
|
+
minWidth?: number
|
|
8
|
+
/** Minimum height (default 0) */
|
|
9
|
+
minHeight?: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class SpacerHost extends BaseHost {
|
|
13
|
+
minWidth = 0
|
|
14
|
+
minHeight = 0
|
|
15
|
+
|
|
16
|
+
constructor(props: SpacerProps, ctx: HostContext) {
|
|
17
|
+
// Spacers have flexGrow=1 by default
|
|
18
|
+
super("spacer", { flexGrow: 1, ...props }, ctx)
|
|
19
|
+
this.updateProps(props)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
measure(_maxW: number, _maxH: number): Size {
|
|
23
|
+
// Spacers have no natural size, they expand via flexGrow
|
|
24
|
+
return { w: this.minWidth, h: this.minHeight }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
override layout(rect: Rect): void {
|
|
28
|
+
super.layout(rect)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
render(_buffer: CellBuffer, _palette: Palette): void {
|
|
32
|
+
// Spacers render nothing
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
override updateProps(props: Record<string, unknown>): void {
|
|
36
|
+
super.updateProps(props)
|
|
37
|
+
if (props.minWidth !== undefined) this.minWidth = props.minWidth as number
|
|
38
|
+
if (props.minHeight !== undefined) this.minHeight = props.minHeight as number
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { displayWidth, parseColor, type CellBuffer, type Palette, type ColorLike } from "@effect-tui/core"
|
|
2
|
+
import type { HostContext, Rect, Size, CommonProps } from "../reconciler/types.js"
|
|
3
|
+
import { BaseHost } from "./base.js"
|
|
4
|
+
|
|
5
|
+
export interface TextProps extends CommonProps {
|
|
6
|
+
fg?: ColorLike
|
|
7
|
+
bg?: ColorLike
|
|
8
|
+
bold?: boolean
|
|
9
|
+
italic?: boolean
|
|
10
|
+
underline?: boolean
|
|
11
|
+
inverse?: boolean
|
|
12
|
+
/** If true, wrap text to multiple lines (default: false, text is truncated) */
|
|
13
|
+
wrap?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class TextHost extends BaseHost {
|
|
17
|
+
fg?: ColorLike
|
|
18
|
+
bg?: ColorLike
|
|
19
|
+
bold = false
|
|
20
|
+
italic = false
|
|
21
|
+
underline = false
|
|
22
|
+
inverse = false
|
|
23
|
+
wrap = false // Default: truncate (no wrap)
|
|
24
|
+
|
|
25
|
+
// Cache wrapped lines between measure() and render()
|
|
26
|
+
private cachedLines: string[] | null = null
|
|
27
|
+
private cachedWidth = 0
|
|
28
|
+
|
|
29
|
+
constructor(props: TextProps, ctx: HostContext) {
|
|
30
|
+
super("text", props, ctx)
|
|
31
|
+
this.updateProps(props)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Get text content from RawTextHost children */
|
|
35
|
+
private getContent(): string {
|
|
36
|
+
return this.children
|
|
37
|
+
.filter((c): c is RawTextHost => c instanceof RawTextHost)
|
|
38
|
+
.map((c) => c.content)
|
|
39
|
+
.join("")
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
measure(maxW: number, maxH: number): Size {
|
|
43
|
+
const content = this.getContent()
|
|
44
|
+
const rawLines = content.split("\n")
|
|
45
|
+
|
|
46
|
+
if (this.wrap) {
|
|
47
|
+
// Wrap mode: may span multiple lines. Cache result for render()
|
|
48
|
+
this.cachedLines = rawLines.flatMap((line, idx) =>
|
|
49
|
+
idx < rawLines.length - 1 ? [...this.wrapText(line, maxW), ""] : this.wrapText(line, maxW),
|
|
50
|
+
)
|
|
51
|
+
this.cachedWidth = maxW
|
|
52
|
+
const w = this.cachedLines.reduce((max, line) => Math.max(max, displayWidth(line)), 0)
|
|
53
|
+
return { w, h: Math.min(this.cachedLines.length, maxH) }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Default: respect explicit newlines but do not wrap long words
|
|
57
|
+
this.cachedLines = null
|
|
58
|
+
const widths = rawLines.map((line) => Math.min(displayWidth(line), maxW))
|
|
59
|
+
const w = widths.reduce((max, val) => Math.max(max, val), 0)
|
|
60
|
+
const h = Math.min(rawLines.length, maxH)
|
|
61
|
+
return { w, h }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Wrap text to fit within maxWidth */
|
|
65
|
+
private wrapText(text: string, maxWidth: number): string[] {
|
|
66
|
+
const result: string[] = []
|
|
67
|
+
for (const rawLine of text.split("\n")) {
|
|
68
|
+
if (rawLine === "") {
|
|
69
|
+
result.push("")
|
|
70
|
+
continue
|
|
71
|
+
}
|
|
72
|
+
let line = ""
|
|
73
|
+
let lineW = 0
|
|
74
|
+
for (const ch of rawLine) {
|
|
75
|
+
const w = displayWidth(ch)
|
|
76
|
+
if (lineW + w > maxWidth && line.length > 0) {
|
|
77
|
+
result.push(line)
|
|
78
|
+
line = ch
|
|
79
|
+
lineW = w
|
|
80
|
+
} else {
|
|
81
|
+
line += ch
|
|
82
|
+
lineW += w
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (line.length > 0) result.push(line)
|
|
86
|
+
}
|
|
87
|
+
return result.length > 0 ? result : [""]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
override layout(rect: Rect): void {
|
|
91
|
+
super.layout(rect)
|
|
92
|
+
// Layout children (RawTextHost nodes) at same position
|
|
93
|
+
for (const child of this.children) {
|
|
94
|
+
child.layout(rect)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
render(buffer: CellBuffer, palette: Palette): void {
|
|
99
|
+
if (!this.rect) return
|
|
100
|
+
|
|
101
|
+
const style: Record<string, unknown> = {}
|
|
102
|
+
if (this.fg !== undefined) style.fg = typeof this.fg === "string" ? parseColor(this.fg) : this.fg
|
|
103
|
+
if (this.bg !== undefined) style.bg = typeof this.bg === "string" ? parseColor(this.bg) : this.bg
|
|
104
|
+
if (this.bold) style.bold = true
|
|
105
|
+
if (this.italic) style.italic = true
|
|
106
|
+
if (this.underline) style.underline = true
|
|
107
|
+
if (this.inverse) style.inverse = true
|
|
108
|
+
|
|
109
|
+
const styleId = palette.id(style)
|
|
110
|
+
const content = this.getContent()
|
|
111
|
+
const rawLines = content.split("\n")
|
|
112
|
+
|
|
113
|
+
if (this.wrap) {
|
|
114
|
+
// Wrap mode: use cached lines if width matches, otherwise rewrap
|
|
115
|
+
const rectW = this.rect.w
|
|
116
|
+
const lines =
|
|
117
|
+
this.cachedLines && this.cachedWidth === rectW
|
|
118
|
+
? this.cachedLines
|
|
119
|
+
: rawLines.flatMap((line, idx) =>
|
|
120
|
+
idx < rawLines.length - 1 ? [...this.wrapText(line, rectW), ""] : this.wrapText(line, rectW),
|
|
121
|
+
)
|
|
122
|
+
for (let i = 0; i < lines.length && i < this.rect.h; i++) {
|
|
123
|
+
buffer.drawText(this.rect.x, this.rect.y + i, lines[i], styleId, this.rect.w)
|
|
124
|
+
}
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Default: render explicit newlines, clip to width/height
|
|
129
|
+
const maxLines = Math.min(this.rect.h, rawLines.length)
|
|
130
|
+
for (let i = 0; i < maxLines; i++) {
|
|
131
|
+
buffer.drawText(this.rect.x, this.rect.y + i, rawLines[i], styleId, this.rect.w)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
override updateProps(props: Record<string, unknown>): void {
|
|
136
|
+
super.updateProps(props)
|
|
137
|
+
// Always assign; props may be undefined when attribute is removed
|
|
138
|
+
this.fg = props.fg as ColorLike | undefined
|
|
139
|
+
this.bg = props.bg as ColorLike | undefined
|
|
140
|
+
this.bold = Boolean(props.bold)
|
|
141
|
+
this.italic = Boolean(props.italic)
|
|
142
|
+
this.underline = Boolean(props.underline)
|
|
143
|
+
this.inverse = Boolean(props.inverse)
|
|
144
|
+
this.wrap = Boolean(props.wrap)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Special host for raw text nodes (React text children) */
|
|
149
|
+
export class RawTextHost extends BaseHost {
|
|
150
|
+
content = ""
|
|
151
|
+
|
|
152
|
+
constructor(text: string, ctx: HostContext) {
|
|
153
|
+
super("rawtext", {}, ctx)
|
|
154
|
+
this.content = text
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
measure(maxW: number, _maxH: number): Size {
|
|
158
|
+
const w = Math.min(displayWidth(this.content), maxW)
|
|
159
|
+
return { w, h: 1 }
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
render(buffer: CellBuffer, palette: Palette): void {
|
|
163
|
+
if (!this.rect) return
|
|
164
|
+
const styleId = palette.id({})
|
|
165
|
+
buffer.drawText(this.rect.x, this.rect.y, this.content, styleId, this.rect.w)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
updateText(text: string): void {
|
|
169
|
+
this.content = text
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
override updateProps(_props: Record<string, unknown>): void {
|
|
173
|
+
// Raw text has no props
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { CellBuffer, Palette } from "@effect-tui/core"
|
|
2
|
+
import type { HostContext, Rect, Size, CommonProps } from "../reconciler/types.js"
|
|
3
|
+
import { BaseHost } from "./base.js"
|
|
4
|
+
import { measureFlex, layoutFlex, type FlexAlignment } from "../utils/index.js"
|
|
5
|
+
|
|
6
|
+
export interface VStackProps extends CommonProps {
|
|
7
|
+
spacing?: number
|
|
8
|
+
alignment?: "leading" | "center" | "trailing"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Map VStack alignment names to generic flex alignment
|
|
12
|
+
function toFlexAlignment(alignment: "leading" | "center" | "trailing"): FlexAlignment {
|
|
13
|
+
switch (alignment) {
|
|
14
|
+
case "leading":
|
|
15
|
+
return "start"
|
|
16
|
+
case "center":
|
|
17
|
+
return "center"
|
|
18
|
+
case "trailing":
|
|
19
|
+
return "end"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class VStackHost extends BaseHost {
|
|
24
|
+
spacing = 0
|
|
25
|
+
alignment: "leading" | "center" | "trailing" = "leading"
|
|
26
|
+
private cachedSizes: Size[] = []
|
|
27
|
+
|
|
28
|
+
constructor(props: VStackProps, ctx: HostContext) {
|
|
29
|
+
super("vstack", props, ctx)
|
|
30
|
+
this.updateProps(props)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
measure(maxW: number, maxH: number): Size {
|
|
34
|
+
const result = measureFlex("vertical", this.children, this.spacing, maxH, maxW)
|
|
35
|
+
this.cachedSizes = result.sizes
|
|
36
|
+
return result.totalSize
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override layout(rect: Rect): void {
|
|
40
|
+
super.layout(rect)
|
|
41
|
+
const stretchCross = this.alignment === "leading"
|
|
42
|
+
layoutFlex(
|
|
43
|
+
"vertical",
|
|
44
|
+
this.children,
|
|
45
|
+
this.cachedSizes,
|
|
46
|
+
rect,
|
|
47
|
+
this.spacing,
|
|
48
|
+
toFlexAlignment(this.alignment),
|
|
49
|
+
stretchCross,
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
render(buffer: CellBuffer, palette: Palette): void {
|
|
54
|
+
for (const child of this.children) {
|
|
55
|
+
child.render(buffer, palette)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
override updateProps(props: Record<string, unknown>): void {
|
|
60
|
+
super.updateProps(props)
|
|
61
|
+
if (props.spacing !== undefined) this.spacing = props.spacing as number
|
|
62
|
+
if (props.alignment !== undefined) this.alignment = props.alignment as "leading" | "center" | "trailing"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { CellBuffer, Palette } from "@effect-tui/core"
|
|
2
|
+
import type { HostContext, Rect, Size, CommonProps } from "../reconciler/types.js"
|
|
3
|
+
import { BaseHost } from "./base.js"
|
|
4
|
+
|
|
5
|
+
export interface ZStackProps extends CommonProps {
|
|
6
|
+
alignment?: { h?: "leading" | "center" | "trailing"; v?: "top" | "center" | "bottom" }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Overlay children in the same rect, honoring alignment for each child.
|
|
10
|
+
export class ZStackHost extends BaseHost {
|
|
11
|
+
alignmentH: "leading" | "center" | "trailing" = "center"
|
|
12
|
+
alignmentV: "top" | "center" | "bottom" = "center"
|
|
13
|
+
private cachedSizes: Size[] = []
|
|
14
|
+
|
|
15
|
+
constructor(props: ZStackProps, ctx: HostContext) {
|
|
16
|
+
super("zstack", props, ctx)
|
|
17
|
+
this.updateProps(props)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
measure(maxW: number, maxH: number): Size {
|
|
21
|
+
let maxChildW = 0
|
|
22
|
+
let maxChildH = 0
|
|
23
|
+
this.cachedSizes = []
|
|
24
|
+
|
|
25
|
+
for (const child of this.children) {
|
|
26
|
+
const size = child.measure(maxW, maxH)
|
|
27
|
+
this.cachedSizes.push(size)
|
|
28
|
+
maxChildW = Math.max(maxChildW, size.w)
|
|
29
|
+
maxChildH = Math.max(maxChildH, size.h)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
w: Math.min(maxW, maxChildW),
|
|
34
|
+
h: Math.min(maxH, maxChildH),
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
override layout(rect: Rect): void {
|
|
39
|
+
super.layout(rect)
|
|
40
|
+
|
|
41
|
+
for (let i = 0; i < this.children.length; i++) {
|
|
42
|
+
const child = this.children[i]
|
|
43
|
+
const size = this.cachedSizes[i] ?? child.measure(rect.w, rect.h)
|
|
44
|
+
|
|
45
|
+
let x = rect.x
|
|
46
|
+
let y = rect.y
|
|
47
|
+
|
|
48
|
+
if (this.alignmentH === "center") x += Math.floor((rect.w - size.w) / 2)
|
|
49
|
+
else if (this.alignmentH === "trailing") x += Math.max(0, rect.w - size.w)
|
|
50
|
+
|
|
51
|
+
if (this.alignmentV === "center") y += Math.floor((rect.h - size.h) / 2)
|
|
52
|
+
else if (this.alignmentV === "bottom") y += Math.max(0, rect.h - size.h)
|
|
53
|
+
|
|
54
|
+
child.layout({
|
|
55
|
+
x,
|
|
56
|
+
y,
|
|
57
|
+
w: Math.min(rect.w, size.w),
|
|
58
|
+
h: Math.min(rect.h, size.h),
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
render(buffer: CellBuffer, palette: Palette): void {
|
|
64
|
+
for (const child of this.children) {
|
|
65
|
+
child.render(buffer, palette)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
override updateProps(props: Record<string, unknown>): void {
|
|
70
|
+
super.updateProps(props)
|
|
71
|
+
if (props.alignment !== undefined) {
|
|
72
|
+
const a = props.alignment as ZStackProps["alignment"]
|
|
73
|
+
if (a?.h) this.alignmentH = a.h
|
|
74
|
+
if (a?.v) this.alignmentV = a.v
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Convenience: re-export core theming/types so apps can import from one place
|
|
2
|
+
export * from "@effect-tui/core"
|
|
3
|
+
|
|
4
|
+
// Renderer
|
|
5
|
+
export {
|
|
6
|
+
createRenderer,
|
|
7
|
+
createRoot,
|
|
8
|
+
render,
|
|
9
|
+
useRenderer,
|
|
10
|
+
useTerminalSize,
|
|
11
|
+
RendererContext,
|
|
12
|
+
} from "./renderer.js"
|
|
13
|
+
export type { TuiRenderer, RendererOptions, Root, FrameStats, RenderInstance } from "./renderer.js"
|
|
14
|
+
|
|
15
|
+
// Components
|
|
16
|
+
export { CodeBlock } from "./codeblock.js"
|
|
17
|
+
export type { CodeBlockProps } from "./codeblock.js"
|
|
18
|
+
|
|
19
|
+
// Highlight utilities
|
|
20
|
+
export {
|
|
21
|
+
highlightCode,
|
|
22
|
+
toPlainLines,
|
|
23
|
+
type HighlightLine,
|
|
24
|
+
type HighlightToken,
|
|
25
|
+
type HighlightTokenStyle,
|
|
26
|
+
} from "./highlight.js"
|
|
27
|
+
|
|
28
|
+
// Hooks
|
|
29
|
+
export { useKeyboard, usePaste } from "./hooks/index.js"
|
|
30
|
+
export { useFrameStats } from "./hooks/useFrameStats.js"
|
|
31
|
+
export type { UseKeyboardOptions } from "./hooks/index.js"
|
|
32
|
+
|
|
33
|
+
// Motion (spring animations)
|
|
34
|
+
export {
|
|
35
|
+
useMotionValue,
|
|
36
|
+
useSpring,
|
|
37
|
+
useSprings,
|
|
38
|
+
useSpringRenderer,
|
|
39
|
+
useMotionValueEvent,
|
|
40
|
+
useAnimationFrame,
|
|
41
|
+
motionValue,
|
|
42
|
+
// Color springs
|
|
43
|
+
ColorMotionValue,
|
|
44
|
+
useColorMotionValue,
|
|
45
|
+
useColorSpring,
|
|
46
|
+
} from "./motion/index.js"
|
|
47
|
+
export type { SpringOptions, MotionValue, RGBA, ColorInput } from "./motion/index.js"
|
|
48
|
+
|
|
49
|
+
// Types
|
|
50
|
+
export type { HostInstance, HostContext, Rect, Size, CommonProps } from "./reconciler/types.js"
|
|
51
|
+
export type { TextProps } from "./hosts/text.js"
|
|
52
|
+
export type { SpacerProps } from "./hosts/spacer.js"
|
|
53
|
+
export type { VStackProps } from "./hosts/vstack.js"
|
|
54
|
+
export type { HStackProps } from "./hosts/hstack.js"
|
|
55
|
+
export type { BoxProps, BorderKind } from "./hosts/box.js"
|
|
56
|
+
export type { CanvasProps, DrawContext } from "./hosts/canvas.js"
|
|
57
|
+
|
|
58
|
+
// Debug
|
|
59
|
+
export { DiagnosticsPanel } from "./debug/DiagnosticsPanel.js"
|
|
60
|
+
|
|
61
|
+
// JSX types are provided via jsxImportSource: "@effect-tui/react"
|
|
62
|
+
// See jsx-runtime.ts at package root for the JSX namespace
|