@valyrianjs/terminal 0.1.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.
Files changed (55) hide show
  1. package/README.md +71 -0
  2. package/dist/ansi.d.ts +6 -0
  3. package/dist/ansi.d.ts.map +1 -0
  4. package/dist/ansi.js +105 -0
  5. package/dist/ansi.js.map +1 -0
  6. package/dist/clipboard.d.ts +3 -0
  7. package/dist/clipboard.d.ts.map +1 -0
  8. package/dist/clipboard.js +71 -0
  9. package/dist/clipboard.js.map +1 -0
  10. package/dist/events.d.ts +62 -0
  11. package/dist/events.d.ts.map +1 -0
  12. package/dist/events.js +189 -0
  13. package/dist/events.js.map +1 -0
  14. package/dist/index.d.ts +5 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +4 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/layout.d.ts +16 -0
  19. package/dist/layout.d.ts.map +1 -0
  20. package/dist/layout.js +153 -0
  21. package/dist/layout.js.map +1 -0
  22. package/dist/mouse.d.ts +5 -0
  23. package/dist/mouse.d.ts.map +1 -0
  24. package/dist/mouse.js +34 -0
  25. package/dist/mouse.js.map +1 -0
  26. package/dist/primitives.d.ts +15 -0
  27. package/dist/primitives.d.ts.map +1 -0
  28. package/dist/primitives.js +18 -0
  29. package/dist/primitives.js.map +1 -0
  30. package/dist/render.d.ts +5 -0
  31. package/dist/render.d.ts.map +1 -0
  32. package/dist/render.js +230 -0
  33. package/dist/render.js.map +1 -0
  34. package/dist/session.d.ts +3 -0
  35. package/dist/session.d.ts.map +1 -0
  36. package/dist/session.js +599 -0
  37. package/dist/session.js.map +1 -0
  38. package/dist/tree.d.ts +9 -0
  39. package/dist/tree.d.ts.map +1 -0
  40. package/dist/tree.js +103 -0
  41. package/dist/tree.js.map +1 -0
  42. package/dist/types.d.ts +224 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +2 -0
  45. package/dist/types.js.map +1 -0
  46. package/docs/api-reference.md +273 -0
  47. package/docs/cookbook.md +286 -0
  48. package/docs/core-concepts.md +93 -0
  49. package/docs/getting-started.md +148 -0
  50. package/docs/interaction-model.md +115 -0
  51. package/docs/local-demo.md +28 -0
  52. package/docs/session-runtime.md +451 -0
  53. package/package.json +44 -0
  54. package/tsconfig.build.json +15 -0
  55. package/tsconfig.json +25 -0
@@ -0,0 +1,286 @@
1
+ # Cookbook
2
+
3
+ Recetas cortas y copiables para `valyrianjs-terminal`. Esta guia complementa `docs/getting-started.md`, `docs/interaction-model.md` y `docs/api-reference.md`.
4
+
5
+ ## Render estatico para snapshots
6
+
7
+ Usalo cuando quieras validar layout o generar texto plano sin abrir una sesion interactiva.
8
+
9
+ ```tsx
10
+ /** @jsx v */
11
+ /** @jsxFrag v.fragment */
12
+
13
+ import { v } from "valyrian.js";
14
+ import { Screen, Text, renderTerminal } from "valyrianjs-terminal";
15
+
16
+ const output = renderTerminal(
17
+ <Screen title="Snapshot Demo">
18
+ <Text>Hello terminal</Text>
19
+ <Text>Status: ok</Text>
20
+ </Screen>
21
+ );
22
+
23
+ console.log(output);
24
+ ```
25
+
26
+ ## Input controlado con submit
27
+
28
+ Usalo cuando necesites un campo editable que guarde el valor final al presionar `Enter`.
29
+
30
+ ```tsx
31
+ /** @jsx v */
32
+ /** @jsxFrag v.fragment */
33
+
34
+ import { v } from "valyrian.js";
35
+ import { Input, Screen, Text, mountTerminal } from "valyrianjs-terminal";
36
+
37
+ const state = { value: "", submitted: "" };
38
+
39
+ const session = mountTerminal(() => (
40
+ <Screen>
41
+ <Input
42
+ id="name"
43
+ value={state.value}
44
+ placeholder="Write a quick note"
45
+ onchange={(event) => {
46
+ state.value = event.value;
47
+ }}
48
+ onsubmit={(event) => {
49
+ state.submitted = event.value;
50
+ }}
51
+ />
52
+ <Text>{state.submitted || "Nothing submitted yet"}</Text>
53
+ </Screen>
54
+ ));
55
+
56
+ session.focus("name");
57
+ session.dispatchKey("H");
58
+ session.dispatchKey("i");
59
+ session.dispatchKey("ENTER");
60
+
61
+ console.log(state.submitted);
62
+ console.log(session.output());
63
+ ```
64
+
65
+ ## Boton que muta estado
66
+
67
+ Usalo cuando quieras activar acciones simples desde teclado o click programatico.
68
+
69
+ ```tsx
70
+ /** @jsx v */
71
+ /** @jsxFrag v.fragment */
72
+
73
+ import { v } from "valyrian.js";
74
+ import { Button, Screen, Text, mountTerminal } from "valyrianjs-terminal";
75
+
76
+ const state = { count: 0 };
77
+
78
+ const session = mountTerminal(() => (
79
+ <Screen>
80
+ <Button
81
+ id="increment"
82
+ onpress={() => {
83
+ state.count += 1;
84
+ }}
85
+ >
86
+ Increment
87
+ </Button>
88
+ <Text>{`Count: ${state.count}`}</Text>
89
+ </Screen>
90
+ ));
91
+
92
+ session.click("increment");
93
+ session.click("increment");
94
+
95
+ console.log(session.output());
96
+ ```
97
+
98
+ ## Lista interactiva con `onchange` y `onpress`
99
+
100
+ Usalo cuando quieras separar el item actualmente seleccionado del item activado con `Enter`.
101
+
102
+ ```tsx
103
+ /** @jsx v */
104
+ /** @jsxFrag v.fragment */
105
+
106
+ import { v } from "valyrian.js";
107
+ import { List, Screen, Text, mountTerminal } from "valyrianjs-terminal";
108
+
109
+ const state = { selected: "", opened: "" };
110
+
111
+ const session = mountTerminal(() => (
112
+ <Screen>
113
+ <List
114
+ id="menu"
115
+ items={["Inbox", "Today", "Done"]}
116
+ onchange={(event) => {
117
+ state.selected = event.value;
118
+ }}
119
+ onpress={(event) => {
120
+ state.opened = event.value;
121
+ }}
122
+ />
123
+ <Text>{`Selected: ${state.selected || "-"}`}</Text>
124
+ <Text>{`Opened: ${state.opened || "-"}`}</Text>
125
+ </Screen>
126
+ ));
127
+
128
+ session.focus("menu");
129
+ session.dispatchKey("DOWN");
130
+ session.dispatchKey("DOWN");
131
+ session.dispatchKey("ENTER");
132
+
133
+ console.log(state.selected);
134
+ console.log(state.opened);
135
+ ```
136
+
137
+ ## Scroll view con `height` y `highlightRows`
138
+
139
+ Usalo para recortar contenido vertical y marcar filas relevantes dentro del viewport.
140
+
141
+ ```tsx
142
+ /** @jsx v */
143
+ /** @jsxFrag v.fragment */
144
+
145
+ import { v } from "valyrian.js";
146
+ import { Screen, ScrollView, Text, mountTerminal } from "valyrianjs-terminal";
147
+
148
+ const session = mountTerminal(() => (
149
+ <Screen>
150
+ <ScrollView id="activity" height={3} highlightRows={[2]}>
151
+ <Text>Alpha</Text>
152
+ <Text>Beta</Text>
153
+ <Text>Gamma</Text>
154
+ <Text>Delta</Text>
155
+ </ScrollView>
156
+ </Screen>
157
+ ), { ansi: true });
158
+
159
+ session.focus("activity");
160
+ console.log(session.output());
161
+
162
+ session.dispatchKey("DOWN");
163
+ console.log(session.output());
164
+ console.log(session.ansiOutput());
165
+ ```
166
+
167
+ ## Clipboard adapter custom
168
+
169
+ Usalo cuando quieras conectar copiar y pegar con un portapapeles propio en lugar del estado interno de la sesion.
170
+
171
+ ```tsx
172
+ /** @jsx v */
173
+ /** @jsxFrag v.fragment */
174
+
175
+ import { v } from "valyrian.js";
176
+ import { Input, Screen, mountTerminal } from "valyrianjs-terminal";
177
+
178
+ const state = { value: "abcd" };
179
+ const clipboard = {
180
+ value: "",
181
+ readText() {
182
+ return this.value;
183
+ },
184
+ writeText(value: string) {
185
+ this.value = value;
186
+ }
187
+ };
188
+
189
+ const session = mountTerminal(() => (
190
+ <Screen>
191
+ <Input
192
+ id="name"
193
+ value={state.value}
194
+ onchange={(event) => {
195
+ state.value = event.value;
196
+ }}
197
+ />
198
+ </Screen>
199
+ ), { clipboard });
200
+
201
+ session.focus("name");
202
+ session.dispatchKey("HOME");
203
+ session.dispatchKey("SHIFT_RIGHT");
204
+ session.dispatchKey("SHIFT_RIGHT");
205
+ session.dispatchKey("CTRL_C");
206
+
207
+ clipboard.value = "XY";
208
+ session.dispatchKey("END");
209
+ session.dispatchKey("CTRL_V");
210
+
211
+ console.log(session.clipboard());
212
+ console.log(state.value);
213
+ ```
214
+
215
+ ## Interaccion por coordenadas con `focusAt` y `clickAt`
216
+
217
+ Usalo en pruebas o adapters donde el punto de entrada real son coordenadas del frame y no ids conocidos.
218
+
219
+ ```tsx
220
+ /** @jsx v */
221
+ /** @jsxFrag v.fragment */
222
+
223
+ import { v } from "valyrian.js";
224
+ import { Button, Input, Screen, mountTerminal } from "valyrianjs-terminal";
225
+
226
+ const state = { clicks: 0 };
227
+
228
+ const session = mountTerminal(() => (
229
+ <Screen>
230
+ <Input id="name" value="abc" />
231
+ <Button id="save" onpress={() => {
232
+ state.clicks += 1;
233
+ }}>
234
+ Save
235
+ </Button>
236
+ </Screen>
237
+ ));
238
+
239
+ session.focusAt(2, 1);
240
+ session.clickAt(3, 2);
241
+
242
+ console.log(session.output());
243
+ console.log(state.clicks);
244
+ ```
245
+
246
+ ## Inspeccion de salida ANSI con `ansiOutput`
247
+
248
+ Usalo cuando necesites verificar cursor, estilos o secuencias ANSI en pruebas e integraciones.
249
+
250
+ ```tsx
251
+ /** @jsx v */
252
+ /** @jsxFrag v.fragment */
253
+
254
+ import { v } from "valyrian.js";
255
+ import { Input, Screen, mountTerminal } from "valyrianjs-terminal";
256
+
257
+ const state = { value: "AB" };
258
+
259
+ const session = mountTerminal(() => (
260
+ <Screen title="ANSI Demo">
261
+ <Input
262
+ id="name"
263
+ value={state.value}
264
+ onchange={(event) => {
265
+ state.value = event.value;
266
+ }}
267
+ />
268
+ </Screen>
269
+ ), { ansi: true });
270
+
271
+ session.focus("name");
272
+ session.dispatchKey("LEFT");
273
+
274
+ const ansi = session.ansiOutput();
275
+
276
+ console.log(ansi);
277
+ console.log(/\u001b\[[0-9]+;[0-9]+H/.test(ansi));
278
+ ```
279
+
280
+ ## Ver tambien
281
+
282
+ - `docs/getting-started.md` para el flujo minimo de montaje
283
+ - `docs/core-concepts.md` para el modelo mental del paquete
284
+ - `docs/interaction-model.md` para foco, teclado, mouse y clipboard
285
+ - `docs/session-runtime.md` para lifecycle, streams y runtime de sesion
286
+ - `docs/api-reference.md` para la superficie publica completa
@@ -0,0 +1,93 @@
1
+ # Core Concepts
2
+
3
+ Esta guia explica el modelo mental del paquete antes de entrar al detalle de runtime o referencia.
4
+
5
+ ## 1. Primitivas terminal-first
6
+
7
+ `valyrianjs-terminal` no renderiza HTML ni componentes de navegador. Sus primitivas generan nodos terminales propios que luego se convierten en texto plano o en un frame ANSI.
8
+
9
+ Las piezas base se agrupan asi:
10
+
11
+ - layout: `Screen`, `Box`, `View`, `Text`, `Table`, `Row`, `Td`
12
+ - interaccion: `Input`, `Button`, `List`, `ScrollView`
13
+
14
+ Piensalo como un DSL de interfaces de texto, no como una adaptacion visual del DOM.
15
+
16
+ ## 2. Dos modos de trabajo
17
+
18
+ Hay dos entrypoints principales:
19
+
20
+ - `renderTerminal()` para generar texto plano a partir de un arbol terminal
21
+ - `mountTerminal()` para crear una sesion interactiva con foco, teclado, mouse y escritura opcional a streams
22
+
23
+ Regla simple:
24
+
25
+ - si solo quieres inspeccionar contenido, usa `renderTerminal()`
26
+ - si necesitas interaccion o runtime vivo, usa `mountTerminal()`
27
+
28
+ ## 3. El estado vive fuera de la libreria
29
+
30
+ La libreria renderiza lo que tu funcion de UI devuelve con el estado actual. No guarda un store de aplicacion por ti.
31
+
32
+ Eso significa que:
33
+
34
+ - tus handlers mutan estado externo
35
+ - `mountTerminal()` vuelve a evaluar la funcion de render
36
+ - `session.update()` solo hace falta cuando mutaste estado fuera de un handler que ya detona rerender
37
+
38
+ ## 4. `id` es la llave de la interaccion
39
+
40
+ Los nodos interactivos pueden renderizarse sin `id`, pero pierdes gran parte del control programatico.
41
+
42
+ Necesitas `id` estable si quieres:
43
+
44
+ - enfocar con `session.focus(id)`
45
+ - activar con `session.click(id)`
46
+ - participar de hitboxes por coordenadas
47
+ - recibir bien flujos de foco y navegacion
48
+
49
+ Recomendacion practica: da `id` a todo `Input`, `Button`, `List` y `ScrollView` que vaya a vivir mas de una prueba trivial.
50
+
51
+ ## 5. Foco e hitboxes
52
+
53
+ La sesion calcula hitboxes a partir del frame renderizado actual. Eso permite dos clases de interaccion:
54
+
55
+ - por identificador: `focus(id)`, `click(id)`
56
+ - por coordenadas: `focusAt(x, y)`, `clickAt(x, y)`
57
+
58
+ El foco secuencial tambien sale del arbol actual:
59
+
60
+ - `focusNext()`
61
+ - `focusPrev()`
62
+ - `dispatchKey("TAB")`
63
+ - `dispatchKey("SHIFT_TAB")`
64
+
65
+ Si cambia el arbol, cambia tambien el orden y la geometria del foco.
66
+
67
+ ## 6. Salida plana vs salida ANSI
68
+
69
+ El paquete maneja dos representaciones utiles:
70
+
71
+ - salida plana: la devuelven `renderTerminal()` y `session.output()`
72
+ - salida ANSI: la devuelve `session.ansiOutput()` y, si activas `ansi: true`, tambien se escribe a `stdout`
73
+
74
+ Usa salida plana para snapshots y pruebas. Usa ANSI cuando necesitas cursor, spans visuales, foco o integracion con una terminal real.
75
+
76
+ ## 7. Streams y cleanup
77
+
78
+ `mountTerminal()` puede trabajar sin streams, pero si conectas `stdin` y `stdout` la sesion entra en modo runtime real.
79
+
80
+ Cuando montas con `stdin`:
81
+
82
+ - la sesion escucha `data`
83
+ - intenta activar raw mode si el stream lo soporta
84
+ - intenta restaurarlo al llamar `destroy()`
85
+
86
+ Por eso `destroy()` no es opcional cuando conectaste streams reales.
87
+
88
+ ## 8. Donde seguir
89
+
90
+ - `docs/interaction-model.md` explica que hace cada primitiva interactiva
91
+ - `docs/session-runtime.md` explica lifecycle, streams, clipboard, coordenadas y mouse
92
+ - `docs/cookbook.md` muestra recetas cortas para tareas comunes
93
+ - `docs/api-reference.md` sirve como consulta puntual
@@ -0,0 +1,148 @@
1
+ # Getting Started
2
+
3
+ Esta guia cubre el happy path minimo para empezar con `valyrianjs-terminal`.
4
+
5
+ ## 1. Instala los paquetes
6
+
7
+ ```bash
8
+ npm install valyrianjs-terminal valyrian.js
9
+ ```
10
+
11
+ ## 2. Empieza con render estatico
12
+
13
+ Primero valida layout y contenido sin streams ni runtime interactivo.
14
+
15
+ ```tsx
16
+ /** @jsx v */
17
+ /** @jsxFrag v.fragment */
18
+
19
+ import { v } from "valyrian.js";
20
+ import { Screen, Text, renderTerminal } from "valyrianjs-terminal";
21
+
22
+ const output = renderTerminal(
23
+ <Screen title="Status">
24
+ <Text>Hello terminal</Text>
25
+ <Text>Status: ok</Text>
26
+ </Screen>
27
+ );
28
+
29
+ console.log(output);
30
+ ```
31
+
32
+ Usa este camino cuando quieras:
33
+
34
+ - generar snapshots
35
+ - validar layout
36
+ - probar salida plana sin conectar `stdin` ni `stdout`
37
+
38
+ ## 3. Sube a una sesion interactiva minima
39
+
40
+ Cuando ya necesitas editar texto, manejar foco o reaccionar a teclado, cambia a `mountTerminal()`.
41
+
42
+ ```tsx
43
+ /** @jsx v */
44
+ /** @jsxFrag v.fragment */
45
+
46
+ import { v } from "valyrian.js";
47
+ import { Button, Input, Screen, Text, mountTerminal } from "valyrianjs-terminal";
48
+
49
+ const state = { value: "", saved: "" };
50
+
51
+ const session = mountTerminal(() => (
52
+ <Screen title="Quick Note">
53
+ <Input
54
+ id="note"
55
+ value={state.value}
56
+ placeholder="Write a quick note"
57
+ onchange={(event) => {
58
+ state.value = event.value;
59
+ }}
60
+ onsubmit={(event) => {
61
+ state.saved = event.value;
62
+ }}
63
+ />
64
+ <Button
65
+ id="save"
66
+ onpress={() => {
67
+ state.saved = state.value;
68
+ }}
69
+ >
70
+ Save
71
+ </Button>
72
+ <Text>{state.saved || "Nothing saved yet"}</Text>
73
+ </Screen>
74
+ ));
75
+
76
+ session.focus("note");
77
+ session.dispatchKey("H");
78
+ session.dispatchKey("i");
79
+
80
+ console.log(session.output());
81
+ ```
82
+
83
+ Regla practica: da `id` estables a `Input`, `Button`, `List` y `ScrollView` si quieres usar foco, coordenadas o interaccion programatica.
84
+
85
+ ## 4. Entiende el lifecycle minimo
86
+
87
+ La sesion no guarda tu estado de negocio; vuelve a evaluar la funcion de render con el estado externo actual.
88
+
89
+ ```tsx
90
+ /** @jsx v */
91
+ /** @jsxFrag v.fragment */
92
+
93
+ import { v } from "valyrian.js";
94
+ import { Screen, Text, mountTerminal } from "valyrianjs-terminal";
95
+
96
+ const state = { count: 0 };
97
+
98
+ const session = mountTerminal(() => (
99
+ <Screen>
100
+ <Text>Count: {state.count}</Text>
101
+ </Screen>
102
+ ));
103
+
104
+ state.count += 1;
105
+ session.update();
106
+
107
+ console.log(session.output());
108
+ session.destroy();
109
+ ```
110
+
111
+ Resumen rapido:
112
+
113
+ - `output()` devuelve el frame actual en texto plano
114
+ - `ansiOutput()` devuelve el frame actual como ANSI completo
115
+ - `update()` reevalua la funcion de render
116
+ - `destroy()` desmonta listeners y limpia `stdin` cuando aplica
117
+
118
+ ## 5. Cuando conectar streams
119
+
120
+ Conecta `stdin`, `stdout` y `ansi: true` solo cuando ya vas a correr una UI real en terminal.
121
+
122
+ ```tsx
123
+ /** @jsx v */
124
+ /** @jsxFrag v.fragment */
125
+
126
+ import { v } from "valyrian.js";
127
+ import { Screen, Text, mountTerminal } from "valyrianjs-terminal";
128
+
129
+ const session = mountTerminal(() => (
130
+ <Screen title="Live App">
131
+ <Text>Streaming to the terminal</Text>
132
+ </Screen>
133
+ ), {
134
+ stdin: process.stdin,
135
+ stdout: process.stdout,
136
+ ansi: true
137
+ });
138
+ ```
139
+
140
+ Para pruebas o snapshots, normalmente basta con `renderTerminal()` o `mountTerminal()` sin streams.
141
+
142
+ ## Siguiente lectura
143
+
144
+ - `docs/core-concepts.md`
145
+ - `docs/interaction-model.md`
146
+ - `docs/session-runtime.md`
147
+ - `docs/cookbook.md`
148
+ - `docs/api-reference.md`
@@ -0,0 +1,115 @@
1
+ # Interaction Model
2
+
3
+ Esta guia describe como responden las primitivas interactivas del paquete. Si todavia no tienes claro el modelo base, empieza por `docs/core-concepts.md`. Si necesitas lifecycle, streams o runtime de sesion, sigue con `docs/session-runtime.md`.
4
+
5
+ ## Reglas compartidas
6
+
7
+ - `Tab` avanza al siguiente elemento enfocable.
8
+ - `Shift+Tab` regresa al anterior.
9
+ - Los nodos interactivos necesitan `id` si quieres enfocarlos o activarlos programaticamente.
10
+ - `focusAt(x, y)` y `clickAt(x, y)` dependen de los hitboxes del frame actual.
11
+
12
+ ## `Input`
13
+
14
+ `Input` es una primitiva de edicion de una sola linea con cursor, seleccion y submit.
15
+
16
+ Comportamiento observable:
17
+
18
+ - texto normal: inserta caracteres
19
+ - `Enter`: dispara `onsubmit`
20
+ - `Left` / `Right`: mueve cursor
21
+ - `Shift+Left` / `Shift+Right`: extiende seleccion
22
+ - `Alt+Left` / `Alt+Right`: navega por palabra
23
+ - `Home` / `End`: salta al inicio o final
24
+ - `Ctrl+A`: selecciona todo
25
+ - `Ctrl+C`: copia seleccion
26
+ - `Ctrl+X`: corta seleccion
27
+ - `Ctrl+V`: pega desde clipboard
28
+ - `Backspace` / `Delete`: elimina contenido
29
+
30
+ Handlers principales:
31
+
32
+ - `onchange`
33
+ - `oninput`
34
+ - `onsubmit`
35
+ - `onChangeText`
36
+
37
+ ## `Button`
38
+
39
+ `Button` representa una accion discreta.
40
+
41
+ Comportamiento observable:
42
+
43
+ - responde a `Enter` y `Space` cuando tiene foco
44
+ - responde a `session.click(id)`
45
+ - responde a `session.clickAt(x, y)` cuando el hitbox cae en el boton
46
+
47
+ Handlers principales:
48
+
49
+ - `onpress`
50
+ - `onclick`
51
+ - `action`
52
+ - `onPress`
53
+
54
+ ## `List`
55
+
56
+ `List` modela seleccion y activacion por fila.
57
+
58
+ Comportamiento observable:
59
+
60
+ - `Up` / `Left`: mueve seleccion hacia arriba
61
+ - `Down` / `Right`: mueve seleccion hacia abajo
62
+ - `Enter`: dispara `onpress`
63
+ - el hover por mouse expone fila, indice y valor actual
64
+
65
+ Handlers principales:
66
+
67
+ - `onchange`
68
+ - `onpress`
69
+ - `onhover`
70
+ - `onrowenter`
71
+ - `onrowleave`
72
+ - `oncapturestart`
73
+ - `oncaptureend`
74
+
75
+ Con `pointerCapture`, la lista conserva la interaccion durante drag aunque el puntero salga del hitbox inicial.
76
+
77
+ ## `ScrollView`
78
+
79
+ `ScrollView` recorta contenido vertical y expone interaccion por viewport.
80
+
81
+ Comportamiento observable:
82
+
83
+ - `Up`: desplaza hacia arriba
84
+ - `Down`: desplaza hacia abajo
85
+ - `height`: define el viewport visible
86
+ - `highlightRows`: resalta filas visibles concretas
87
+ - el hover por mouse expone fila visible y texto renderizado
88
+
89
+ Handlers principales:
90
+
91
+ - `onhover`
92
+ - `onrowenter`
93
+ - `onrowleave`
94
+ - `oncapturestart`
95
+ - `oncaptureend`
96
+
97
+ Con `pointerCapture`, el scroll mantiene la interaccion durante drag aunque el puntero salga del viewport.
98
+
99
+ ## Mouse y pointer capture
100
+
101
+ Cuando la sesion recibe eventos SGR de mouse:
102
+
103
+ - `press`: enfoca y activa el hitbox correspondiente
104
+ - `drag`: extiende seleccion en `Input` o actualiza hover en `List` y `ScrollView`
105
+ - `release`: cierra captura y limpia hover cuando corresponde
106
+ - `wheel-up` / `wheel-down`: se traducen a navegacion vertical
107
+
108
+ `pointerCapture` solo aplica hoy a `List` y `ScrollView`.
109
+
110
+ ## Donde seguir
111
+
112
+ - `docs/core-concepts.md` para el modelo mental del paquete
113
+ - `docs/session-runtime.md` para lifecycle, streams, clipboard y runtime
114
+ - `docs/cookbook.md` para recetas practicas
115
+ - `docs/api-reference.md` para consulta puntual de props, payloads y tipos
@@ -0,0 +1,28 @@
1
+ # Local Demo
2
+
3
+ `examples/` existe solo como apoyo de desarrollo local. No forma parte del paquete publicado por npm, no aparece en `exports` y no hay CLI publicada por `valyrianjs-terminal`.
4
+
5
+ ## Archivos
6
+
7
+ - `examples/demo.tsx`: define `createDemoState()` y `DemoApp`; valida composicion de primitivas (`Screen`, `Box`, `View`, `Text`, `Input`, `Button`, `List`, `ScrollView`, `Table`, `Row`, `Td`) y payloads basicos de eventos.
8
+ - `examples/basic.tsx`: valida el camino minimo para usar `renderTerminal()` en snapshot y `mountTerminal()` con `stdin`/`stdout` en local.
9
+ - `examples/cli.tsx`: valida el launcher local con `--help`, `--snapshot`, foco inicial, salida por `Esc` o `Ctrl+C` y cleanup ANSI al cerrar.
10
+
11
+ ## Comandos
12
+
13
+ ```bash
14
+ bun run examples/basic.tsx
15
+ bun run examples/basic.tsx --snapshot
16
+ bun run examples/cli.tsx
17
+ bun run examples/cli.tsx --snapshot
18
+ bun run examples/cli.tsx --help
19
+ bun run test
20
+ bun run typecheck
21
+ bun run build
22
+ ```
23
+
24
+ ## Alcance
25
+
26
+ - `--snapshot` imprime la UI de ejemplo como texto plano.
27
+ - sin `--snapshot`, los ejemplos montan una sesion local conectada a `process.stdin` y `process.stdout`.
28
+ - estos archivos no son una interfaz distribuida a consumidores del paquete; son fixtures manuales para validar el adapter en la maquina local.