@valyrianjs/terminal 0.1.1 → 0.1.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.
Files changed (107) hide show
  1. package/README.md +105 -55
  2. package/dist/ansi.d.ts +20 -4
  3. package/dist/ansi.d.ts.map +1 -1
  4. package/dist/ansi.js +171 -47
  5. package/dist/ansi.js.map +1 -1
  6. package/dist/editor-state.d.ts +22 -0
  7. package/dist/editor-state.d.ts.map +1 -0
  8. package/dist/editor-state.js +110 -0
  9. package/dist/editor-state.js.map +1 -0
  10. package/dist/events.d.ts +1 -4
  11. package/dist/events.d.ts.map +1 -1
  12. package/dist/events.js +15 -38
  13. package/dist/events.js.map +1 -1
  14. package/dist/index.d.ts +4 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +3 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/keymap.d.ts +7 -0
  19. package/dist/keymap.d.ts.map +1 -0
  20. package/dist/keymap.js +133 -0
  21. package/dist/keymap.js.map +1 -0
  22. package/dist/layout.d.ts +10 -1
  23. package/dist/layout.d.ts.map +1 -1
  24. package/dist/layout.js +97 -7
  25. package/dist/layout.js.map +1 -1
  26. package/dist/mouse.d.ts +1 -0
  27. package/dist/mouse.d.ts.map +1 -1
  28. package/dist/mouse.js +24 -1
  29. package/dist/mouse.js.map +1 -1
  30. package/dist/output-writer.d.ts +9 -0
  31. package/dist/output-writer.d.ts.map +1 -0
  32. package/dist/output-writer.js +79 -0
  33. package/dist/output-writer.js.map +1 -0
  34. package/dist/paste.d.ts +7 -0
  35. package/dist/paste.d.ts.map +1 -0
  36. package/dist/paste.js +18 -0
  37. package/dist/paste.js.map +1 -0
  38. package/dist/primitives.d.ts +8 -1
  39. package/dist/primitives.d.ts.map +1 -1
  40. package/dist/primitives.js +9 -1
  41. package/dist/primitives.js.map +1 -1
  42. package/dist/render.d.ts +8 -3
  43. package/dist/render.d.ts.map +1 -1
  44. package/dist/render.js +840 -67
  45. package/dist/render.js.map +1 -1
  46. package/dist/runtime.d.ts +29 -0
  47. package/dist/runtime.d.ts.map +1 -0
  48. package/dist/runtime.js +215 -0
  49. package/dist/runtime.js.map +1 -0
  50. package/dist/scheduler.d.ts +8 -0
  51. package/dist/scheduler.d.ts.map +1 -0
  52. package/dist/scheduler.js +24 -0
  53. package/dist/scheduler.js.map +1 -0
  54. package/dist/session.d.ts.map +1 -1
  55. package/dist/session.js +729 -199
  56. package/dist/session.js.map +1 -1
  57. package/dist/stream-log.d.ts +40 -0
  58. package/dist/stream-log.d.ts.map +1 -0
  59. package/dist/stream-log.js +73 -0
  60. package/dist/stream-log.js.map +1 -0
  61. package/dist/text.d.ts +3 -0
  62. package/dist/text.d.ts.map +1 -0
  63. package/dist/text.js +19 -0
  64. package/dist/text.js.map +1 -0
  65. package/dist/theme.d.ts +7 -0
  66. package/dist/theme.d.ts.map +1 -0
  67. package/dist/theme.js +254 -0
  68. package/dist/theme.js.map +1 -0
  69. package/dist/tree.d.ts +2 -0
  70. package/dist/tree.d.ts.map +1 -1
  71. package/dist/tree.js +42 -1
  72. package/dist/tree.js.map +1 -1
  73. package/dist/types.d.ts +183 -18
  74. package/dist/types.d.ts.map +1 -1
  75. package/docs/api-reference.md +302 -136
  76. package/docs/assets/quick-note.svg +13 -0
  77. package/docs/cookbook.md +296 -201
  78. package/docs/core-concepts.md +143 -55
  79. package/docs/getting-started.md +209 -90
  80. package/docs/interaction-model.md +86 -52
  81. package/docs/primitive-gallery.md +365 -0
  82. package/docs/session-runtime.md +131 -362
  83. package/docs/valyrian-modules.md +3196 -0
  84. package/llms-full.txt +5357 -0
  85. package/package.json +21 -8
  86. package/src/ansi.ts +269 -0
  87. package/src/clipboard.ts +76 -0
  88. package/src/editor-state.ts +162 -0
  89. package/src/events.ts +163 -0
  90. package/src/index.ts +92 -0
  91. package/src/keymap.ts +151 -0
  92. package/src/layout.ts +282 -0
  93. package/src/mouse.ts +68 -0
  94. package/src/output-writer.ts +93 -0
  95. package/src/paste.ts +23 -0
  96. package/src/primitives.ts +52 -0
  97. package/src/render.ts +1107 -0
  98. package/src/runtime.ts +273 -0
  99. package/src/scheduler.ts +33 -0
  100. package/src/session.ts +1260 -0
  101. package/src/stream-log.ts +96 -0
  102. package/src/text.ts +20 -0
  103. package/src/theme.ts +263 -0
  104. package/src/tree.ts +169 -0
  105. package/src/types.ts +523 -0
  106. package/tsconfig.json +4 -7
  107. package/docs/local-demo.md +0 -28
@@ -1,191 +1,343 @@
1
1
  # API Reference
2
2
 
3
- Reference for the actual public surface published by `valyrianjs-terminal`.
3
+ Reference for the public surface published by `@valyrianjs/terminal`. For a guided first project, start with [Getting Started](./getting-started.md). For practical primitive selection, use [Primitive Gallery](./primitive-gallery.md).
4
4
 
5
- ## Published Entrypoints
5
+ ## Published entrypoints
6
6
 
7
- ### `valyrianjs-terminal`
7
+ ### `@valyrianjs/terminal`
8
8
 
9
- Main entrypoint. At a high level, it exposes:
9
+ Main entrypoint for terminal primitives, rendering, sessions, props, payloads, and types.
10
10
 
11
- - `renderTerminal()`
12
- - `mountTerminal()`
13
- - primitives `Screen`, `Box`, `View`, `Text`, `Input`, `Button`, `ScrollView`, `List`, `Table`, `Row`, `Td`
14
- - prop, event, node, and session types
11
+ Common imports:
15
12
 
16
- ### `valyrianjs-terminal/render`
13
+ ```tsx
14
+ import { Screen, Text, mountTerminal, renderTerminal } from "@valyrianjs/terminal";
15
+ ```
17
16
 
18
- Published subpath for lower-level rendering utilities.
17
+ ### `@valyrianjs/terminal/render`
18
+
19
+ Rendering-only subpath for lower-level rendering utilities:
19
20
 
20
21
  - `renderTerminal(input): string`
21
22
  - `renderTerminalNode(node): string`
22
23
  - `renderTerminalFrame(node): TerminalFrame`
23
24
 
24
- Use this subpath when you only need to transform terminal nodes into text or a `TerminalFrame`, without mounting an interactive session.
25
+ Use this subpath for rendering-focused integrations that produce output without mounting an interactive session.
25
26
 
26
- ## Main Functions
27
+ ## Root exports overview
27
28
 
28
- ### `renderTerminal(input): string`
29
+ The root entrypoint exports the public primitives (`Screen`, `Box`, `View`, `Pane`, `Split`, `Fixed`, `Overlay`, `FocusScope`, `Text`, `Input`, `Editor`, `Button`, `List`, `ScrollView`, `LogView`, `Table`, `Row`, and `Td`), the main functions `renderTerminal()` and `mountTerminal()`, public prop and payload types, keymap helpers, and theme helpers.
29
30
 
30
- Resolves the provided root and returns terminal output as plain text.
31
+ ## Main functions
31
32
 
32
- Use cases supported by the current implementation:
33
+ ### `renderTerminal(input): string`
33
34
 
34
- - snapshots and tests
35
- - layout validation without `stdin` or `stdout`
36
- - content inspection in non-interactive mode
35
+ Resolves the provided terminal tree and returns plain text.
37
36
 
38
- Notes:
37
+ Use it for:
39
38
 
40
- - concatenates root nodes with newlines
41
- - removes only trailing whitespace with `trimEnd()`
42
- - does not create listeners or interactive state
39
+ - snapshots
40
+ - static examples
41
+ - non-interactive command output
42
+ - layout checks without session state
43
43
 
44
44
  ### `mountTerminal(input, options?): TerminalSession`
45
45
 
46
- Mounts an interactive session on the terminal tree and returns a `TerminalSession`.
46
+ Creates an interactive session around a terminal tree.
47
47
 
48
- High-level behavior:
48
+ The session can:
49
49
 
50
- - resolves the current tree and re-renders it with `session.update()`
51
- - manages focus by `id`
52
- - handles keyboard, mouse, selection, and clipboard interaction
53
- - can write to `stdout` automatically when provided
54
- - if it receives `stdin`, it enables raw mode on mount and restores it in `destroy()`
50
+ - rerender with `update()`
51
+ - preserve and move focus
52
+ - dispatch keyboard input
53
+ - handle mouse and coordinate interaction
54
+ - use clipboard integration
55
+ - write ANSI diffs to `stdout` in app runtime
56
+ - clean up connected streams with `destroy()`
55
57
 
56
58
  ## `TerminalMountOptions`
57
59
 
58
- - `ansi?: boolean` - if `stdout` is present, writes ANSI diffs instead of plain text
59
- - `clipboard?: TerminalClipboardAdapter | false` - custom adapter or disables the system clipboard
60
- - `stdin?` - stream with `on("data")`; `off()`, `removeListener()`, `setRawMode()`, `resume()`, and `pause()` are optional
61
- - `stdout?` - writer with `write(chunk: string)`
60
+ - `runtime?: "app" | "headless"` - selects real app output or scriptable plain output. Omitted runtime becomes app mode for interactive TTY hosts and headless in non-TTY/CI contexts.
61
+ - `alternateScreen?: boolean` - enters alternate screen mode and restores it on destroy by default. Real interactive app mode enables it by default unless overridden.
62
+ - `hideCursor?: boolean` - hides the terminal cursor and restores it on destroy by default. Real interactive app mode enables it by default unless overridden.
63
+ - `restoreOnDestroy?: boolean` - controls restore behavior for cursor and alternate screen state.
64
+ - `clipboard?: TerminalClipboardAdapter | false` - custom clipboard adapter or disabled external clipboard integration.
65
+ - `cols?: number` - initial terminal width in columns.
66
+ - `rows?: number` - initial terminal height in rows.
67
+ - `stdin?` - input stream with `on("data")`; cleanup and raw-mode methods are optional.
68
+ - `stdout?` - output stream with `write(chunk)`; optional dimensions, resize events, and drain events are used when supported.
69
+ - `theme?` - terminal theme for semantic style spans.
70
+ - `keymap?` - custom key bindings for built-in terminal interaction behavior.
71
+
72
+ If no explicit dimensions or stream dimensions are available, sessions default to `80x24`. Dimensions must be positive integers.
73
+
74
+ `hideCursor` and `restoreOnDestroy` describe cursor and terminal-restore intent for sessions connected to compatible hosts. Cursor restore follows the connected terminal and stream capabilities. Run `bun examples/docs/cursor.tsx`, type text, press `C`, and quit with `Ctrl+C`; or open [`examples/docs/cursor.tsx`](../examples/docs/cursor.tsx).
75
+
76
+ ## Keymap helpers
77
+
78
+ - `defaultTerminalKeyBindings` - built-in key bindings for focus traversal, editing, lists, buttons, and scroll views.
79
+ - `createTerminalKeyBindings(bindings?)` - returns a normalized binding list that can extend or replace default behavior.
80
+ - `createResolvedTerminalKeymap(options?)` - creates a keymap object used by sessions.
81
+ - `resolveTerminalKeyBinding(key, context, keymap)` - resolves a normalized key against a context.
82
+ - `validateTerminalKeyBindings(bindings)` - validates key binding shape and rejects ambiguous entries.
83
+
84
+ Use `keymap` in `TerminalMountOptions` when an app needs custom keyboard behavior while keeping predictable focus and primitive events.
85
+
86
+ ## Theme helpers
87
+
88
+ - `defaultTerminalTheme` - bundled app-like recipes for common controls.
89
+ - `highContrastTerminalTheme` - alternate recipes with stronger contrast.
90
+ - `mergeTerminalTheme(base, override)` - combines theme recipes and span tokens.
91
+ - `resolveTerminalStyle(style, theme?)` - resolves dot path recipes or inline style objects.
92
+ - `resolveTerminalStyleToken(kind, theme?)` - resolves semantic span tokens for ANSI/plain serialization.
93
+
94
+ Theme recipes belong in `theme.styles`. Use `color`, `background`, padding, and border values with hex colors for normal app styling.
95
+
96
+ ## Visual style system
97
+
98
+ `theme.styles` stores named style recipes. A recipe may define color, background, padding, border, and nested visual-state recipes. The bundled default theme includes app-like recipes for core controls such as `button.base`, `button.focus`, `input.base`, `input.focus`, `input.selection`, `list.base`, `list.current`, `list.selected`, `list.hover`, and `list.empty`. Components resolve recipes by dot path, so `style="panel.queue"` reads `theme.styles.panel.queue`. Inline style objects work too when the style belongs to one component instance.
99
+
100
+ Use `style`, `styles`, and `state` for normal component styling:
101
+
102
+ - `style` sets the base recipe or inline style for the component frame.
103
+ - `styles` maps visual states to dot path recipes or inline style objects.
104
+ - `state` declares app-owned states such as `loading`, `warning`, `success`, `muted`, `expanded`, or `dropTarget`.
105
+
106
+ Renderer-owned states come from the runtime when the renderer has the fact itself. Focus, hover, selection, current rows, and pointer capture fall in this group when the primitive supports them. App-owned state should describe product state that the app already knows. Do not mark a ready button as `loading` or an editable field as `readonly`; that teaches a lie to the UI and then the UI repeats it with confidence.
107
+
108
+ Precedence: the renderer starts with the component default recipe, applies the instance `style`, then applies `styles` entries for current states in stable visual-state order. Geometry fields such as supported padding and border come from the component default plus the instance `style` so layout, hitboxes, and cursors stay stable across focus, hover, and pressed state changes. State styles affect the rendered spans after layout; later current states override earlier visual fields when they set the same property. Inline style objects and dot path recipes use the same merge path after resolution.
109
+
110
+ Renderer notes:
111
+
112
+ - Raw ANSI escape control is not the normal public styling API. Use semantic styles and let `ansiOutput()` serialize frames.
113
+ - Layout margin is not supported; use padding, `gap`, `Fixed`, `Split`, or explicit text spacing.
114
+ - The renderer owns terminal frame spans, clipping, focus, and selection; the app owns business state and labels.
115
+
116
+ Run `bun examples/docs/style-system.tsx`, try `Tab`, `Enter`, and `W`, and quit with `Ctrl+C`; or open [`examples/docs/style-system.tsx`](../examples/docs/style-system.tsx). Run `bun examples/docs/theme-colors.tsx`, press `Tab`, and quit with `Ctrl+C`; or open [`examples/docs/theme-colors.tsx`](../examples/docs/theme-colors.tsx).
117
+
118
+ ### TerminalStyleSpan
119
+
120
+ `TerminalStyleSpan` is a low-level frame API for renderer integrations and frame serialization. It describes a styled range in a rendered frame and may carry `kind`, coordinates, and `style?` when the renderer resolves an inline style object. App components get their everyday styling surface from semantic styles.
121
+
122
+ Use `style`, `styles`, and `state` for component styling. Use `TerminalStyleSpan` when a low-level frame integration needs styled ranges after render.
123
+
124
+ ### Advanced: span serialization tokens
125
+
126
+ `ansiOpen`, `ansiClose`, `plainPrefix`, and `plainSuffix` are low-level fields for trusted renderer integrations that already own frame spans and need exact serialization behavior. Application components get their styling API from semantic styles.
127
+
128
+ Apps should prefer `theme.styles`, `style`, `styles`, `state`, `color`, `background`, and hex colors. Those fields keep styling semantic, portable, and safe for both `output()` and `ansiOutput()`. When a token defines `color`, `background`, or `style`, ANSI serialization uses the resolved style fields before raw ANSI fallback tokens.
129
+
130
+ Token behavior:
131
+
132
+ - `ansiOpen` writes a raw ANSI opening sequence around the span in ANSI output when no `color`, `background`, or `style` field supplies a safer style.
133
+ - `ansiClose` writes the matching raw ANSI close sequence in ANSI output for the same low-level case.
134
+ - `plainPrefix` adds text before the span only in plain output.
135
+ - `plainSuffix` adds text after the span only in plain output.
136
+
137
+ Prefer semantic styles first: `theme.styles`, `style`, `styles`, `state`, hex `color`, and `background` keep output portable across plain and ANSI render paths. Use raw ANSI tokens for trusted low-level integrations that own frame serialization. Keep token input trusted, pair open and close tokens exactly, verify both `output()` and `ansiOutput()`, and document the integration reason when semantic hex style does not cover the serialization requirement.
138
+
139
+ ## Layout primitives
140
+
141
+ Use [Primitive Gallery](./primitive-gallery.md) for practical composition examples, including [`examples/docs/primitive-layout-shell.tsx`](../examples/docs/primitive-layout-shell.tsx), [`examples/docs/primitive-input-workbench.tsx`](../examples/docs/primitive-input-workbench.tsx), [`examples/docs/primitive-data-explorer.tsx`](../examples/docs/primitive-data-explorer.tsx), [`examples/docs/primitive-activity-console.tsx`](../examples/docs/primitive-activity-console.tsx), and [`examples/docs/primitive-command-panel.tsx`](../examples/docs/primitive-command-panel.tsx). Run them with `bun examples/docs/primitive-layout-shell.tsx`, `bun examples/docs/primitive-input-workbench.tsx`, `bun examples/docs/primitive-data-explorer.tsx`, `bun examples/docs/primitive-activity-console.tsx`, or `bun examples/docs/primitive-command-panel.tsx`; quit with `Ctrl+C`. Use API Reference for prop-level details.
62
142
 
63
- ## Layout Primitives
64
143
 
65
144
  ### `Screen`
66
145
 
67
- `TerminalScreenProps` props:
146
+ Props:
68
147
 
69
148
  - `title?: string`
70
149
 
71
- Role: root container. If `title` exists, it renders as the first line of the frame.
150
+ Root container. If `title` is present, it renders as the first line. In a mounted session or render call with dimensions, `Screen` passes the available viewport context to children.
72
151
 
73
152
  ### `Box`
74
153
 
75
- `TerminalBoxProps` props:
154
+ Props:
76
155
 
77
156
  - `direction?: "row" | "column"`
78
157
  - `gap?: number`
79
- - `padding?: number`
80
- - `border?: boolean`
158
+ - `padding?: number | { x?: number; y?: number; top?: number; right?: number; bottom?: number; left?: number }`
159
+ - `style?: string | TerminalStyleDefinition`
160
+ - `styles?: Partial<Record<TerminalVisualState, string | TerminalStyleDefinition>>`
161
+ - `state?: TerminalVisualState | TerminalVisualState[]`
81
162
  - `width?: number`
82
163
  - `height?: number`
164
+ - `fill?: boolean`
83
165
  - `id?: string`
84
166
  - `focusable?: boolean`
85
167
 
86
- Role: layout container. In `row`, it composes horizontally; in `column`, vertically.
168
+ Layout container. `Box`, `View`, and `Pane` behave like block elements in a sized context: they use available width by default and keep content height by default, so stacked containers do not all become full-height. Numeric dimensions constrain the final frame and explicit `width` or `height` wins over context defaults. Use `fill` when a surface should consume the full available height as well as width. Put background fill, border, and padding in `style` or a `theme.styles` recipe. Margin is not supported; compose spacing with layout, padding, and explicit text when needed.
87
169
 
88
170
  ### `View`
89
171
 
90
- `TerminalViewProps` props:
172
+ Props: layout props from `Box`, plus `role?: string`.
91
173
 
92
- - all layout props from `Box`
93
- - `role?: string`
174
+ Semantic layout container with the same sizing behavior as `Box`.
94
175
 
95
- Role: semantic container equivalent to `terminal-view`.
176
+ ### `Pane`
96
177
 
97
- ### `Text`
178
+ Props: layout props from `Box`.
98
179
 
99
- `TerminalTextProps` props:
180
+ Named layout boundary for composing terminal regions.
100
181
 
101
- - `value?: any`
182
+ ### `Split`
183
+
184
+ Props:
185
+
186
+ - `direction?: "row" | "column"`
187
+ - `width?: number`
188
+ - `height?: number`
189
+ - `fill?: boolean`
190
+ - `sizes?: Array<number | `${number}%` | `${number}fr`>`
191
+ - `breakpoints?: Array<{ maxCols?: number; maxRows?: number; direction?: "row" | "column"; sizes?: TerminalSplitSize[]; gap?: number }>`
192
+ - `gap?: number`
193
+ - `id?: string`
194
+ - `focusable?: boolean`
195
+
196
+ Split layout. Split uses the available render area when width and height are omitted inside a sized context. In `row`, it divides width; in `column`, it divides height. `sizes` may mix absolute numbers, percentages, and `fr` units. Percentages and fractions use the available axis after gaps. Rounding is deterministic: floor the ideal sizes, then give remaining cells to the largest fractional remainders with index order as the tie breaker. Breakpoints are local to the resolved split width and height, and the first matching breakpoint wins. Run `bun examples/docs/responsive-split.tsx`, resize the terminal to change the layout, and quit with `Ctrl+C`; or open [`examples/docs/responsive-split.tsx`](../examples/docs/responsive-split.tsx).
197
+
198
+ ## Visual states
199
+
200
+ State families:
201
+
202
+ | Family | States |
203
+ | --- | --- |
204
+ | Common | `focus`, `hover`, `disabled`, `loading` |
205
+ | Activation/controls | `pressed`, `checked`, `unchecked`, `indeterminate` |
206
+ | Selection/navigation | `selected`, `current`, `expanded`, `collapsed` |
207
+ | Entry/text | `invalid`, `valid`, `readonly`, `placeholder`, `selection`, `editing`, `submitted` |
208
+ | Data/content | `empty`, `error`, `warning`, `success`, `muted` |
209
+ | Pointer/capture/composition | `dragging`, `dropTarget`, `capturing` |
210
+
211
+ Buttons, inputs, editors, lists, tables, panes, boxes, overlays, scroll views, log views, and text can use `style`, `styles`, and `state` where the style affects their rendered frame. Use renderer-owned states such as focus or selection when the component knows them, and use `state` for app-owned statuses such as loading, warning, success, dragging, or drop target.
212
+
213
+ Shared visual props for styled primitives:
214
+
215
+ - `style?: string | TerminalStyleDefinition` - base style recipe or inline style.
216
+ - `styles?: Partial<Record<TerminalVisualState, string | TerminalStyleDefinition>>` - visual-state style map.
217
+ - `state?: TerminalVisualState | TerminalVisualState[]` - app-owned visual state or states.
102
218
 
103
- Role: renders `value` or the concatenated text from its children. If there are line breaks, they are preserved.
219
+ ### `Fixed`
104
220
 
105
- ### `Table`
221
+ Props:
106
222
 
107
- `TerminalTableProps` props:
223
+ - `position: "top" | "bottom" | "left" | "right"`
224
+ - `size: number`
108
225
 
109
- - `v-for?: any[]`
226
+ Direct-child marker consumed by `Screen` and `Pane` to reserve stable rows or columns.
110
227
 
111
- Role: composes rows and automatically calculates the maximum width for each column.
228
+ ### `Overlay`
112
229
 
113
- ### `Row`
230
+ Props:
114
231
 
115
- `TerminalRowProps` props:
232
+ - `x: number`
233
+ - `y: number`
234
+ - `width: number`
235
+ - `height: number`
236
+ - shared visual props: `style`, `styles`, `state`
237
+ - `trapFocus?: boolean`
238
+ - `id?: string`
239
+ - `focusable?: boolean`
240
+
241
+ Draws a clipped region over the current frame. Use it for popovers and lightweight dialog-like surfaces. `trapFocus` keeps traversal inside the overlay while it is active.
242
+
243
+ Overlay keeps focused surfaces clipped and positioned; app routing and pane movement stay in your app layer.
244
+
245
+ ### `FocusScope`
246
+
247
+ Props:
116
248
 
117
- - `separator?: string`
249
+ - `active?: boolean`
118
250
 
119
- Role: joins cells using `separator` or `" | "` by default.
251
+ Bounds sequential focus traversal to descendants when focus is already inside the scope.
120
252
 
121
- ### `Td`
253
+ ### `Text`
254
+
255
+ Props:
122
256
 
123
- `TerminalTdProps` props:
257
+ - `value?: any`
258
+ - shared visual props: `style`, `styles`, `state`
124
259
 
125
- - `padding?: number`
260
+ Renders `value` or child text. Line breaks are preserved.
126
261
 
127
- Role: wraps cell content and applies internal padding when defined.
262
+ ### `Table`, `Row`, and `Td`
128
263
 
129
- ## Interactive Primitives
264
+ `Table` composes rows and calculates column widths. `Row` joins cells with `separator?: string`. `Td` supports `padding?: number` and shared visual props: `style`, `styles`, `state`.
130
265
 
131
- All of them depend on `id` to fully participate in focus, hitboxes, coordinate lookup, and several `TerminalSession` helpers.
266
+ ## Interactive primitives
132
267
 
133
268
  ### `Input`
134
269
 
135
- `TerminalInputProps` props:
270
+ Props:
136
271
 
137
272
  - `id?: string`
138
273
  - `focusable?: boolean`
139
274
  - `value?: string`
140
275
  - `placeholder?: string`
276
+ - shared visual props: `style`, `styles`, `state`
141
277
  - `onchange?(event)`
142
278
  - `oninput?(event)`
143
279
  - `onsubmit?(event)`
144
- - `onChangeText?(value)`
145
280
 
146
- Current interaction support:
147
-
148
- - cursor movement and text selection
149
- - `LEFT`, `RIGHT`, `SHIFT_LEFT`, `SHIFT_RIGHT`
150
- - `ALT_LEFT`, `ALT_RIGHT`, `HOME`, `END`
151
- - `CTRL_A`, `CTRL_C`, `CTRL_X`, `CTRL_V`
152
- - `BACKSPACE`, `DELETE`, character input, and `ENTER`
153
-
154
- Important payloads:
281
+ Payloads:
155
282
 
156
283
  - `TerminalInputChangeEventPayload` - `{ type: "change" | "input", id, value }`
157
284
  - `TerminalInputSubmitEventPayload` - `{ type: "submit", id, value }`
158
285
 
286
+ Supports single-line editing, cursor movement, selection, copy/cut/paste, deletion, and submit.
287
+
288
+ ### `Editor`
289
+
290
+ Props:
291
+
292
+ - `id?: string`
293
+ - `focusable?: boolean`
294
+ - `value?: string`
295
+ - `placeholder?: string`
296
+ - `height?: number`
297
+ - shared visual props: `style`, `styles`, `state`
298
+ - `onchange?(event)`
299
+ - `oninput?(event)`
300
+ - `onsubmit?(event)`
301
+ - `oncancel?(event)`
302
+
303
+ Payloads:
304
+
305
+ - `TerminalEditorChangeEventPayload` - `{ type: "change" | "input", id, value }`
306
+ - `TerminalEditorSubmitEventPayload` - `{ type: "submit", id, value }`
307
+ - `TerminalEditorCancelEventPayload` - `{ type: "cancel", id, value }`
308
+
309
+ Supports multiline editing, submit, cancel, cursor movement, paste, and deletion. Cursor columns use JavaScript string columns rather than a complete terminal-width model.
310
+
159
311
  ### `Button`
160
312
 
161
- `TerminalButtonProps` props:
313
+ Props:
162
314
 
163
315
  - `id?: string`
164
316
  - `focusable?: boolean`
165
317
  - `label?: string`
318
+ - shared visual props: `style`, `styles`, `state`
166
319
  - `onpress?(event)`
167
320
  - `onclick?(event)`
168
321
  - `action?(event)`
169
- - `onPress?(event)`
170
-
171
- Current activation paths:
172
322
 
173
- - `session.click(id?)`
174
- - `session.clickAt(x, y)`
175
- - `dispatchKey("ENTER")` or `dispatchKey("SPACE")` when focus is on the button
176
-
177
- Important payload:
323
+ Payload:
178
324
 
179
325
  - `TerminalButtonPressEventPayload` - `{ type: "press" | "click", id }`
180
326
 
327
+ Activation paths include focused `ENTER`, focused `SPACE`, `session.click(id)`, and `session.clickAt(x, y)`.
328
+
181
329
  ### `List<T>`
182
330
 
183
- `TerminalListProps<T>` props:
331
+ Props:
184
332
 
185
333
  - `id?: string`
186
334
  - `focusable?: boolean`
187
335
  - `pointerCapture?: boolean`
188
336
  - `items?: T[]`
337
+ - `virtualized?: boolean`
338
+ - `itemHeight?: 1`
339
+ - `overscan?: number`
340
+ - shared visual props: `style`, `styles`, `state`
189
341
  - `renderItem?(item, index): string`
190
342
  - `onchange?(event)`
191
343
  - `onpress?(event)`
@@ -195,25 +347,20 @@ Important payload:
195
347
  - `oncapturestart?(event)`
196
348
  - `oncaptureend?(event)`
197
349
 
198
- Current interaction:
199
-
200
- - `UP` and `LEFT` move selection up
201
- - `DOWN` and `RIGHT` move selection down
202
- - `ENTER` triggers `onpress`
203
- - mouse hover exposes row, index, and value
204
-
205
- Important payloads:
350
+ Payloads:
206
351
 
207
352
  - `TerminalListChangeEventPayload<T>` - `{ type: "change", id, index, value }`
208
353
  - `TerminalListPressEventPayload<T>` - `{ type: "press", id, index, value }`
209
354
  - `TerminalListPointerEventPayload<T>` - `{ type: "hover" | "rowenter" | "rowleave", id, row, index, value, x, y }`
210
355
  - `TerminalCaptureEventPayload` - `{ type: "capturestart" | "captureend", id, source, row, x, y }`
211
356
 
357
+ Supports selection, activation, hover payloads, optional virtualization, and pointer capture.
358
+
212
359
  ### `ScrollView`
213
360
 
214
- `TerminalScrollViewProps` props:
361
+ Props:
215
362
 
216
- - layout props (`direction`, `gap`, `padding`, `border`, `width`, `height`, `id`, `focusable`)
363
+ - layout props: `direction`, `gap`, `padding`, `width`, `height`, `fill`, `id`, `focusable`, `style`, `styles`, `state`
217
364
  - `pointerCapture?: boolean`
218
365
  - `highlightRows?: number[]`
219
366
  - `onhover?(event)`
@@ -222,52 +369,71 @@ Important payloads:
222
369
  - `oncapturestart?(event)`
223
370
  - `oncaptureend?(event)`
224
371
 
225
- Current interaction:
226
-
227
- - `UP` and `DOWN` adjust the vertical offset when it has focus
228
- - rendering clips visible content based on `height`
229
- - `highlightRows` marks specific visible rows
230
- - mouse hover exposes the visible row and rendered text
231
-
232
- Important payloads:
372
+ Payloads:
233
373
 
234
374
  - `TerminalScrollPointerEventPayload` - `{ type: "hover" | "rowenter" | "rowleave", id, row, value, x, y }`
235
375
  - `TerminalCaptureEventPayload` - `{ type: "capturestart" | "captureend", id, source, row, x, y }`
236
376
 
377
+ Clips vertical content and supports keyboard scrolling, highlighted rows, hover payloads, and pointer capture.
378
+
379
+ ### `LogView`
380
+
381
+ Props:
382
+
383
+ - layout props: `direction`, `gap`, `padding`, `width`, `height`, `fill`, `id`, `focusable`, `style`, `styles`, `state`
384
+ - `entries?: readonly TerminalLogViewEntry[]`
385
+ - `followTail?: boolean`
386
+ - `emptyText?: string`
387
+ - `renderEntry?(entry, index): string`
388
+
389
+ Entry shape:
390
+
391
+ - `TerminalLogViewEntry` - `{ id: string, content: string }`
392
+
393
+ Renders append-only logs and transcript-like panes. `followTail` keeps the visible frame at the bottom of the rendered entries. Use `followTail` as the `LogView` option for bottom-pinned transcript views while log storage and export stay in the app layer.
394
+
395
+ ## Render subpath exports
396
+
397
+ The `@valyrianjs/terminal/render` subpath exports:
398
+
399
+ - `renderTerminal(input): string`
400
+ - `renderTerminalNode(node): string`
401
+ - `renderTerminalFrame(node): TerminalFrame`
402
+
403
+ These functions are useful for render-only integrations that should not import session runtime helpers.
404
+
237
405
  ## `TerminalSession`
238
406
 
239
- Public contract for the interactive session.
240
-
241
- - `update(): string` - resolves the root again and returns the current plain-text output
242
- - `output(): string` - returns the last rendered plain frame
243
- - `ansiOutput(): string` - returns the current frame serialized as ANSI
244
- - `tree(): TerminalNode[]` - exposes the current resolved terminal tree
245
- - `focus(id: string): boolean` - focuses an interactive node by `id`
246
- - `focusAt(x: number, y: number): boolean` - focuses by computed hitbox
247
- - `focusNext(): boolean` - moves focus forward in render order
248
- - `focusPrev(): boolean` - moves focus backward in render order
249
- - `dispatchKey(key: string): string` - injects a normalized key and returns the current output
250
- - `click(id?: string): string` - activates the focused button or a specific one by `id`
251
- - `clickAt(x: number, y: number): string` - activates or focuses using coordinates
252
- - `clipboard(): string` - returns the last clipboard value known by the session
253
- - `setClipboard(value: string): string` - updates the internal clipboard and, if present, the adapter
254
- - `selectAll(): string` - selects all content in the focused `Input`
255
- - `destroy(): void` - removes `stdin` listeners, exits raw mode, and pauses the stream when applicable
256
-
257
- ## Relevant Utility Types
258
-
259
- - `TerminalMountOptions` - options for mounting the session
260
- - `TerminalClipboardAdapter` - minimum contract for integrating an external clipboard
261
- - `TerminalFrame` - rendered frame with `lines`, `hitboxes`, `cursor`, and `spans`
262
- - `TerminalHitbox` - computed interactive region for focus and coordinate-based clicks
263
- - `TerminalStyleSpan` - visual marker such as `selection`, `focus`, or `highlight`
264
- - `TerminalNode`, `TerminalElementNode`, `TerminalTextNode` - resolved terminal tree
265
- - `TerminalLayoutProps` - shared base for `Box`, `View`, and `ScrollView`
266
- - `TerminalFocusableProps` - `id` and `focusable`
267
- - `TerminalPointerCaptureProps` - `pointerCapture` for lists and scroll views
268
- - `InputInteractionState` - cursor position and selection anchor
269
- - `TerminalChangeEventPayload` - union of `Input` and `List` change events
270
- - `TerminalPressEventPayload` - union of `Button` and `List` press events
271
- - `TerminalPointerCoordinates` - optional `x` and `y` coordinates in mouse payloads
272
- - `TerminalMouseEventType` - `"hover" | "rowenter" | "rowleave"`
273
- - `TerminalPointerSource` - `"press" | "drag" | "release"`
407
+ - `size(): TerminalSize` - returns `{ cols, rows }`.
408
+ - `resize(cols: number, rows: number): void` - validates and stores a new size, then rerenders.
409
+ - `update(): string` - rerenders and returns plain text.
410
+ - `output(): string` - returns the current plain-text frame.
411
+ - `ansiOutput(): string` - returns the current ANSI frame.
412
+ - `tree(): TerminalNode[]` - returns the current resolved terminal tree.
413
+ - `focus(id: string): boolean` - focuses a node by id.
414
+ - `focusAt(x: number, y: number): boolean` - focuses by coordinates.
415
+ - `focusNext(): boolean` - moves focus forward.
416
+ - `focusPrev(): boolean` - moves focus backward.
417
+ - `dispatchKey(key: string): string` - dispatches a normalized key and returns plain text.
418
+ - `click(id?: string): string` - activates the focused button or a button by id.
419
+ - `clickAt(x: number, y: number): string` - activates or focuses by coordinates.
420
+ - `clipboard(): string` - returns the session clipboard buffer.
421
+ - `setClipboard(value: string): string` - updates the session clipboard buffer and adapter when present.
422
+ - `selectAll(): string` - selects all content in the focused `Input`.
423
+ - `destroy(): void` - removes listeners and restores supported terminal state.
424
+
425
+ ## Package scope
426
+
427
+ - Use the package for terminal primitives, rendering, sessions, focus, input, and output.
428
+ - Compose command-palette surfaces with `Overlay`, `FocusScope`, `Input`, `List`, and `Button`.
429
+ - Keep log storage, export, routing, and business rules in your app layer.
430
+ - Use semantic text and styles for rendered content; reserve terminal escape control for documented integration paths.
431
+ - Host features such as resize, mouse input, and modified keys follow the terminal/runtime environment.
432
+
433
+ ## Related docs
434
+
435
+ - [Getting Started](./getting-started.md) for the first project.
436
+ - [Core Concepts](./core-concepts.md) for the mental model.
437
+ - [Cookbook](./cookbook.md) for practical recipes.
438
+ - [Interaction Model](./interaction-model.md) for behavior by primitive.
439
+ - [Session Runtime](./session-runtime.md) for host integration.
@@ -0,0 +1,13 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="640" height="220" viewBox="0 0 640 220" role="img" aria-labelledby="title desc">
2
+ <title id="title">Quick note terminal result</title>
3
+ <desc id="desc">A terminal window with a quick note app, an input hint, and Ctrl+C exit guidance.</desc>
4
+ <rect width="640" height="220" rx="18" fill="#0d1117"/>
5
+ <rect x="24" y="24" width="592" height="172" rx="12" fill="#161b22" stroke="#30363d"/>
6
+ <circle cx="52" cy="52" r="6" fill="#ff7b72"/>
7
+ <circle cx="72" cy="52" r="6" fill="#f2cc60"/>
8
+ <circle cx="92" cy="52" r="6" fill="#56d364"/>
9
+ <text x="44" y="92" fill="#e6edf3" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="18">Quick note</text>
10
+ <text x="44" y="124" fill="#8b949e" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="16">Type a note. Ctrl+C: exit.</text>
11
+ <rect x="44" y="144" width="360" height="28" rx="6" fill="#0d1117" stroke="#58a6ff"/>
12
+ <text x="58" y="164" fill="#c9d1d9" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="15">Write a note</text>
13
+ </svg>