@dealdeploy/skl 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/opentui/SKILL.md +198 -0
- package/.agents/skills/opentui/references/animation/REFERENCE.md +431 -0
- package/.agents/skills/opentui/references/components/REFERENCE.md +143 -0
- package/.agents/skills/opentui/references/components/code-diff.md +496 -0
- package/.agents/skills/opentui/references/components/containers.md +412 -0
- package/.agents/skills/opentui/references/components/inputs.md +531 -0
- package/.agents/skills/opentui/references/components/text-display.md +384 -0
- package/.agents/skills/opentui/references/core/REFERENCE.md +145 -0
- package/.agents/skills/opentui/references/core/api.md +506 -0
- package/.agents/skills/opentui/references/core/configuration.md +166 -0
- package/.agents/skills/opentui/references/core/gotchas.md +393 -0
- package/.agents/skills/opentui/references/core/patterns.md +448 -0
- package/.agents/skills/opentui/references/keyboard/REFERENCE.md +511 -0
- package/.agents/skills/opentui/references/layout/REFERENCE.md +337 -0
- package/.agents/skills/opentui/references/layout/patterns.md +444 -0
- package/.agents/skills/opentui/references/react/REFERENCE.md +174 -0
- package/.agents/skills/opentui/references/react/api.md +435 -0
- package/.agents/skills/opentui/references/react/configuration.md +301 -0
- package/.agents/skills/opentui/references/react/gotchas.md +443 -0
- package/.agents/skills/opentui/references/react/patterns.md +501 -0
- package/.agents/skills/opentui/references/solid/REFERENCE.md +201 -0
- package/.agents/skills/opentui/references/solid/api.md +543 -0
- package/.agents/skills/opentui/references/solid/configuration.md +315 -0
- package/.agents/skills/opentui/references/solid/gotchas.md +415 -0
- package/.agents/skills/opentui/references/solid/patterns.md +558 -0
- package/.agents/skills/opentui/references/testing/REFERENCE.md +614 -0
- package/.claude/skills/opentui/SKILL.md +198 -0
- package/.claude/skills/opentui/references/animation/REFERENCE.md +431 -0
- package/.claude/skills/opentui/references/components/REFERENCE.md +143 -0
- package/.claude/skills/opentui/references/components/code-diff.md +496 -0
- package/.claude/skills/opentui/references/components/containers.md +412 -0
- package/.claude/skills/opentui/references/components/inputs.md +531 -0
- package/.claude/skills/opentui/references/components/text-display.md +384 -0
- package/.claude/skills/opentui/references/core/REFERENCE.md +145 -0
- package/.claude/skills/opentui/references/core/api.md +506 -0
- package/.claude/skills/opentui/references/core/configuration.md +166 -0
- package/.claude/skills/opentui/references/core/gotchas.md +393 -0
- package/.claude/skills/opentui/references/core/patterns.md +448 -0
- package/.claude/skills/opentui/references/keyboard/REFERENCE.md +511 -0
- package/.claude/skills/opentui/references/layout/REFERENCE.md +337 -0
- package/.claude/skills/opentui/references/layout/patterns.md +444 -0
- package/.claude/skills/opentui/references/react/REFERENCE.md +174 -0
- package/.claude/skills/opentui/references/react/api.md +435 -0
- package/.claude/skills/opentui/references/react/configuration.md +301 -0
- package/.claude/skills/opentui/references/react/gotchas.md +443 -0
- package/.claude/skills/opentui/references/react/patterns.md +501 -0
- package/.claude/skills/opentui/references/solid/REFERENCE.md +201 -0
- package/.claude/skills/opentui/references/solid/api.md +543 -0
- package/.claude/skills/opentui/references/solid/configuration.md +315 -0
- package/.claude/skills/opentui/references/solid/gotchas.md +415 -0
- package/.claude/skills/opentui/references/solid/patterns.md +558 -0
- package/.claude/skills/opentui/references/testing/REFERENCE.md +614 -0
- package/index.ts +169 -38
- package/package.json +1 -1
- package/update.ts +87 -0
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
# Core API Reference
|
|
2
|
+
|
|
3
|
+
## Renderer
|
|
4
|
+
|
|
5
|
+
### createCliRenderer(config?)
|
|
6
|
+
|
|
7
|
+
Creates and initializes the CLI renderer.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { createCliRenderer, type CliRendererConfig } from "@opentui/core"
|
|
11
|
+
|
|
12
|
+
const renderer = await createCliRenderer({
|
|
13
|
+
targetFPS: 60, // Target frames per second
|
|
14
|
+
exitOnCtrlC: true, // Exit process on Ctrl+C
|
|
15
|
+
consoleOptions: { // Debug console overlay
|
|
16
|
+
position: ConsolePosition.BOTTOM,
|
|
17
|
+
sizePercent: 30,
|
|
18
|
+
startInDebugMode: false,
|
|
19
|
+
},
|
|
20
|
+
onDestroy: () => {}, // Cleanup callback
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### CliRenderer Instance
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
renderer.root // Root renderable node
|
|
28
|
+
renderer.width // Terminal width in columns
|
|
29
|
+
renderer.height // Terminal height in rows
|
|
30
|
+
renderer.keyInput // Keyboard event emitter
|
|
31
|
+
renderer.console // Console overlay controller
|
|
32
|
+
|
|
33
|
+
renderer.start() // Start render loop
|
|
34
|
+
renderer.stop() // Stop render loop
|
|
35
|
+
renderer.destroy() // Cleanup and exit alternate screen
|
|
36
|
+
renderer.requestRender() // Request a re-render
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Console Overlay
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
renderer.console.show() // Show console overlay
|
|
43
|
+
renderer.console.hide() // Hide console overlay
|
|
44
|
+
renderer.console.toggle() // Toggle visibility/focus
|
|
45
|
+
renderer.console.clear() // Clear console contents
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Renderables
|
|
49
|
+
|
|
50
|
+
All renderables extend the base `Renderable` class and share common properties.
|
|
51
|
+
|
|
52
|
+
### Common Properties
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
interface CommonProps {
|
|
56
|
+
id?: string // Unique identifier
|
|
57
|
+
|
|
58
|
+
// Positioning
|
|
59
|
+
position?: "relative" | "absolute"
|
|
60
|
+
left?: number | string
|
|
61
|
+
top?: number | string
|
|
62
|
+
right?: number | string
|
|
63
|
+
bottom?: number | string
|
|
64
|
+
|
|
65
|
+
// Dimensions
|
|
66
|
+
width?: number | string | "auto"
|
|
67
|
+
height?: number | string | "auto"
|
|
68
|
+
minWidth?: number
|
|
69
|
+
minHeight?: number
|
|
70
|
+
maxWidth?: number
|
|
71
|
+
maxHeight?: number
|
|
72
|
+
|
|
73
|
+
// Flexbox
|
|
74
|
+
flexDirection?: "row" | "column" | "row-reverse" | "column-reverse"
|
|
75
|
+
flexGrow?: number
|
|
76
|
+
flexShrink?: number
|
|
77
|
+
flexBasis?: number | string
|
|
78
|
+
flexWrap?: "nowrap" | "wrap" | "wrap-reverse"
|
|
79
|
+
justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly"
|
|
80
|
+
alignItems?: "flex-start" | "flex-end" | "center" | "stretch" | "baseline"
|
|
81
|
+
alignSelf?: "auto" | "flex-start" | "flex-end" | "center" | "stretch" | "baseline"
|
|
82
|
+
alignContent?: "flex-start" | "flex-end" | "center" | "stretch" | "space-between" | "space-around"
|
|
83
|
+
|
|
84
|
+
// Spacing
|
|
85
|
+
padding?: number
|
|
86
|
+
paddingTop?: number
|
|
87
|
+
paddingRight?: number
|
|
88
|
+
paddingBottom?: number
|
|
89
|
+
paddingLeft?: number
|
|
90
|
+
margin?: number
|
|
91
|
+
marginTop?: number
|
|
92
|
+
marginRight?: number
|
|
93
|
+
marginBottom?: number
|
|
94
|
+
marginLeft?: number
|
|
95
|
+
gap?: number
|
|
96
|
+
|
|
97
|
+
// Display
|
|
98
|
+
display?: "flex" | "none"
|
|
99
|
+
overflow?: "visible" | "hidden" | "scroll"
|
|
100
|
+
zIndex?: number
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Renderable Methods
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
renderable.add(child) // Add child renderable
|
|
108
|
+
renderable.remove(child) // Remove child renderable
|
|
109
|
+
renderable.getRenderable(id) // Find child by ID
|
|
110
|
+
renderable.focus() // Focus this renderable
|
|
111
|
+
renderable.blur() // Remove focus
|
|
112
|
+
renderable.destroy() // Destroy and cleanup
|
|
113
|
+
|
|
114
|
+
renderable.on(event, handler) // Add event listener
|
|
115
|
+
renderable.off(event, handler) // Remove event listener
|
|
116
|
+
renderable.emit(event, ...args) // Emit event
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### TextRenderable
|
|
120
|
+
|
|
121
|
+
Display styled text content.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import { TextRenderable, TextAttributes, t, bold, fg, underline } from "@opentui/core"
|
|
125
|
+
|
|
126
|
+
const text = new TextRenderable(renderer, {
|
|
127
|
+
id: "text",
|
|
128
|
+
content: "Hello World",
|
|
129
|
+
fg: "#FFFFFF", // Foreground color
|
|
130
|
+
bg: "#000000", // Background color
|
|
131
|
+
attributes: TextAttributes.BOLD | TextAttributes.UNDERLINE,
|
|
132
|
+
selectable: true, // Allow text selection
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
// Styled text with template literals
|
|
136
|
+
const styled = new TextRenderable(renderer, {
|
|
137
|
+
content: t`${bold("Bold")} and ${fg("#FF0000")(underline("red underlined"))}`,
|
|
138
|
+
})
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**TextAttributes flags:**
|
|
142
|
+
- `TextAttributes.BOLD`
|
|
143
|
+
- `TextAttributes.DIM`
|
|
144
|
+
- `TextAttributes.ITALIC`
|
|
145
|
+
- `TextAttributes.UNDERLINE`
|
|
146
|
+
- `TextAttributes.BLINK`
|
|
147
|
+
- `TextAttributes.INVERSE`
|
|
148
|
+
- `TextAttributes.HIDDEN`
|
|
149
|
+
- `TextAttributes.STRIKETHROUGH`
|
|
150
|
+
|
|
151
|
+
### BoxRenderable
|
|
152
|
+
|
|
153
|
+
Container with borders and layout.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { BoxRenderable } from "@opentui/core"
|
|
157
|
+
|
|
158
|
+
const box = new BoxRenderable(renderer, {
|
|
159
|
+
id: "box",
|
|
160
|
+
width: 40,
|
|
161
|
+
height: 10,
|
|
162
|
+
backgroundColor: "#1a1a2e",
|
|
163
|
+
border: true,
|
|
164
|
+
borderStyle: "single" | "double" | "rounded" | "bold" | "none",
|
|
165
|
+
borderColor: "#FFFFFF",
|
|
166
|
+
title: "Panel Title",
|
|
167
|
+
titleAlignment: "left" | "center" | "right",
|
|
168
|
+
onMouseDown: (event) => {},
|
|
169
|
+
onMouseUp: (event) => {},
|
|
170
|
+
onMouseMove: (event) => {},
|
|
171
|
+
})
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### InputRenderable
|
|
175
|
+
|
|
176
|
+
Single-line text input.
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { InputRenderable, InputRenderableEvents } from "@opentui/core"
|
|
180
|
+
|
|
181
|
+
const input = new InputRenderable(renderer, {
|
|
182
|
+
id: "input",
|
|
183
|
+
width: 30,
|
|
184
|
+
placeholder: "Enter text...",
|
|
185
|
+
value: "", // Initial value
|
|
186
|
+
backgroundColor: "#1a1a1a",
|
|
187
|
+
textColor: "#FFFFFF",
|
|
188
|
+
cursorColor: "#00FF00",
|
|
189
|
+
focusedBackgroundColor: "#2a2a2a",
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
input.on(InputRenderableEvents.CHANGE, (value: string) => {
|
|
193
|
+
console.log("Value:", value)
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
input.focus() // Must be focused to receive input
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### SelectRenderable
|
|
200
|
+
|
|
201
|
+
List selection component.
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { SelectRenderable, SelectRenderableEvents } from "@opentui/core"
|
|
205
|
+
|
|
206
|
+
const select = new SelectRenderable(renderer, {
|
|
207
|
+
id: "select",
|
|
208
|
+
width: 30,
|
|
209
|
+
height: 10,
|
|
210
|
+
options: [
|
|
211
|
+
{ name: "Option 1", description: "First option", value: "1" },
|
|
212
|
+
{ name: "Option 2", description: "Second option", value: "2" },
|
|
213
|
+
],
|
|
214
|
+
selectedIndex: 0,
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
// Called when Enter is pressed - selection confirmed
|
|
218
|
+
select.on(SelectRenderableEvents.ITEM_SELECTED, (index, option) => {
|
|
219
|
+
console.log("Selected:", option.name)
|
|
220
|
+
performAction(option)
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
// Called when navigating with arrow keys
|
|
224
|
+
select.on(SelectRenderableEvents.SELECTION_CHANGED, (index, option) => {
|
|
225
|
+
console.log("Browsing:", option.name)
|
|
226
|
+
showPreview(option)
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
select.focus() // Navigate with up/down/j/k, select with enter
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Event distinction:**
|
|
233
|
+
- `ITEM_SELECTED` - Enter key pressed, user confirms selection
|
|
234
|
+
- `SELECTION_CHANGED` - Arrow keys, user navigating/browsing options
|
|
235
|
+
|
|
236
|
+
### TabSelectRenderable
|
|
237
|
+
|
|
238
|
+
Horizontal tab selection.
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
import { TabSelectRenderable, TabSelectRenderableEvents } from "@opentui/core"
|
|
242
|
+
|
|
243
|
+
const tabs = new TabSelectRenderable(renderer, {
|
|
244
|
+
id: "tabs",
|
|
245
|
+
width: 60,
|
|
246
|
+
options: [
|
|
247
|
+
{ name: "Home", description: "Dashboard" },
|
|
248
|
+
{ name: "Settings", description: "Configuration" },
|
|
249
|
+
],
|
|
250
|
+
tabWidth: 20,
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
// Called when Enter is pressed - tab selected
|
|
254
|
+
tabs.on(TabSelectRenderableEvents.ITEM_SELECTED, (index, option) => {
|
|
255
|
+
console.log("Tab selected:", option.name)
|
|
256
|
+
switchToTab(index)
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
// Called when navigating with arrow keys
|
|
260
|
+
tabs.on(TabSelectRenderableEvents.SELECTION_CHANGED, (index, option) => {
|
|
261
|
+
console.log("Browsing tab:", option.name)
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
tabs.focus() // Navigate with left/right/[/], select with enter
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Event distinction** (same as SelectRenderable):
|
|
268
|
+
- `ITEM_SELECTED` - Enter key pressed, user confirms tab
|
|
269
|
+
- `SELECTION_CHANGED` - Arrow keys, user navigating tabs
|
|
270
|
+
|
|
271
|
+
### ScrollBoxRenderable
|
|
272
|
+
|
|
273
|
+
Scrollable container.
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
import { ScrollBoxRenderable } from "@opentui/core"
|
|
277
|
+
|
|
278
|
+
const scrollbox = new ScrollBoxRenderable(renderer, {
|
|
279
|
+
id: "scrollbox",
|
|
280
|
+
width: 40,
|
|
281
|
+
height: 20,
|
|
282
|
+
showScrollbar: true,
|
|
283
|
+
scrollbarOptions: {
|
|
284
|
+
showArrows: true,
|
|
285
|
+
trackOptions: {
|
|
286
|
+
foregroundColor: "#7aa2f7",
|
|
287
|
+
backgroundColor: "#414868",
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
// Add content that exceeds viewport
|
|
293
|
+
for (let i = 0; i < 100; i++) {
|
|
294
|
+
scrollbox.add(new TextRenderable(renderer, {
|
|
295
|
+
id: `line-${i}`,
|
|
296
|
+
content: `Line ${i}`,
|
|
297
|
+
}))
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
scrollbox.focus() // Scroll with arrow keys
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### ASCIIFontRenderable
|
|
304
|
+
|
|
305
|
+
ASCII art text.
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
import { ASCIIFontRenderable, RGBA } from "@opentui/core"
|
|
309
|
+
|
|
310
|
+
const title = new ASCIIFontRenderable(renderer, {
|
|
311
|
+
id: "title",
|
|
312
|
+
text: "OPENTUI",
|
|
313
|
+
font: "tiny" | "block" | "slick" | "shade",
|
|
314
|
+
color: RGBA.fromHex("#FFFFFF"),
|
|
315
|
+
})
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### FrameBufferRenderable
|
|
319
|
+
|
|
320
|
+
Low-level 2D rendering surface.
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
import { FrameBufferRenderable, RGBA } from "@opentui/core"
|
|
324
|
+
|
|
325
|
+
const canvas = new FrameBufferRenderable(renderer, {
|
|
326
|
+
id: "canvas",
|
|
327
|
+
width: 50,
|
|
328
|
+
height: 20,
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
// Direct pixel manipulation
|
|
332
|
+
canvas.frameBuffer.fillRect(10, 5, 20, 8, RGBA.fromHex("#FF0000"))
|
|
333
|
+
canvas.frameBuffer.drawText("Custom", 12, 7, RGBA.fromHex("#FFFFFF"))
|
|
334
|
+
canvas.frameBuffer.setCell(x, y, char, fg, bg)
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Constructs (VNode API)
|
|
338
|
+
|
|
339
|
+
Declarative wrappers that create VNodes instead of direct instances.
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
import { Text, Box, Input, Select, instantiate, delegate } from "@opentui/core"
|
|
343
|
+
|
|
344
|
+
// Create VNode tree
|
|
345
|
+
const ui = Box(
|
|
346
|
+
{ border: true, padding: 1 },
|
|
347
|
+
Text({ content: "Hello" }),
|
|
348
|
+
Input({ placeholder: "Type here..." }),
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
// Instantiate onto renderer
|
|
352
|
+
renderer.root.add(ui)
|
|
353
|
+
|
|
354
|
+
// Delegate focus to nested element
|
|
355
|
+
const form = delegate(
|
|
356
|
+
{ focus: "email-input" },
|
|
357
|
+
Box(
|
|
358
|
+
{},
|
|
359
|
+
Text({ content: "Email:" }),
|
|
360
|
+
Input({ id: "email-input", placeholder: "you@example.com" }),
|
|
361
|
+
),
|
|
362
|
+
)
|
|
363
|
+
form.focus() // Focuses the input, not the box
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Colors (RGBA)
|
|
367
|
+
|
|
368
|
+
The `RGBA` class is exported from `@opentui/core` but works across **all frameworks** (Core, React, Solid). Use it for programmatic color manipulation.
|
|
369
|
+
|
|
370
|
+
### Creating Colors
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
import { RGBA, parseColor } from "@opentui/core"
|
|
374
|
+
|
|
375
|
+
// From hex string (most common)
|
|
376
|
+
RGBA.fromHex("#FF0000") // Full hex
|
|
377
|
+
RGBA.fromHex("#F00") // Short hex
|
|
378
|
+
|
|
379
|
+
// From integers (0-255 range)
|
|
380
|
+
RGBA.fromInts(255, 0, 0, 255) // r, g, b, a - fully opaque red
|
|
381
|
+
RGBA.fromInts(255, 0, 0, 128) // 50% transparent red
|
|
382
|
+
RGBA.fromInts(0, 0, 0, 0) // Fully transparent
|
|
383
|
+
|
|
384
|
+
// From normalized floats (0.0-1.0 range)
|
|
385
|
+
RGBA.fromValues(1.0, 0.0, 0.0, 1.0) // Fully opaque red
|
|
386
|
+
RGBA.fromValues(0.1, 0.1, 0.1, 0.7) // Dark gray, 70% opaque
|
|
387
|
+
RGBA.fromValues(0.0, 0.5, 1.0, 1.0) // Light blue
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Common Color Patterns
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
// Theme colors
|
|
394
|
+
const primary = RGBA.fromHex("#7aa2f7") // Tokyo Night blue
|
|
395
|
+
const background = RGBA.fromHex("#1a1a2e")
|
|
396
|
+
const foreground = RGBA.fromHex("#c0caf5")
|
|
397
|
+
const error = RGBA.fromHex("#f7768e")
|
|
398
|
+
|
|
399
|
+
// Overlays and shadows
|
|
400
|
+
const modalOverlay = RGBA.fromValues(0.0, 0.0, 0.0, 0.5) // 50% black
|
|
401
|
+
const shadow = RGBA.fromInts(0, 0, 0, 77) // 30% black
|
|
402
|
+
|
|
403
|
+
// Borders
|
|
404
|
+
const activeBorder = RGBA.fromHex("#7aa2f7")
|
|
405
|
+
const inactiveBorder = RGBA.fromInts(65, 72, 104, 255)
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### parseColor Utility
|
|
409
|
+
|
|
410
|
+
```typescript
|
|
411
|
+
// Accepts multiple formats
|
|
412
|
+
parseColor("#FF0000") // Hex string
|
|
413
|
+
parseColor("red") // CSS color name
|
|
414
|
+
parseColor("transparent") // Special values
|
|
415
|
+
parseColor(RGBA.fromHex("#F00")) // Pass-through RGBA objects
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### When to Use Each Method
|
|
419
|
+
|
|
420
|
+
| Method | Use When |
|
|
421
|
+
|--------|----------|
|
|
422
|
+
| `fromHex()` | Working with design specs, CSS colors, config files |
|
|
423
|
+
| `fromInts()` | You have 8-bit values (0-255), common in graphics |
|
|
424
|
+
| `fromValues()` | Doing color interpolation, animations, math |
|
|
425
|
+
| `parseColor()` | Accepting user input or config that could be any format |
|
|
426
|
+
|
|
427
|
+
### Using RGBA in React/Solid
|
|
428
|
+
|
|
429
|
+
```tsx
|
|
430
|
+
// Import from @opentui/core, use in any framework
|
|
431
|
+
import { RGBA } from "@opentui/core"
|
|
432
|
+
|
|
433
|
+
// React or Solid component
|
|
434
|
+
function ThemedBox() {
|
|
435
|
+
const bg = RGBA.fromHex("#1a1a2e")
|
|
436
|
+
const border = RGBA.fromInts(122, 162, 247, 255)
|
|
437
|
+
|
|
438
|
+
return (
|
|
439
|
+
<box backgroundColor={bg} borderColor={border} border>
|
|
440
|
+
<text fg={RGBA.fromHex("#c0caf5")}>Works everywhere!</text>
|
|
441
|
+
</box>
|
|
442
|
+
)
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
Color props in React/Solid accept both string formats (`"#FF0000"`, `"red"`) and `RGBA` objects.
|
|
447
|
+
|
|
448
|
+
## Keyboard Input
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
import { type KeyEvent } from "@opentui/core"
|
|
452
|
+
|
|
453
|
+
renderer.keyInput.on("keypress", (key: KeyEvent) => {
|
|
454
|
+
console.log(key.name) // "a", "escape", "f1", etc.
|
|
455
|
+
console.log(key.sequence) // Raw escape sequence
|
|
456
|
+
console.log(key.ctrl) // Ctrl held
|
|
457
|
+
console.log(key.shift) // Shift held
|
|
458
|
+
console.log(key.meta) // Alt held
|
|
459
|
+
console.log(key.option) // Option held (macOS)
|
|
460
|
+
console.log(key.eventType) // "press" | "release" | "repeat"
|
|
461
|
+
})
|
|
462
|
+
|
|
463
|
+
renderer.keyInput.on("paste", (text: string) => {
|
|
464
|
+
console.log("Pasted:", text)
|
|
465
|
+
})
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## Animation Timeline
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
import { Timeline, engine } from "@opentui/core"
|
|
472
|
+
|
|
473
|
+
const timeline = new Timeline({
|
|
474
|
+
duration: 2000,
|
|
475
|
+
loop: false,
|
|
476
|
+
autoplay: true,
|
|
477
|
+
})
|
|
478
|
+
|
|
479
|
+
timeline.add(
|
|
480
|
+
{ width: 0 },
|
|
481
|
+
{
|
|
482
|
+
width: 50,
|
|
483
|
+
duration: 1000,
|
|
484
|
+
ease: "easeOutQuad",
|
|
485
|
+
onUpdate: (anim) => {
|
|
486
|
+
box.setWidth(anim.targets[0].width)
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
engine.attach(renderer)
|
|
492
|
+
engine.addTimeline(timeline)
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
## Type Exports
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
import type {
|
|
499
|
+
CliRenderer,
|
|
500
|
+
CliRendererConfig,
|
|
501
|
+
RenderContext,
|
|
502
|
+
KeyEvent,
|
|
503
|
+
Renderable,
|
|
504
|
+
// ... and more
|
|
505
|
+
} from "@opentui/core"
|
|
506
|
+
```
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Core Configuration
|
|
2
|
+
|
|
3
|
+
## Renderer Configuration
|
|
4
|
+
|
|
5
|
+
### createCliRenderer Options
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { createCliRenderer, ConsolePosition } from "@opentui/core"
|
|
9
|
+
|
|
10
|
+
const renderer = await createCliRenderer({
|
|
11
|
+
// Rendering
|
|
12
|
+
targetFPS: 60, // Target frames per second (default: 60)
|
|
13
|
+
|
|
14
|
+
// Behavior
|
|
15
|
+
exitOnCtrlC: true, // Exit on Ctrl+C (default: true)
|
|
16
|
+
|
|
17
|
+
// Console overlay
|
|
18
|
+
consoleOptions: {
|
|
19
|
+
position: ConsolePosition.BOTTOM, // BOTTOM | TOP | LEFT | RIGHT
|
|
20
|
+
sizePercent: 30, // Percentage of screen
|
|
21
|
+
colorInfo: "#00FFFF",
|
|
22
|
+
colorWarn: "#FFFF00",
|
|
23
|
+
colorError: "#FF0000",
|
|
24
|
+
colorDebug: "#888888",
|
|
25
|
+
startInDebugMode: false,
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
// Lifecycle
|
|
29
|
+
onDestroy: () => {
|
|
30
|
+
// Cleanup callback
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Environment Variables
|
|
36
|
+
|
|
37
|
+
OpenTUI respects several environment variables for configuration and debugging.
|
|
38
|
+
|
|
39
|
+
### Debug & Development
|
|
40
|
+
|
|
41
|
+
| Variable | Type | Default | Description |
|
|
42
|
+
|----------|------|---------|-------------|
|
|
43
|
+
| `OTUI_DEBUG` | boolean | false | Enable debug mode, capture raw input |
|
|
44
|
+
| `OTUI_DEBUG_FFI` | boolean | false | Debug logging for FFI bindings |
|
|
45
|
+
| `OTUI_TRACE_FFI` | boolean | false | Tracing for FFI bindings |
|
|
46
|
+
| `OTUI_SHOW_STATS` | boolean | false | Show debug overlay at startup |
|
|
47
|
+
| `OTUI_DUMP_CAPTURES` | boolean | false | Dump captured output on exit |
|
|
48
|
+
|
|
49
|
+
### Console
|
|
50
|
+
|
|
51
|
+
| Variable | Type | Default | Description |
|
|
52
|
+
|----------|------|---------|-------------|
|
|
53
|
+
| `OTUI_USE_CONSOLE` | boolean | true | Enable console capture |
|
|
54
|
+
| `SHOW_CONSOLE` | boolean | false | Show console at startup |
|
|
55
|
+
|
|
56
|
+
### Rendering
|
|
57
|
+
|
|
58
|
+
| Variable | Type | Default | Description |
|
|
59
|
+
|----------|------|---------|-------------|
|
|
60
|
+
| `OTUI_NO_NATIVE_RENDER` | boolean | false | Disable ANSI output (for debugging) |
|
|
61
|
+
| `OTUI_USE_ALTERNATE_SCREEN` | boolean | true | Use alternate screen buffer |
|
|
62
|
+
| `OTUI_OVERRIDE_STDOUT` | boolean | true | Override stdout stream |
|
|
63
|
+
|
|
64
|
+
### Terminal Capabilities
|
|
65
|
+
|
|
66
|
+
| Variable | Type | Default | Description |
|
|
67
|
+
|----------|------|---------|-------------|
|
|
68
|
+
| `OPENTUI_NO_GRAPHICS` | boolean | false | Disable Kitty graphics protocol |
|
|
69
|
+
| `OPENTUI_FORCE_UNICODE` | boolean | false | Force Mode 2026 Unicode support |
|
|
70
|
+
| `OPENTUI_FORCE_WCWIDTH` | boolean | false | Use wcwidth for character width |
|
|
71
|
+
| `OPENTUI_FORCE_NOZWJ` | boolean | false | Disable ZWJ emoji joining |
|
|
72
|
+
| `OPENTUI_FORCE_EXPLICIT_WIDTH` | string | - | Force explicit width ("true"/"false") |
|
|
73
|
+
|
|
74
|
+
### Tree-sitter (Syntax Highlighting)
|
|
75
|
+
|
|
76
|
+
| Variable | Type | Default | Description |
|
|
77
|
+
|----------|------|---------|-------------|
|
|
78
|
+
| `OTUI_TS_STYLE_WARN` | boolean | false | Warn on missing syntax styles |
|
|
79
|
+
| `OTUI_TREE_SITTER_WORKER_PATH` | string | "" | Custom tree-sitter worker path |
|
|
80
|
+
|
|
81
|
+
### XDG Paths
|
|
82
|
+
|
|
83
|
+
| Variable | Type | Default | Description |
|
|
84
|
+
|----------|------|---------|-------------|
|
|
85
|
+
| `XDG_CONFIG_HOME` | string | "" | User config directory |
|
|
86
|
+
| `XDG_DATA_HOME` | string | "" | User data directory |
|
|
87
|
+
|
|
88
|
+
## Usage Examples
|
|
89
|
+
|
|
90
|
+
### Development Mode
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Show debug overlay and console
|
|
94
|
+
OTUI_SHOW_STATS=true SHOW_CONSOLE=true bun run src/index.ts
|
|
95
|
+
|
|
96
|
+
# Debug FFI issues
|
|
97
|
+
OTUI_DEBUG_FFI=true OTUI_TRACE_FFI=true bun run src/index.ts
|
|
98
|
+
|
|
99
|
+
# Disable native rendering for testing
|
|
100
|
+
OTUI_NO_NATIVE_RENDER=true bun run src/index.ts
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Terminal Compatibility
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Force wcwidth for problematic terminals
|
|
107
|
+
OPENTUI_FORCE_WCWIDTH=true bun run src/index.ts
|
|
108
|
+
|
|
109
|
+
# Disable graphics for SSH sessions
|
|
110
|
+
OPENTUI_NO_GRAPHICS=true bun run src/index.ts
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Project Setup
|
|
114
|
+
|
|
115
|
+
### package.json
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"name": "my-tui-app",
|
|
120
|
+
"type": "module",
|
|
121
|
+
"scripts": {
|
|
122
|
+
"start": "bun run src/index.ts",
|
|
123
|
+
"dev": "bun --watch run src/index.ts",
|
|
124
|
+
"test": "bun test"
|
|
125
|
+
},
|
|
126
|
+
"dependencies": {
|
|
127
|
+
"@opentui/core": "latest"
|
|
128
|
+
},
|
|
129
|
+
"devDependencies": {
|
|
130
|
+
"@types/bun": "latest",
|
|
131
|
+
"typescript": "latest"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### tsconfig.json
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"compilerOptions": {
|
|
141
|
+
"lib": ["ESNext"],
|
|
142
|
+
"target": "ESNext",
|
|
143
|
+
"module": "ESNext",
|
|
144
|
+
"moduleResolution": "bundler",
|
|
145
|
+
"strict": true,
|
|
146
|
+
"skipLibCheck": true,
|
|
147
|
+
"noEmit": true,
|
|
148
|
+
"types": ["bun-types"]
|
|
149
|
+
},
|
|
150
|
+
"include": ["src/**/*"]
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Building Native Code
|
|
155
|
+
|
|
156
|
+
Native code changes require rebuilding:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
# From repo root (if developing OpenTUI itself)
|
|
160
|
+
bun run build
|
|
161
|
+
|
|
162
|
+
# Zig is required for native compilation
|
|
163
|
+
# Install: https://ziglang.org/learn/getting-started/
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Note**: TypeScript changes do NOT require building. Bun runs TypeScript directly.
|