@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/cookbook.md
CHANGED
|
@@ -1,179 +1,304 @@
|
|
|
1
1
|
# Cookbook
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Practical recipes for ValyrianJS Terminal. Start here after [Getting Started](./getting-started.md) when you want copyable patterns for common terminal UI tasks.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Input handling
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Use `Input` when a single-line field should update app state and optionally submit on `Enter`.
|
|
8
|
+
|
|
9
|
+
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`.
|
|
8
10
|
|
|
9
11
|
```tsx
|
|
10
|
-
|
|
11
|
-
/** @jsxFrag v.fragment */
|
|
12
|
+
import { Input, Screen, Text, mountTerminal } from "@valyrianjs/terminal";
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
import { Screen, Text, renderTerminal } from "valyrianjs-terminal";
|
|
14
|
+
const state = { value: "", submitted: "" };
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
function App() {
|
|
17
|
+
return (
|
|
18
|
+
<Screen title="Input recipe">
|
|
19
|
+
<Input
|
|
20
|
+
id="name"
|
|
21
|
+
value={state.value}
|
|
22
|
+
placeholder="Name"
|
|
23
|
+
onchange={(event) => {
|
|
24
|
+
state.value = event.value;
|
|
25
|
+
}}
|
|
26
|
+
onsubmit={(event) => {
|
|
27
|
+
state.submitted = event.value;
|
|
28
|
+
}}
|
|
29
|
+
/>
|
|
30
|
+
<Text>{state.submitted || "Nothing submitted yet"}</Text>
|
|
31
|
+
</Screen>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const session = mountTerminal(<App />);
|
|
22
36
|
|
|
23
|
-
|
|
37
|
+
session.focus("name");
|
|
38
|
+
session.dispatchKey("A");
|
|
39
|
+
session.dispatchKey("ENTER");
|
|
40
|
+
|
|
41
|
+
console.log(session.output());
|
|
42
|
+
session.destroy();
|
|
24
43
|
```
|
|
25
44
|
|
|
26
|
-
|
|
45
|
+
Give the field a stable `id` if you want focus, coordinate lookup, or programmatic dispatch.
|
|
27
46
|
|
|
28
|
-
|
|
47
|
+
## Lists and selection
|
|
29
48
|
|
|
30
|
-
|
|
31
|
-
/** @jsx v */
|
|
32
|
-
/** @jsxFrag v.fragment */
|
|
49
|
+
Use `List` when the app needs selection and activation as separate events.
|
|
33
50
|
|
|
34
|
-
|
|
35
|
-
import { Input, Screen, Text, mountTerminal } from "valyrianjs-terminal";
|
|
51
|
+
Related example: [`examples/docs/employees-list.tsx`](../examples/docs/employees-list.tsx). Run it with `bun examples/docs/employees-list.tsx`, choose a person with `J/K` or arrows, and quit with `Ctrl+C`.
|
|
36
52
|
|
|
37
|
-
|
|
53
|
+
```tsx
|
|
54
|
+
import { List, Screen, Text, mountTerminal } from "@valyrianjs/terminal";
|
|
55
|
+
|
|
56
|
+
const state = { selected: "", opened: "" };
|
|
38
57
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
function App() {
|
|
59
|
+
return (
|
|
60
|
+
<Screen title="List recipe">
|
|
61
|
+
<List
|
|
62
|
+
id="menu"
|
|
63
|
+
items={["Inbox", "Today", "Done"]}
|
|
64
|
+
onchange={(event) => {
|
|
65
|
+
state.selected = event.value;
|
|
66
|
+
}}
|
|
67
|
+
onpress={(event) => {
|
|
68
|
+
state.opened = event.value;
|
|
69
|
+
}}
|
|
70
|
+
/>
|
|
71
|
+
<Text>Selected: {state.selected || "-"}</Text>
|
|
72
|
+
<Text>Opened: {state.opened || "-"}</Text>
|
|
73
|
+
</Screen>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const session = mountTerminal(<App />);
|
|
55
78
|
|
|
56
|
-
session.focus("
|
|
57
|
-
session.dispatchKey("
|
|
58
|
-
session.dispatchKey("i");
|
|
79
|
+
session.focus("menu");
|
|
80
|
+
session.dispatchKey("DOWN");
|
|
59
81
|
session.dispatchKey("ENTER");
|
|
60
82
|
|
|
61
|
-
console.log(state.submitted);
|
|
62
83
|
console.log(session.output());
|
|
84
|
+
session.destroy();
|
|
63
85
|
```
|
|
64
86
|
|
|
65
|
-
|
|
87
|
+
For large lists, add `virtualized` and place the list in a bounded region such as a filled pane or split.
|
|
88
|
+
|
|
89
|
+
## Local state to Valyrian state module bridge
|
|
90
|
+
|
|
91
|
+
Start with local objects for small examples. Use Valyrian state modules such as `createPulseStore` when shared state and named transitions make the UI easier to maintain.
|
|
66
92
|
|
|
67
|
-
|
|
93
|
+
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`.
|
|
68
94
|
|
|
69
95
|
```tsx
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
session
|
|
96
|
+
import { createPulseStore } from "valyrian.js/pulses";
|
|
97
|
+
import { Button, Screen, Text, mountTerminal } from "@valyrianjs/terminal";
|
|
98
|
+
|
|
99
|
+
const counter = createPulseStore(
|
|
100
|
+
{ count: 0 },
|
|
101
|
+
{
|
|
102
|
+
increment(state) {
|
|
103
|
+
state.count += 1;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
function App() {
|
|
109
|
+
return (
|
|
110
|
+
<Screen title="State recipe">
|
|
111
|
+
<Text>Count: {counter.state.count}</Text>
|
|
112
|
+
<Button id="increment" onpress={() => counter.increment()}>
|
|
113
|
+
Increment
|
|
114
|
+
</Button>
|
|
115
|
+
</Screen>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const session = mountTerminal(<App />);
|
|
120
|
+
|
|
121
|
+
session.focus("increment");
|
|
122
|
+
session.dispatchKey("ENTER");
|
|
94
123
|
|
|
95
124
|
console.log(session.output());
|
|
125
|
+
session.destroy();
|
|
96
126
|
```
|
|
97
127
|
|
|
98
|
-
|
|
128
|
+
The app owns the store. The terminal session renders the current state and dispatches interaction events.
|
|
99
129
|
|
|
100
|
-
Usalo cuando quieras separar el item actualmente seleccionado del item activado con `Enter`.
|
|
101
130
|
|
|
102
|
-
|
|
103
|
-
/** @jsx v */
|
|
104
|
-
/** @jsxFrag v.fragment */
|
|
131
|
+
## Primitive Gallery mini apps
|
|
105
132
|
|
|
106
|
-
|
|
107
|
-
import { List, Screen, Text, mountTerminal } from "valyrianjs-terminal";
|
|
133
|
+
Use [Primitive Gallery](./primitive-gallery.md) when you want to pick the right primitive before copying a recipe. The gallery shows what each primitive is, where it fits, core props, a short example, and a complete mini app.
|
|
108
134
|
|
|
109
|
-
|
|
135
|
+
Complete primitive demos:
|
|
110
136
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
));
|
|
137
|
+
- **Operations Workspace** ([`examples/docs/primitive-layout-shell.tsx`](../examples/docs/primitive-layout-shell.tsx)). Run it with `bun examples/docs/primitive-layout-shell.tsx`, inspect the shell regions, and quit with `Ctrl+C`.
|
|
138
|
+
- **Ticket Intake** ([`examples/docs/primitive-input-workbench.tsx`](../examples/docs/primitive-input-workbench.tsx)). Run it with `bun examples/docs/primitive-input-workbench.tsx`, type a summary, move focus with `Tab`, save with `Enter`, and quit with `Ctrl+C`.
|
|
139
|
+
- **Service Explorer** ([`examples/docs/primitive-data-explorer.tsx`](../examples/docs/primitive-data-explorer.tsx)). Run it with `bun examples/docs/primitive-data-explorer.tsx`, move through items with `J/K`, and quit with `Ctrl+C`.
|
|
140
|
+
- **Activity Console** ([`examples/docs/primitive-activity-console.tsx`](../examples/docs/primitive-activity-console.tsx)). Run it with `bun examples/docs/primitive-activity-console.tsx`, add events with `Enter`, scroll the viewport with `Up/Down`, and quit with `Ctrl+C`.
|
|
141
|
+
- **Command Panel** ([`examples/docs/primitive-command-panel.tsx`](../examples/docs/primitive-command-panel.tsx)). Run it with `bun examples/docs/primitive-command-panel.tsx`, type a filter, choose commands with arrows, pick with `Enter`, and quit with `Ctrl+C`.
|
|
127
142
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
143
|
+
Use API Reference for prop-level details after you choose the primitive family.
|
|
144
|
+
|
|
145
|
+
## Valyrian.js modules in terminal apps
|
|
146
|
+
|
|
147
|
+
Valyrian.js modules let terminal apps use the same app-layer tools you would use in Valyrian browser or server apps. The terminal adapter owns rendering, focus, input dispatch, output, and cleanup. Your app owns state, data, persistence, commands, and business rules.
|
|
148
|
+
|
|
149
|
+
Read the dedicated guide at [`docs/valyrian-modules.md`](./valyrian-modules.md) for deeper patterns around `valyrian.js/request`, `valyrian.js/query`, `valyrian.js/tasks`, state modules, forms, persistence, localization, money formatting, and utilities.
|
|
150
|
+
|
|
151
|
+
Complete terminal demos:
|
|
152
|
+
|
|
153
|
+
- **Operations Workbench** ([`examples/docs/module-state-workbench.tsx`](../examples/docs/module-state-workbench.tsx)). Run it with `bun examples/docs/module-state-workbench.tsx`, select jobs with `J/K`, dispatch with `Enter`, mark work with `D` or `B`, reset with `R`, and quit with `Ctrl+C`.
|
|
154
|
+
- **API Operations Dashboard** ([`examples/docs/module-api-dashboard.tsx`](../examples/docs/module-api-dashboard.tsx)). Run it with `bun examples/docs/module-api-dashboard.tsx`, refresh with `R`, toggle a controlled error with `E`, invalidate with `I`, run or cancel the task with `T` or `C`, and quit with `Ctrl+C`.
|
|
155
|
+
- **Billing/Settings Wizard** ([`examples/docs/module-form-workflow.tsx`](../examples/docs/module-form-workflow.tsx)). Run it with `bun examples/docs/module-form-workflow.tsx`, fill values with `N`, switch language with `L`, save with `S` or `Enter`, reset with `R`, clear saved data with `X`, and quit with `Ctrl+C`.
|
|
156
|
+
|
|
157
|
+
## Overlay or modal-like composition
|
|
158
|
+
|
|
159
|
+
Use `Overlay` and `FocusScope` for app-local popovers or lightweight dialog surfaces. The app owns whether the surface is present and what action is performed.
|
|
160
|
+
|
|
161
|
+
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`.
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
import { FocusScope, Input, List, Overlay, Screen, Text, mountTerminal } from "@valyrianjs/terminal";
|
|
165
|
+
|
|
166
|
+
const commands = ["Open file", "Run task", "Toggle panel"];
|
|
167
|
+
const state = { query: "", executed: "" };
|
|
168
|
+
|
|
169
|
+
function App() {
|
|
170
|
+
const visible = commands.filter((command) =>
|
|
171
|
+
command.toLowerCase().includes(state.query.toLowerCase())
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<Screen title="Overlay recipe">
|
|
176
|
+
<Text>{state.executed ? `Executed: ${state.executed}` : "Choose a command"}</Text>
|
|
177
|
+
<Overlay x={2} y={2} width={40} height={6} trapFocus>
|
|
178
|
+
<FocusScope>
|
|
179
|
+
<Input
|
|
180
|
+
id="query"
|
|
181
|
+
value={state.query}
|
|
182
|
+
placeholder="Search"
|
|
183
|
+
onchange={(event) => {
|
|
184
|
+
state.query = event.value;
|
|
185
|
+
}}
|
|
186
|
+
/>
|
|
187
|
+
<List
|
|
188
|
+
id="results"
|
|
189
|
+
items={visible}
|
|
190
|
+
onpress={(event) => {
|
|
191
|
+
state.executed = event.value;
|
|
192
|
+
}}
|
|
193
|
+
/>
|
|
194
|
+
</FocusScope>
|
|
195
|
+
</Overlay>
|
|
196
|
+
</Screen>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const session = mountTerminal(<App />);
|
|
201
|
+
|
|
202
|
+
session.focus("query");
|
|
203
|
+
session.dispatchKey("R");
|
|
204
|
+
session.focus("results");
|
|
131
205
|
session.dispatchKey("ENTER");
|
|
132
206
|
|
|
133
|
-
console.log(
|
|
134
|
-
|
|
207
|
+
console.log(session.output());
|
|
208
|
+
session.destroy();
|
|
135
209
|
```
|
|
136
210
|
|
|
137
|
-
|
|
211
|
+
This local composition uses public focus, overlay, input, and list primitives. Keep shared command catalogs, permissions, and workflow orchestration in the app layer when the palette grows.
|
|
138
212
|
|
|
139
|
-
|
|
213
|
+
## Log view / follow-tail behavior with `LogView`
|
|
214
|
+
|
|
215
|
+
Use `LogView` for append-only logs or transcript-like panes. `followTail` is a `LogView` option, not a standalone primitive.
|
|
216
|
+
|
|
217
|
+
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`.
|
|
140
218
|
|
|
141
219
|
```tsx
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
220
|
+
import { LogView, Screen, mountTerminal } from "@valyrianjs/terminal";
|
|
221
|
+
|
|
222
|
+
const entries = [
|
|
223
|
+
{ id: "1", content: "User: hello" },
|
|
224
|
+
{ id: "2", content: "System: ready" },
|
|
225
|
+
{ id: "3", content: "User: summarize the latest output" }
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
function App() {
|
|
229
|
+
return (
|
|
230
|
+
<Screen title="Log recipe">
|
|
231
|
+
<LogView
|
|
232
|
+
height={3}
|
|
233
|
+
entries={entries}
|
|
234
|
+
followTail
|
|
235
|
+
emptyText="No entries yet"
|
|
236
|
+
renderEntry={(entry) => entry.content}
|
|
237
|
+
/>
|
|
238
|
+
</Screen>
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const session = mountTerminal(<App />, { cols: 80, rows: 8 });
|
|
161
243
|
|
|
162
|
-
session.dispatchKey("DOWN");
|
|
163
244
|
console.log(session.output());
|
|
164
|
-
|
|
245
|
+
session.destroy();
|
|
165
246
|
```
|
|
166
247
|
|
|
167
|
-
|
|
248
|
+
Keep log state in your app and pass entries into `LogView`.
|
|
168
249
|
|
|
169
|
-
|
|
250
|
+
## Full-terminal layout
|
|
251
|
+
|
|
252
|
+
Use `Screen`, `Fixed`, `Split`, and `Pane` when a session should fill the available terminal size. `Split` uses the available body area from context, and panes take available width by default. Use `fill` when a surface should consume the full available height; block containers otherwise stack at content height.
|
|
253
|
+
|
|
254
|
+
Full 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`.
|
|
170
255
|
|
|
171
256
|
```tsx
|
|
172
|
-
|
|
173
|
-
|
|
257
|
+
import { Fixed, Pane, Screen, Split, Text, mountTerminal } from "@valyrianjs/terminal";
|
|
258
|
+
|
|
259
|
+
function App() {
|
|
260
|
+
return (
|
|
261
|
+
<Screen title="Workspace">
|
|
262
|
+
<Fixed position="top" size={3}>
|
|
263
|
+
<Pane fill style={{ background: "#111111", padding: 1 }}>
|
|
264
|
+
<Text>Header</Text>
|
|
265
|
+
</Pane>
|
|
266
|
+
</Fixed>
|
|
267
|
+
<Split direction="row" gap={1}>
|
|
268
|
+
<Pane fill style={{ background: "#111111", padding: 1 }}>
|
|
269
|
+
<Text>Main content</Text>
|
|
270
|
+
</Pane>
|
|
271
|
+
<Pane fill style={{ background: "#111111", padding: 1 }}>
|
|
272
|
+
<Text>Side panel</Text>
|
|
273
|
+
</Pane>
|
|
274
|
+
</Split>
|
|
275
|
+
<Fixed position="bottom" size={3}>
|
|
276
|
+
<Pane fill style={{ background: "#111111", padding: 1 }}>
|
|
277
|
+
<Text>Ready</Text>
|
|
278
|
+
</Pane>
|
|
279
|
+
</Fixed>
|
|
280
|
+
</Screen>
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const session = mountTerminal(<App />, { cols: 80, rows: 24 });
|
|
285
|
+
|
|
286
|
+
console.log(session.output());
|
|
287
|
+
session.destroy();
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Styles are expressed as recipes or inline style objects. The renderer translates those styles to supported terminal output for the current session, so avoid depending on raw ANSI sequences in rendered content. For style recipes in a runnable ANSI app, run `bun examples/docs/style-system.tsx`, use `Tab`, `Enter`, and `W` to change state, and quit with `Ctrl+C`; or open [`examples/docs/style-system.tsx`](../examples/docs/style-system.tsx). For responsive split sizing, 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).
|
|
291
|
+
|
|
292
|
+
For a full-screen responsive pizza builder with ingredient selection, `Split` fractions, a running total, and simulated checkout, run `bun examples/docs/pizza-builder.tsx`, choose toppings with `Up/Down` and `Space`, press `Enter`, resize with `R`, clear with `C`, and quit with `Ctrl+C`; or open [`examples/docs/pizza-builder.tsx`](../examples/docs/pizza-builder.tsx).
|
|
293
|
+
|
|
294
|
+
## Clipboard adapter
|
|
174
295
|
|
|
175
|
-
|
|
176
|
-
|
|
296
|
+
Use a clipboard adapter when copy and paste should go through an application-provided clipboard implementation.
|
|
297
|
+
|
|
298
|
+
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`.
|
|
299
|
+
|
|
300
|
+
```tsx
|
|
301
|
+
import { Input, Screen, mountTerminal } from "@valyrianjs/terminal";
|
|
177
302
|
|
|
178
303
|
const state = { value: "abcd" };
|
|
179
304
|
const clipboard = {
|
|
@@ -186,101 +311,71 @@ const clipboard = {
|
|
|
186
311
|
}
|
|
187
312
|
};
|
|
188
313
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
314
|
+
function App() {
|
|
315
|
+
return (
|
|
316
|
+
<Screen title="Clipboard recipe">
|
|
317
|
+
<Input
|
|
318
|
+
id="name"
|
|
319
|
+
value={state.value}
|
|
320
|
+
onchange={(event) => {
|
|
321
|
+
state.value = event.value;
|
|
322
|
+
}}
|
|
323
|
+
/>
|
|
324
|
+
</Screen>
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const session = mountTerminal(<App />, { clipboard });
|
|
200
329
|
|
|
201
330
|
session.focus("name");
|
|
202
|
-
session.dispatchKey("
|
|
203
|
-
session.dispatchKey("SHIFT_RIGHT");
|
|
204
|
-
session.dispatchKey("SHIFT_RIGHT");
|
|
331
|
+
session.dispatchKey("CTRL_A");
|
|
205
332
|
session.dispatchKey("CTRL_C");
|
|
206
333
|
|
|
207
|
-
clipboard.value = "XY";
|
|
208
|
-
session.dispatchKey("END");
|
|
209
|
-
session.dispatchKey("CTRL_V");
|
|
210
|
-
|
|
211
334
|
console.log(session.clipboard());
|
|
212
|
-
|
|
335
|
+
session.destroy();
|
|
213
336
|
```
|
|
214
337
|
|
|
215
|
-
|
|
338
|
+
Use `clipboard: false` when a session should rely on its local clipboard buffer.
|
|
216
339
|
|
|
217
|
-
|
|
340
|
+
## Coordinate-based interaction
|
|
218
341
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
342
|
+
Use `focusAt` and `clickAt` when an adapter receives frame coordinates instead of known ids.
|
|
343
|
+
|
|
344
|
+
Related example: [`examples/docs/cursor.tsx`](../examples/docs/cursor.tsx). Run it with `bun examples/docs/cursor.tsx`, type text, press `C`, and quit with `Ctrl+C`.
|
|
222
345
|
|
|
223
|
-
|
|
224
|
-
import { Button, Input, Screen, mountTerminal } from "valyrianjs
|
|
346
|
+
```tsx
|
|
347
|
+
import { Button, Input, Screen, mountTerminal } from "@valyrianjs/terminal";
|
|
225
348
|
|
|
226
349
|
const state = { clicks: 0 };
|
|
227
350
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
<
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
351
|
+
function App() {
|
|
352
|
+
return (
|
|
353
|
+
<Screen title="Coordinates">
|
|
354
|
+
<Input id="name" value="abc" />
|
|
355
|
+
<Button id="save" onpress={() => {
|
|
356
|
+
state.clicks += 1;
|
|
357
|
+
}}>
|
|
358
|
+
Save
|
|
359
|
+
</Button>
|
|
360
|
+
</Screen>
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const session = mountTerminal(<App />);
|
|
238
365
|
|
|
239
366
|
session.focusAt(2, 1);
|
|
240
367
|
session.clickAt(3, 2);
|
|
241
368
|
|
|
242
369
|
console.log(session.output());
|
|
243
370
|
console.log(state.clicks);
|
|
371
|
+
session.destroy();
|
|
244
372
|
```
|
|
245
373
|
|
|
246
|
-
##
|
|
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
|
|
374
|
+
## See also
|
|
281
375
|
|
|
282
|
-
-
|
|
283
|
-
-
|
|
284
|
-
-
|
|
285
|
-
-
|
|
286
|
-
-
|
|
376
|
+
- [Getting Started](./getting-started.md) for the first project.
|
|
377
|
+
- [Core Concepts](./core-concepts.md) for the mental model.
|
|
378
|
+
- [Interaction Model](./interaction-model.md) for focus, keyboard, mouse, and event behavior.
|
|
379
|
+
- [Valyrian Modules](./valyrian-modules.md)
|
|
380
|
+
- [Session Runtime](./session-runtime.md) for streams and host integration.
|
|
381
|
+
- [API Reference](./api-reference.md) for props, payloads, and session methods.
|