@valyrianjs/terminal 0.1.0 → 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.
- package/README.md +105 -55
- package/dist/ansi.d.ts +20 -4
- package/dist/ansi.d.ts.map +1 -1
- package/dist/ansi.js +171 -47
- package/dist/ansi.js.map +1 -1
- package/dist/editor-state.d.ts +22 -0
- package/dist/editor-state.d.ts.map +1 -0
- package/dist/editor-state.js +110 -0
- package/dist/editor-state.js.map +1 -0
- package/dist/events.d.ts +1 -4
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +15 -38
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/keymap.d.ts +7 -0
- package/dist/keymap.d.ts.map +1 -0
- package/dist/keymap.js +133 -0
- package/dist/keymap.js.map +1 -0
- package/dist/layout.d.ts +10 -1
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +97 -7
- package/dist/layout.js.map +1 -1
- package/dist/mouse.d.ts +1 -0
- package/dist/mouse.d.ts.map +1 -1
- package/dist/mouse.js +24 -1
- package/dist/mouse.js.map +1 -1
- package/dist/output-writer.d.ts +9 -0
- package/dist/output-writer.d.ts.map +1 -0
- package/dist/output-writer.js +79 -0
- package/dist/output-writer.js.map +1 -0
- package/dist/paste.d.ts +7 -0
- package/dist/paste.d.ts.map +1 -0
- package/dist/paste.js +18 -0
- package/dist/paste.js.map +1 -0
- package/dist/primitives.d.ts +8 -1
- package/dist/primitives.d.ts.map +1 -1
- package/dist/primitives.js +9 -1
- package/dist/primitives.js.map +1 -1
- package/dist/render.d.ts +8 -3
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +840 -67
- package/dist/render.js.map +1 -1
- package/dist/runtime.d.ts +29 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +215 -0
- package/dist/runtime.js.map +1 -0
- package/dist/scheduler.d.ts +8 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +24 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +729 -199
- package/dist/session.js.map +1 -1
- package/dist/stream-log.d.ts +40 -0
- package/dist/stream-log.d.ts.map +1 -0
- package/dist/stream-log.js +73 -0
- package/dist/stream-log.js.map +1 -0
- package/dist/text.d.ts +3 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +19 -0
- package/dist/text.js.map +1 -0
- package/dist/theme.d.ts +7 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +254 -0
- package/dist/theme.js.map +1 -0
- package/dist/tree.d.ts +2 -0
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +42 -1
- package/dist/tree.js.map +1 -1
- package/dist/types.d.ts +183 -18
- package/dist/types.d.ts.map +1 -1
- package/docs/api-reference.md +302 -136
- package/docs/assets/quick-note.svg +13 -0
- package/docs/cookbook.md +297 -202
- package/docs/core-concepts.md +143 -55
- package/docs/getting-started.md +209 -90
- package/docs/interaction-model.md +95 -61
- package/docs/primitive-gallery.md +365 -0
- package/docs/session-runtime.md +132 -363
- package/docs/valyrian-modules.md +3196 -0
- package/llms-full.txt +5357 -0
- package/package.json +21 -8
- package/src/ansi.ts +269 -0
- package/src/clipboard.ts +76 -0
- package/src/editor-state.ts +162 -0
- package/src/events.ts +163 -0
- package/src/index.ts +92 -0
- package/src/keymap.ts +151 -0
- package/src/layout.ts +282 -0
- package/src/mouse.ts +68 -0
- package/src/output-writer.ts +93 -0
- package/src/paste.ts +23 -0
- package/src/primitives.ts +52 -0
- package/src/render.ts +1107 -0
- package/src/runtime.ts +273 -0
- package/src/scheduler.ts +33 -0
- package/src/session.ts +1260 -0
- package/src/stream-log.ts +96 -0
- package/src/text.ts +20 -0
- package/src/theme.ts +263 -0
- package/src/tree.ts +169 -0
- package/src/types.ts +523 -0
- package/tsconfig.json +4 -7
- package/docs/local-demo.md +0 -28
package/docs/session-runtime.md
CHANGED
|
@@ -1,451 +1,220 @@
|
|
|
1
1
|
# Session Runtime
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This guide explains how to use `mountTerminal()` in common cases first, then how to integrate it with host streams and runtime features.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## When to use the session runtime
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Use `mountTerminal()` when the UI needs one or more of these capabilities:
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- focus and keyboard dispatch
|
|
10
|
+
- repeated renders after state changes
|
|
11
|
+
- clipboard integration
|
|
12
|
+
- mouse and coordinate-based interaction
|
|
13
|
+
- `stdin` and `stdout` connection
|
|
14
|
+
- ANSI output for a real terminal
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
- mantiene foco entre renders
|
|
13
|
-
- despacha teclado por sesion
|
|
14
|
-
- conecta `stdin` y `stdout`
|
|
15
|
-
- responde a coordenadas y eventos de mouse
|
|
16
|
+
Use `renderTerminal()` for deterministic static plain text.
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
## Practical recommendations
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
- Start without streams while building examples and scripted flows.
|
|
21
|
+
- Give stable `id` values to focusable primitives you want to control.
|
|
22
|
+
- Keep application state outside the renderer.
|
|
23
|
+
- Valyrian reactive state read by components refreshes the terminal when it changes, including external async changes. Call `session.update()` for non-reactive state or an explicit manual refresh.
|
|
24
|
+
- Call `session.destroy()` when a session is connected to real streams.
|
|
25
|
+
- Design keyboard-first flows and connect resize, modified keys, clipboard, and mouse through the host capabilities available in each terminal environment.
|
|
26
|
+
|
|
27
|
+
## Common runtime usage
|
|
22
28
|
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
Full example: [`examples/docs/interactive-note.tsx`](../examples/docs/interactive-note.tsx). Run it with `bun examples/docs/interactive-note.tsx`, type a note, press `Enter`, and quit with `Ctrl+C`.
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { Input, Screen, Text, mountTerminal } from "@valyrianjs/terminal";
|
|
25
33
|
|
|
26
34
|
const state = { value: "" };
|
|
27
35
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
)
|
|
36
|
+
function App() {
|
|
37
|
+
return (
|
|
38
|
+
<Screen title="Runtime demo">
|
|
39
|
+
<Input
|
|
40
|
+
id="name"
|
|
41
|
+
value={state.value}
|
|
42
|
+
placeholder="Name"
|
|
43
|
+
onchange={(event) => {
|
|
44
|
+
state.value = event.value;
|
|
45
|
+
}}
|
|
46
|
+
/>
|
|
47
|
+
<Text>Current: {state.value || "(empty)"}</Text>
|
|
48
|
+
</Screen>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const session = mountTerminal(<App />);
|
|
40
53
|
|
|
41
54
|
session.focus("name");
|
|
42
55
|
session.dispatchKey("A");
|
|
43
56
|
session.dispatchKey("B");
|
|
44
57
|
|
|
45
58
|
console.log(session.output());
|
|
59
|
+
session.destroy();
|
|
46
60
|
```
|
|
47
61
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
`mountTerminal(input, options?)` acepta un `TerminalMountOptions` con cuatro puntos de integracion:
|
|
51
|
-
|
|
52
|
-
### `ansi?: boolean`
|
|
53
|
-
|
|
54
|
-
Activa salida ANSI incremental hacia `stdout`. `session.ansiOutput()` sigue disponible aunque no actives esta opcion; lo que cambia es la escritura automatica de la sesion cuando hace rerender. Si no lo activas, la salida principal enviada a `stdout` es texto plano.
|
|
55
|
-
|
|
56
|
-
### `clipboard?: TerminalClipboardAdapter | false`
|
|
57
|
-
|
|
58
|
-
- si pasas un adapter, la sesion usa `readText()` y `writeText()` cuando ejecuta atajos como `CTRL_C` o `CTRL_V`
|
|
59
|
-
- si pasas `false`, desactivas la integracion con clipboard del sistema
|
|
60
|
-
- aun con `clipboard: false`, `session.clipboard()` y `session.setClipboard()` siguen funcionando como buffer de la sesion
|
|
61
|
-
|
|
62
|
-
```tsx
|
|
63
|
-
/** @jsx v */
|
|
64
|
-
/** @jsxFrag v.fragment */
|
|
65
|
-
|
|
66
|
-
import { v } from "valyrian.js";
|
|
67
|
-
import { Screen, mountTerminal } from "valyrianjs-terminal";
|
|
68
|
-
|
|
69
|
-
const app = () => <Screen title="Clipboard Demo" />;
|
|
70
|
-
|
|
71
|
-
const session = mountTerminal(app, {
|
|
72
|
-
clipboard: {
|
|
73
|
-
readText() {
|
|
74
|
-
return "pasted value";
|
|
75
|
-
},
|
|
76
|
-
writeText(value) {
|
|
77
|
-
console.log("copied:", value);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
```tsx
|
|
84
|
-
/** @jsx v */
|
|
85
|
-
/** @jsxFrag v.fragment */
|
|
62
|
+
The session lifecycle is:
|
|
86
63
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const session = mountTerminal(app, { clipboard: false });
|
|
93
|
-
session.setClipboard("fallback value");
|
|
94
|
-
```
|
|
64
|
+
1. mount with `mountTerminal()`
|
|
65
|
+
2. read `output()` or `ansiOutput()`
|
|
66
|
+
3. dispatch input or update external state
|
|
67
|
+
4. rerender with `update()` when needed
|
|
68
|
+
5. close with `destroy()`
|
|
95
69
|
|
|
96
|
-
|
|
70
|
+
## Input, output, and cleanup
|
|
97
71
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
Contrato esperado:
|
|
72
|
+
### `output()`
|
|
101
73
|
|
|
102
|
-
-
|
|
103
|
-
- `off(...)` o `removeListener(...)` opcional para cleanup
|
|
104
|
-
- `setRawMode?(boolean)` opcional
|
|
105
|
-
- `resume?()` y `pause?()` opcionales
|
|
74
|
+
Returns the current plain-text frame. Use it for snapshots, examples, and content inspection.
|
|
106
75
|
|
|
107
|
-
### `
|
|
76
|
+
### `ansiOutput()`
|
|
108
77
|
|
|
109
|
-
|
|
78
|
+
Returns the current frame serialized with ANSI cursor movement and style spans.
|
|
110
79
|
|
|
111
|
-
-
|
|
112
|
-
- con `ansi: true`, escribe diffs ANSI incrementales
|
|
80
|
+
Related example: [`examples/docs/theme-colors.tsx`](../examples/docs/theme-colors.tsx). Run it with `bun examples/docs/theme-colors.tsx`, press `Tab`, and quit with `Ctrl+C`.
|
|
113
81
|
|
|
114
82
|
```tsx
|
|
115
|
-
|
|
116
|
-
/** @jsxFrag v.fragment */
|
|
117
|
-
|
|
118
|
-
import { v } from "valyrian.js";
|
|
119
|
-
import { Screen, mountTerminal } from "valyrianjs-terminal";
|
|
83
|
+
import { Screen, mountTerminal } from "@valyrianjs/terminal";
|
|
120
84
|
|
|
121
|
-
|
|
85
|
+
function App() {
|
|
86
|
+
return <Screen title="ANSI frame" />;
|
|
87
|
+
}
|
|
122
88
|
|
|
123
|
-
const
|
|
89
|
+
const session = mountTerminal(<App />, { runtime: "headless" });
|
|
124
90
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
stdout: {
|
|
128
|
-
write(chunk) {
|
|
129
|
-
writes.push(String(chunk));
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
});
|
|
91
|
+
console.log(session.ansiOutput());
|
|
92
|
+
session.destroy();
|
|
133
93
|
```
|
|
134
94
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
La sesion mantiene un frame actual, una salida actual y el estado interactivo asociado al arbol enfocable. El ciclo practico es:
|
|
138
|
-
|
|
139
|
-
1. montar con `mountTerminal()`
|
|
140
|
-
2. leer con `output()` o `ansiOutput()`
|
|
141
|
-
3. mutar estado externo o despachar interacciones
|
|
142
|
-
4. rerender con `update()` o mediante eventos que ya disparan rerender
|
|
143
|
-
5. cerrar con `destroy()`
|
|
95
|
+
`ansiOutput()` is an explicit inspection/export path. Keep ordinary `Text`, input values, list rows, and log entries as text content. Advanced span serialization tokens are documented in [Advanced: span serialization tokens](./api-reference.md#advanced-span-serialization-tokens) for low-level renderer integrations.
|
|
144
96
|
|
|
145
97
|
### `update()`
|
|
146
98
|
|
|
147
|
-
|
|
99
|
+
Re-evaluates the session input and returns the current plain-text output.
|
|
148
100
|
|
|
149
|
-
|
|
101
|
+
Related example: [`examples/docs/component-composition.tsx`](../examples/docs/component-composition.tsx). Run it with `bun examples/docs/component-composition.tsx`, switch cards with `N/P`, and quit with `Ctrl+C`.
|
|
150
102
|
|
|
151
103
|
```tsx
|
|
104
|
+
import { Screen, Text, mountTerminal } from "@valyrianjs/terminal";
|
|
105
|
+
|
|
152
106
|
const state = { count: 0 };
|
|
153
107
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
<
|
|
157
|
-
|
|
158
|
-
|
|
108
|
+
function App() {
|
|
109
|
+
return (
|
|
110
|
+
<Screen title="Update demo">
|
|
111
|
+
<Text>Count: {state.count}</Text>
|
|
112
|
+
</Screen>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const session = mountTerminal(<App />);
|
|
159
117
|
|
|
160
118
|
state.count += 1;
|
|
161
119
|
session.update();
|
|
162
120
|
|
|
163
121
|
console.log(session.output());
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### `output()`
|
|
167
|
-
|
|
168
|
-
Devuelve el frame actual en texto plano. Es la forma mas directa de:
|
|
169
|
-
|
|
170
|
-
- inspeccionar estado actual
|
|
171
|
-
- validar snapshots
|
|
172
|
-
- probar foco y contenido sin ANSI
|
|
173
|
-
|
|
174
|
-
### `ansiOutput()`
|
|
175
|
-
|
|
176
|
-
Devuelve el frame actual serializado como ANSI completo, incluyendo cursor y spans visuales. Es util cuando quieres:
|
|
177
|
-
|
|
178
|
-
- inspeccionar posicion de cursor
|
|
179
|
-
- validar seleccion o foco en una terminal ANSI
|
|
180
|
-
- integrar una capa que consume escape sequences completas
|
|
181
|
-
|
|
182
|
-
```tsx
|
|
183
|
-
/** @jsx v */
|
|
184
|
-
/** @jsxFrag v.fragment */
|
|
185
|
-
|
|
186
|
-
import { v } from "valyrian.js";
|
|
187
|
-
import { Screen, mountTerminal } from "valyrianjs-terminal";
|
|
188
|
-
|
|
189
|
-
const app = () => <Screen title="ANSI Frame Demo" />;
|
|
190
|
-
|
|
191
|
-
const session = mountTerminal(app, { ansi: true });
|
|
192
|
-
const ansi = session.ansiOutput();
|
|
193
|
-
console.log(ansi);
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### `destroy()`
|
|
197
|
-
|
|
198
|
-
Desmonta listeners de `stdin`, intenta salir de raw mode con `setRawMode(false)` y llama `pause()` si existe.
|
|
199
|
-
|
|
200
|
-
Llamalo siempre cuando montaste la sesion con `stdin` real o un emisor conectado.
|
|
201
|
-
|
|
202
|
-
```ts
|
|
203
122
|
session.destroy();
|
|
204
123
|
```
|
|
205
124
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
El foco vive a nivel de sesion. Para participar en este flujo, los nodos interactivos necesitan `id`.
|
|
209
|
-
|
|
210
|
-
### `focus(id)`
|
|
211
|
-
|
|
212
|
-
Enfoca un nodo por `id`. Devuelve `true` si lo encontro.
|
|
213
|
-
|
|
214
|
-
### `focusNext()` y `focusPrev()`
|
|
215
|
-
|
|
216
|
-
Recorren el orden actual de elementos enfocables. `dispatchKey("TAB")` y `dispatchKey("SHIFT_TAB")` usan este mismo flujo.
|
|
217
|
-
|
|
218
|
-
### `focusAt(x, y)`
|
|
219
|
-
|
|
220
|
-
Busca el hitbox en las coordenadas actuales, actualiza hover semantico cuando aplica y enfoca ese nodo.
|
|
221
|
-
|
|
222
|
-
### `clickAt(x, y)`
|
|
223
|
-
|
|
224
|
-
- si cae sobre un `Button`, dispara su accion
|
|
225
|
-
- si cae sobre un `Input`, enfoca y coloca cursor segun la coordenada
|
|
226
|
-
- si cae sobre otra superficie enfocable, mueve el foco
|
|
227
|
-
|
|
228
|
-
```tsx
|
|
229
|
-
const session = mountTerminal(() => (
|
|
230
|
-
<Screen>
|
|
231
|
-
<Input id="name" value="abc" />
|
|
232
|
-
<Button id="save">Save</Button>
|
|
233
|
-
</Screen>
|
|
234
|
-
));
|
|
235
|
-
|
|
236
|
-
session.focusAt(2, 1);
|
|
237
|
-
session.clickAt(3, 2);
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
## Keyboard dispatch por sesion
|
|
241
|
-
|
|
242
|
-
`dispatchKey(key)` procesa una tecla ya normalizada contra el nodo enfocado y devuelve la salida plana actual.
|
|
243
|
-
|
|
244
|
-
Atajos soportados por la API publica observables en pruebas:
|
|
245
|
-
|
|
246
|
-
- globales: `TAB`, `SHIFT_TAB`
|
|
247
|
-
- `Input`: caracteres de un solo byte, `ENTER`, `LEFT`, `RIGHT`, `SHIFT_LEFT`, `SHIFT_RIGHT`, `ALT_LEFT`, `ALT_RIGHT`, `HOME`, `END`, `CTRL_A`, `CTRL_C`, `CTRL_X`, `CTRL_V`, `BACKSPACE`, `DELETE`
|
|
248
|
-
- `Button`: `ENTER`, `SPACE`
|
|
249
|
-
- `List`: `UP`, `DOWN`, `LEFT`, `RIGHT`, `ENTER`
|
|
250
|
-
- `ScrollView`: `UP`, `DOWN`
|
|
251
|
-
|
|
252
|
-
```tsx
|
|
253
|
-
const state = { value: "", saved: "" };
|
|
254
|
-
|
|
255
|
-
const session = mountTerminal(() => (
|
|
256
|
-
<Screen>
|
|
257
|
-
<Input
|
|
258
|
-
id="name"
|
|
259
|
-
value={state.value}
|
|
260
|
-
onchange={(event) => {
|
|
261
|
-
state.value = event.value;
|
|
262
|
-
}}
|
|
263
|
-
onsubmit={(event) => {
|
|
264
|
-
state.saved = event.value;
|
|
265
|
-
}}
|
|
266
|
-
/>
|
|
267
|
-
</Screen>
|
|
268
|
-
));
|
|
269
|
-
|
|
270
|
-
session.focus("name");
|
|
271
|
-
session.dispatchKey("A");
|
|
272
|
-
session.dispatchKey("B");
|
|
273
|
-
session.dispatchKey("LEFT");
|
|
274
|
-
session.dispatchKey("C");
|
|
275
|
-
session.dispatchKey("ENTER");
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
## Clipboard adapter y `clipboard: false`
|
|
279
|
-
|
|
280
|
-
La sesion separa dos conceptos:
|
|
281
|
-
|
|
282
|
-
- buffer de clipboard de la sesion: `clipboard()` y `setClipboard()`
|
|
283
|
-
- integracion con el sistema: `options.clipboard`
|
|
125
|
+
### `destroy()`
|
|
284
126
|
|
|
285
|
-
|
|
127
|
+
Removes listeners and restores supported terminal state when a session connected to streams changed it. Always call it when the session owns real input or output resources.
|
|
286
128
|
|
|
287
|
-
|
|
288
|
-
const state = { value: "abcd" };
|
|
289
|
-
|
|
290
|
-
const session = mountTerminal(() => (
|
|
291
|
-
<Screen>
|
|
292
|
-
<Input
|
|
293
|
-
id="name"
|
|
294
|
-
value={state.value}
|
|
295
|
-
onchange={(event) => {
|
|
296
|
-
state.value = event.value;
|
|
297
|
-
}}
|
|
298
|
-
/>
|
|
299
|
-
</Screen>
|
|
300
|
-
), { clipboard: false });
|
|
129
|
+
## Advanced host integration
|
|
301
130
|
|
|
302
|
-
|
|
303
|
-
session.setClipboard("XY");
|
|
304
|
-
session.dispatchKey("END");
|
|
305
|
-
session.dispatchKey("CTRL_V");
|
|
306
|
-
```
|
|
131
|
+
### Mount options
|
|
307
132
|
|
|
308
|
-
|
|
133
|
+
`mountTerminal(input, options?)` accepts options for host integration. `mountTerminal(<App />)` is the normal interactive path; it uses process stdio, ANSI diffs, alternate screen, and a hidden cursor only when called from a real interactive TTY. Imports and non-TTY/test runs do not auto-attach stdio.
|
|
309
134
|
|
|
310
|
-
|
|
135
|
+
- `runtime?: "app" | "headless"` - selects interactive app behavior or scriptable plain output. Omitted runtime uses app mode only for interactive TTY hosts and stays headless in non-TTY/CI contexts.
|
|
136
|
+
- `alternateScreen?: boolean` - enters the terminal alternate screen and restores it on destroy by default. Real interactive app mode enables it by default unless overridden.
|
|
137
|
+
- `hideCursor?: boolean` - expresses that the session should hide the terminal cursor while it owns the screen when the host supports it. Real interactive app mode enables it by default unless overridden.
|
|
138
|
+
- `restoreOnDestroy?: boolean` - controls whether destroy should restore supported cursor and alternate-screen state.
|
|
139
|
+
- `clipboard?: TerminalClipboardAdapter | false` - connects a custom clipboard adapter or disables external clipboard integration.
|
|
140
|
+
- `cols?: number` and `rows?: number` - set the initial terminal size.
|
|
141
|
+
- `stdin?` - receives keyboard, paste, and mouse input.
|
|
142
|
+
- `stdout?` - receives rendered output.
|
|
311
143
|
|
|
312
|
-
|
|
144
|
+
### Clipboard adapter
|
|
313
145
|
|
|
314
|
-
-
|
|
315
|
-
- si `stdin.setRawMode` existe, intenta `setRawMode(true)`
|
|
316
|
-
- si `stdin.resume` existe, intenta `resume()`
|
|
317
|
-
- en cada rerender, si existe `stdout.write`, la sesion escribe el frame actual
|
|
318
|
-
- al destruir, intenta desuscribirse y restaurar `raw mode`
|
|
146
|
+
Related example: [`examples/docs/interactive-note.tsx`](../examples/docs/interactive-note.tsx). Run it with `bun examples/docs/interactive-note.tsx`, type a note, press `Enter`, and quit with `Ctrl+C`.
|
|
319
147
|
|
|
320
148
|
```tsx
|
|
321
|
-
|
|
322
|
-
/** @jsxFrag v.fragment */
|
|
149
|
+
import { Screen, mountTerminal } from "@valyrianjs/terminal";
|
|
323
150
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
151
|
+
function App() {
|
|
152
|
+
return <Screen title="Clipboard" />;
|
|
153
|
+
}
|
|
327
154
|
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const writes: string[] = [];
|
|
337
|
-
|
|
338
|
-
const session = mountTerminal(app, {
|
|
339
|
-
stdin,
|
|
340
|
-
stdout: {
|
|
341
|
-
write(chunk) {
|
|
342
|
-
writes.push(String(chunk));
|
|
155
|
+
const session = mountTerminal(<App />, {
|
|
156
|
+
clipboard: {
|
|
157
|
+
readText() {
|
|
158
|
+
return "pasted value";
|
|
159
|
+
},
|
|
160
|
+
writeText(value) {
|
|
161
|
+
console.log("copied:", value);
|
|
343
162
|
}
|
|
344
163
|
}
|
|
345
164
|
});
|
|
346
165
|
|
|
347
|
-
stdin.emit("data", "A");
|
|
348
|
-
stdin.emit("data", "\r");
|
|
349
166
|
session.destroy();
|
|
350
167
|
```
|
|
351
168
|
|
|
352
|
-
|
|
169
|
+
Passing `clipboard: false` disables external clipboard integration while preserving the session clipboard buffer through `clipboard()` and `setClipboard()`.
|
|
353
170
|
|
|
354
|
-
|
|
171
|
+
### Streams
|
|
355
172
|
|
|
356
|
-
|
|
357
|
-
- `session.ansiOutput()`: recupera el frame ANSI completo del estado actual
|
|
173
|
+
`stdin` should provide `on("data", listener)`. Cleanup methods such as `off(...)` or `removeListener(...)` are used when available. `setRawMode`, `resume`, and `pause` are optional.
|
|
358
174
|
|
|
359
|
-
|
|
175
|
+
`stdout` should provide `write(chunk: string)`. Optional `columns` and `rows` can provide initial dimensions. Optional `resize` and `drain` events are used only when the stream also provides listener cleanup.
|
|
360
176
|
|
|
361
|
-
|
|
362
|
-
const state = { value: "AB" };
|
|
363
|
-
|
|
364
|
-
const session = mountTerminal(() => (
|
|
365
|
-
<Screen title="ANSI Demo">
|
|
366
|
-
<Input
|
|
367
|
-
id="name"
|
|
368
|
-
value={state.value}
|
|
369
|
-
onchange={(event) => {
|
|
370
|
-
state.value = event.value;
|
|
371
|
-
}}
|
|
372
|
-
/>
|
|
373
|
-
</Screen>
|
|
374
|
-
), { ansi: true });
|
|
177
|
+
### Size and resize
|
|
375
178
|
|
|
376
|
-
|
|
377
|
-
session.dispatchKey("LEFT");
|
|
179
|
+
`size()` returns `{ cols, rows }`. `resize(cols, rows)` validates positive integer dimensions, stores them, and rerenders once.
|
|
378
180
|
|
|
379
|
-
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
## Mouse SGR, wheel y pointer capture
|
|
383
|
-
|
|
384
|
-
Cuando conectas `stdin`, la sesion acepta secuencias SGR de mouse y las traduce a interaccion practica sobre el frame actual.
|
|
385
|
-
|
|
386
|
-
### Press, drag y release
|
|
387
|
-
|
|
388
|
-
- `press`: enfoca y activa el hitbox en la coordenada
|
|
389
|
-
- `drag`: si hay un `Input` activo por mouse, extiende seleccion; en `List` y `ScrollView`, actualiza hover por fila
|
|
390
|
-
- `release`: termina seleccion por mouse y cierra captura cuando aplica
|
|
391
|
-
|
|
392
|
-
```ts
|
|
393
|
-
stdin.emit("data", "\u001b[<0;4;1M");
|
|
394
|
-
stdin.emit("data", "\u001b[<32;7;1M");
|
|
395
|
-
stdin.emit("data", "\u001b[<0;7;1m");
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
Ese patron es suficiente para seleccionar texto dentro de un `Input` por coordenadas.
|
|
181
|
+
Related example: [`examples/docs/background-fill.tsx`](../examples/docs/background-fill.tsx). Run it with `bun examples/docs/background-fill.tsx`, switch surfaces with `B`, and quit with `Ctrl+C`.
|
|
399
182
|
|
|
400
|
-
|
|
183
|
+
```tsx
|
|
184
|
+
import { Screen, mountTerminal } from "@valyrianjs/terminal";
|
|
401
185
|
|
|
402
|
-
|
|
186
|
+
function App() {
|
|
187
|
+
return <Screen title="Resizable" />;
|
|
188
|
+
}
|
|
403
189
|
|
|
404
|
-
|
|
405
|
-
- `wheel-down` equivale a `dispatchKey("DOWN")`
|
|
190
|
+
const session = mountTerminal(<App />, { cols: 80, rows: 24 });
|
|
406
191
|
|
|
407
|
-
|
|
408
|
-
|
|
192
|
+
console.log(session.size());
|
|
193
|
+
session.resize(100, 30);
|
|
194
|
+
console.log(session.size());
|
|
195
|
+
session.destroy();
|
|
409
196
|
```
|
|
410
197
|
|
|
411
|
-
|
|
198
|
+
Automatic resize works with compatible output sources that emit supported resize events after updating their `columns` and `rows` values.
|
|
412
199
|
|
|
413
|
-
###
|
|
200
|
+
### Keyboard, paste, and mouse input
|
|
414
201
|
|
|
415
|
-
`
|
|
202
|
+
`dispatchKey(key)` injects a normalized key directly. Connected `stdin` can also deliver keyboard input, terminal paste input, and supported SGR mouse input.
|
|
416
203
|
|
|
417
|
-
|
|
204
|
+
Bracketed paste is handled as terminal input: pasted text is inserted into the focused `Input` or `Editor` as content instead of being treated as separate key commands. Multiline `Editor` cursor columns are reported as JavaScript UTF-16 string columns, not as a complete terminal grapheme-width model.
|
|
418
205
|
|
|
419
|
-
|
|
420
|
-
- `oncaptureend`
|
|
206
|
+
Mouse input can focus or activate hitboxes, update hover state, and map wheel input to vertical navigation. Keep keyboard alternatives for important actions so every terminal workflow has a reliable input path.
|
|
421
207
|
|
|
422
|
-
|
|
208
|
+
## Host integration behavior
|
|
423
209
|
|
|
424
|
-
-
|
|
425
|
-
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
<Screen>
|
|
430
|
-
<List
|
|
431
|
-
id="menu"
|
|
432
|
-
pointerCapture
|
|
433
|
-
items={["Open", "Save", "Exit"]}
|
|
434
|
-
oncapturestart={(event) => console.log(event)}
|
|
435
|
-
oncaptureend={(event) => console.log(event)}
|
|
436
|
-
/>
|
|
437
|
-
</Screen>
|
|
438
|
-
), { stdin, clipboard: false });
|
|
439
|
-
|
|
440
|
-
stdin.emit("data", "\u001b[<0;2;1M");
|
|
441
|
-
stdin.emit("data", "\u001b[<32;99;99M");
|
|
442
|
-
stdin.emit("data", "\u001b[<0;99;99m");
|
|
443
|
-
```
|
|
210
|
+
- Modified keys follow sequences reported by the connected terminal.
|
|
211
|
+
- Clipboard behavior uses the provided adapter or the session clipboard buffer.
|
|
212
|
+
- Mouse behavior uses supported terminal input sequences.
|
|
213
|
+
- Automatic resize works with compatible output sources and cleanup-capable listeners.
|
|
214
|
+
- Use session runtime for terminal rendering, focus, input, output, and cleanup. Keep routing, persistence, command orchestration, and process management in the app layer.
|
|
444
215
|
|
|
445
|
-
##
|
|
216
|
+
## Where to go next
|
|
446
217
|
|
|
447
|
-
-
|
|
448
|
-
-
|
|
449
|
-
-
|
|
450
|
-
- llama `destroy()` siempre que montes con `stdin`
|
|
451
|
-
- usa `clipboard: false` en pruebas o entornos donde no quieres depender del clipboard del sistema
|
|
218
|
+
- [Getting Started](./getting-started.md) for the first project.
|
|
219
|
+
- [Interaction Model](./interaction-model.md) for per-primitive behavior.
|
|
220
|
+
- [API Reference](./api-reference.md) for exact methods, props, and payloads.
|