@promptctl/rich-js 0.18.1 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -8
- package/dist/core/box.d.ts +3 -1
- package/dist/core/box.js +6 -13
- package/dist/core/cells.d.ts +61 -28
- package/dist/core/cells.js +171 -124
- package/dist/core/clock.d.ts +48 -0
- package/dist/core/clock.js +42 -0
- package/dist/core/color.d.ts +99 -18
- package/dist/core/color.js +334 -146
- package/dist/core/console.d.ts +38 -7
- package/dist/core/console.js +159 -90
- package/dist/core/easing.d.ts +86 -0
- package/dist/core/easing.js +171 -0
- package/dist/core/env.d.ts +16 -0
- package/dist/core/env.js +16 -0
- package/dist/core/export-html.js +1 -4
- package/dist/core/export-lines.d.ts +22 -13
- package/dist/core/export-lines.js +37 -19
- package/dist/core/export-svg.d.ts +49 -0
- package/dist/core/export-svg.js +213 -0
- package/dist/core/fnv1a.d.ts +10 -0
- package/dist/core/fnv1a.js +17 -0
- package/dist/core/highlighter.d.ts +2 -2
- package/dist/core/highlighter.js +113 -47
- package/dist/core/json.js +1 -1
- package/dist/core/markup.d.ts +28 -7
- package/dist/core/markup.js +235 -312
- package/dist/core/measure.d.ts +3 -3
- package/dist/core/measure.js +12 -7
- package/dist/core/memo.d.ts +19 -0
- package/dist/core/memo.js +34 -0
- package/dist/core/noise.d.ts +31 -0
- package/dist/core/noise.js +94 -0
- package/dist/core/osc8.d.ts +6 -6
- package/dist/core/osc8.js +9 -21
- package/dist/core/paint.d.ts +107 -0
- package/dist/core/paint.js +161 -0
- package/dist/core/place.d.ts +1 -1
- package/dist/core/place.js +4 -6
- package/dist/core/pretty.d.ts +126 -2
- package/dist/core/pretty.js +571 -105
- package/dist/core/protocol.d.ts +43 -3
- package/dist/core/protocol.js +23 -2
- package/dist/core/render.d.ts +33 -30
- package/dist/core/render.js +43 -83
- package/dist/core/segment.d.ts +6 -5
- package/dist/core/segment.js +11 -15
- package/dist/core/selection.d.ts +12 -0
- package/dist/core/selection.js +14 -0
- package/dist/core/strip.d.ts +116 -74
- package/dist/core/strip.js +266 -217
- package/dist/core/style.d.ts +27 -7
- package/dist/core/style.js +106 -41
- package/dist/core/text.d.ts +43 -16
- package/dist/core/text.js +180 -59
- package/dist/core/wrap.d.ts +5 -0
- package/dist/core/wrap.js +16 -3
- package/dist/host/app.d.ts +95 -17
- package/dist/host/app.js +201 -61
- package/dist/host/index.d.ts +4 -1
- package/dist/host/index.js +1 -0
- package/dist/host/input.d.ts +84 -0
- package/dist/host/input.js +498 -0
- package/dist/host/terminal-host.d.ts +15 -2
- package/dist/host/terminal-host.js +2 -0
- package/dist/index.d.ts +26 -14
- package/dist/index.js +17 -7
- package/dist/node/prompt.d.ts +13 -0
- package/dist/node/prompt.js +30 -9
- package/dist/node/save.d.ts +4 -3
- package/dist/node/save.js +6 -3
- package/dist/node/terminal-host.d.ts +10 -2
- package/dist/node/terminal-host.js +7 -0
- package/dist/node/traceback.d.ts +2 -1
- package/dist/node/traceback.js +3 -39
- package/dist/renderables/align.js +2 -9
- package/dist/renderables/columns.d.ts +45 -29
- package/dist/renderables/columns.js +142 -103
- package/dist/renderables/constrain.js +6 -12
- package/dist/renderables/effect.d.ts +113 -0
- package/dist/renderables/effect.js +182 -0
- package/dist/renderables/effects.d.ts +252 -0
- package/dist/renderables/effects.js +565 -0
- package/dist/renderables/embed.d.ts +94 -31
- package/dist/renderables/embed.js +141 -45
- package/dist/renderables/group.d.ts +6 -3
- package/dist/renderables/group.js +5 -0
- package/dist/renderables/layout.d.ts +6 -23
- package/dist/renderables/layout.js +24 -113
- package/dist/renderables/list-view.d.ts +42 -0
- package/dist/renderables/list-view.js +78 -0
- package/dist/renderables/live.d.ts +40 -16
- package/dist/renderables/live.js +96 -83
- package/dist/renderables/markdown.d.ts +16 -2
- package/dist/renderables/markdown.js +521 -118
- package/dist/renderables/padding.d.ts +22 -1
- package/dist/renderables/padding.js +30 -24
- package/dist/renderables/panel.d.ts +31 -33
- package/dist/renderables/panel.js +137 -141
- package/dist/renderables/progress.d.ts +110 -16
- package/dist/renderables/progress.js +212 -81
- package/dist/renderables/progressBar.d.ts +24 -4
- package/dist/renderables/progressBar.js +78 -23
- package/dist/renderables/prompt.d.ts +37 -15
- package/dist/renderables/prompt.js +125 -85
- package/dist/renderables/ratio.d.ts +123 -0
- package/dist/renderables/ratio.js +213 -0
- package/dist/renderables/rule.d.ts +3 -2
- package/dist/renderables/rule.js +50 -52
- package/dist/renderables/spinner.d.ts +28 -2
- package/dist/renderables/spinner.js +52 -19
- package/dist/renderables/status.d.ts +13 -7
- package/dist/renderables/status.js +15 -29
- package/dist/renderables/syntax.d.ts +37 -7
- package/dist/renderables/syntax.js +134 -83
- package/dist/renderables/table.d.ts +58 -20
- package/dist/renderables/table.js +373 -197
- package/dist/renderables/traceback.d.ts +5 -4
- package/dist/renderables/traceback.js +239 -68
- package/dist/renderables/tree.d.ts +10 -2
- package/dist/renderables/tree.js +61 -34
- package/dist/renderables/viewport.d.ts +30 -0
- package/dist/renderables/viewport.js +61 -7
- package/dist/template-bindings/color-funcs.d.ts +31 -9
- package/dist/template-bindings/color-funcs.js +40 -14
- package/dist/template-bindings/helpers.d.ts +4 -2
- package/dist/template-bindings/helpers.js +5 -20
- package/dist/template-bindings/index.d.ts +29 -17
- package/dist/template-bindings/index.js +36 -20
- package/dist/template-bindings/palette-funcs.d.ts +3 -1
- package/dist/template-bindings/palette-funcs.js +11 -7
- package/dist/template-bindings/style-funcs.js +4 -2
- package/dist/themes/buildPalette.d.ts +24 -3
- package/dist/themes/buildPalette.js +52 -8
- package/dist/themes/colorMath.d.ts +29 -17
- package/dist/themes/colorMath.js +74 -48
- package/dist/themes/colorRef.d.ts +2 -17
- package/dist/themes/colorRef.js +13 -31
- package/dist/themes/palette.d.ts +24 -0
- package/dist/themes/palette.js +46 -3
- package/dist/themes/ramp.d.ts +21 -34
- package/dist/themes/ramp.js +23 -42
- package/dist/themes/registry.js +39 -28
- package/dist/widgets/button.d.ts +2 -6
- package/dist/widgets/button.js +9 -40
- package/dist/widgets/checkbox.d.ts +2 -5
- package/dist/widgets/checkbox.js +9 -31
- package/dist/widgets/dropdown.d.ts +2 -5
- package/dist/widgets/dropdown.js +17 -51
- package/dist/widgets/event-router.d.ts +31 -40
- package/dist/widgets/event-router.js +52 -483
- package/dist/widgets/index.d.ts +2 -1
- package/dist/widgets/ink.d.ts +22 -0
- package/dist/widgets/ink.js +31 -0
- package/dist/widgets/slider.d.ts +2 -5
- package/dist/widgets/slider.js +11 -34
- package/dist/widgets/text-input.d.ts +19 -10
- package/dist/widgets/text-input.js +156 -147
- package/dist/widgets/themed-widget.d.ts +20 -0
- package/dist/widgets/themed-widget.js +89 -0
- package/dist/widgets/toggle.d.ts +2 -5
- package/dist/widgets/toggle.js +8 -31
- package/dist/widgets/types.d.ts +8 -25
- package/dist/widgets/types.js +8 -0
- package/dist/widgets/widget-app.d.ts +24 -7
- package/dist/widgets/widget-app.js +35 -18
- package/dist/widgets/widget-base.d.ts +2 -0
- package/dist/widgets/widget-base.js +9 -2
- package/package.json +31 -17
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal input: the bytes a terminal sends for keys and the pointer,
|
|
3
|
+
* parsed into `KeyPress` and `ScreenMouseEvent` values, and the one name
|
|
4
|
+
* each key goes by.
|
|
5
|
+
*
|
|
6
|
+
* [LAW:single-enforcer] Escape-sequence parsing lives only here. `App` owns
|
|
7
|
+
* the one parser over its host's input; a `WidgetApp` routes the events `App`
|
|
8
|
+
* hears, and no program reads its terminal's bytes itself.
|
|
9
|
+
*
|
|
10
|
+
* [LAW:dataflow-not-control-flow] The same parse pipeline runs for every
|
|
11
|
+
* input chunk: append → consume one event at a time until the buffer can't
|
|
12
|
+
* yield more. The byte's value, not a side-mode, decides which event is
|
|
13
|
+
* emitted. There is no "are we mid-sequence" mode flag — the buffer head
|
|
14
|
+
* carries all the state we need, so a UTF-8 character or an escape sequence
|
|
15
|
+
* split across two chunks is completed by the second.
|
|
16
|
+
*
|
|
17
|
+
* Lone-ESC handling: a bare `\x1b` is ambiguous (escape key vs. start of a
|
|
18
|
+
* CSI sequence). When the buffer is drained but ends with a lone ESC, the
|
|
19
|
+
* parser defers emission via setTimeout(0). The next chunk cancels the timer
|
|
20
|
+
* if it extends the sequence. `flush()` drains it synchronously.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* The one name a key goes by — what a keymap is keyed by and what
|
|
24
|
+
* `quitKeys` lists. A key that types a character is named by it (`q`, `G`,
|
|
25
|
+
* `>`); any other is named by its key (`up`, `enter`, `space`, `f5`). Held
|
|
26
|
+
* modifiers come first, always in the order `ctrl+`, `meta+`, `shift+`:
|
|
27
|
+
* `ctrl+c`, `shift+tab`, `meta+left`. Shift is not named on a character,
|
|
28
|
+
* which already carries it: Shift+G is `G`.
|
|
29
|
+
*/
|
|
30
|
+
export function keyName(press) {
|
|
31
|
+
const typed = press.character !== "" && press.key !== "space";
|
|
32
|
+
const modifiers = [
|
|
33
|
+
press.ctrl ? "ctrl+" : "",
|
|
34
|
+
press.meta ? "meta+" : "",
|
|
35
|
+
press.shift && !typed ? "shift+" : "",
|
|
36
|
+
];
|
|
37
|
+
return modifiers.join("") + (typed ? press.character : press.key);
|
|
38
|
+
}
|
|
39
|
+
// Single-byte → key name table for the trivial cases.
|
|
40
|
+
const SINGLE_BYTE_KEYS = {
|
|
41
|
+
0x09: "tab",
|
|
42
|
+
0x0a: "enter",
|
|
43
|
+
0x0d: "enter",
|
|
44
|
+
0x1b: "escape",
|
|
45
|
+
0x08: "backspace",
|
|
46
|
+
0x7f: "backspace",
|
|
47
|
+
0x20: "space",
|
|
48
|
+
};
|
|
49
|
+
// Final-byte → key name for the simple `ESC[<X>` arrow / nav forms.
|
|
50
|
+
const CSI_LETTER_KEYS = {
|
|
51
|
+
A: "up",
|
|
52
|
+
B: "down",
|
|
53
|
+
C: "right",
|
|
54
|
+
D: "left",
|
|
55
|
+
H: "home",
|
|
56
|
+
F: "end",
|
|
57
|
+
Z: "tab", // shift+tab encodes as ESC[Z
|
|
58
|
+
};
|
|
59
|
+
// `ESC[<n>~` numeric forms for navigation / function keys.
|
|
60
|
+
const CSI_TILDE_KEYS = {
|
|
61
|
+
"1": "home",
|
|
62
|
+
"2": "insert",
|
|
63
|
+
"3": "delete",
|
|
64
|
+
"4": "end",
|
|
65
|
+
"5": "pageup",
|
|
66
|
+
"6": "pagedown",
|
|
67
|
+
"7": "home",
|
|
68
|
+
"8": "end",
|
|
69
|
+
"11": "f1",
|
|
70
|
+
"12": "f2",
|
|
71
|
+
"13": "f3",
|
|
72
|
+
"14": "f4",
|
|
73
|
+
"15": "f5",
|
|
74
|
+
"17": "f6",
|
|
75
|
+
"18": "f7",
|
|
76
|
+
"19": "f8",
|
|
77
|
+
"20": "f9",
|
|
78
|
+
"21": "f10",
|
|
79
|
+
"23": "f11",
|
|
80
|
+
"24": "f12",
|
|
81
|
+
};
|
|
82
|
+
// SS3 form `ESC O X` for F1–F4 (and arrow keys on some terminals).
|
|
83
|
+
const SS3_KEYS = {
|
|
84
|
+
P: "f1",
|
|
85
|
+
Q: "f2",
|
|
86
|
+
R: "f3",
|
|
87
|
+
S: "f4",
|
|
88
|
+
A: "up",
|
|
89
|
+
B: "down",
|
|
90
|
+
C: "right",
|
|
91
|
+
D: "left",
|
|
92
|
+
H: "home",
|
|
93
|
+
F: "end",
|
|
94
|
+
};
|
|
95
|
+
// Every name a key with no glyph goes by.
|
|
96
|
+
const NAMED_KEYS = new Set([
|
|
97
|
+
...Object.values(SINGLE_BYTE_KEYS),
|
|
98
|
+
...Object.values(CSI_LETTER_KEYS),
|
|
99
|
+
...Object.values(CSI_TILDE_KEYS),
|
|
100
|
+
...Object.values(SS3_KEYS),
|
|
101
|
+
]);
|
|
102
|
+
// [LAW:one-source-of-truth] The glyphs a Ctrl chord is named by are what
|
|
103
|
+
// `ctrlKey` makes of the control bytes no named key claims.
|
|
104
|
+
const CTRL_GLYPHS = new Set(Array.from({ length: 0x20 }, (_, byte) => byte)
|
|
105
|
+
.filter((byte) => byte !== 0 && !(byte in SINGLE_BYTE_KEYS))
|
|
106
|
+
.map((byte) => ctrlKey(byte).key));
|
|
107
|
+
/**
|
|
108
|
+
* `name`, if `keyName` can produce it: modifiers in its order, then a named
|
|
109
|
+
* key or one glyph, with no `shift+` on a glyph and, after `ctrl+`, only a
|
|
110
|
+
* glyph a control byte stands for.
|
|
111
|
+
* [LAW:parse-dont-validate] A name no key can produce throws here, at the
|
|
112
|
+
* one place a program hands names in, rather than binding a key that never fires.
|
|
113
|
+
*/
|
|
114
|
+
export function parseKeyName(name) {
|
|
115
|
+
const [, ctrl, , shift, base] = /^(ctrl\+)?(meta\+)?(shift\+)?(.*)$/u.exec(name);
|
|
116
|
+
const glyph = [...base].length === 1 && !shift && (!ctrl || CTRL_GLYPHS.has(base));
|
|
117
|
+
const producible = NAMED_KEYS.has(base) || glyph;
|
|
118
|
+
if (!producible)
|
|
119
|
+
throw new Error(`no key is named ${JSON.stringify(name)}; see keyName`);
|
|
120
|
+
return name;
|
|
121
|
+
}
|
|
122
|
+
const ESC = 0x1b;
|
|
123
|
+
const LBRACKET = 0x5b; // [
|
|
124
|
+
const LANGLE = 0x3c; // <
|
|
125
|
+
const O_BYTE = 0x4f; // O
|
|
126
|
+
const M_UPPER = 0x4d; // M
|
|
127
|
+
const M_LOWER = 0x6d; // m
|
|
128
|
+
// [LAW:single-enforcer] Shared encode/decode singletons. The parser
|
|
129
|
+
// receives `Uint8Array | string` from the host and walks bytes through
|
|
130
|
+
// its state machine; conversion happens at the two boundaries (string
|
|
131
|
+
// input → bytes via TextEncoder; printable-byte run → JS string via
|
|
132
|
+
// TextDecoder) and only there. Module-level instances keep the seam
|
|
133
|
+
// allocation-free and runtime-agnostic — both APIs are universal across
|
|
134
|
+
// node and browser.
|
|
135
|
+
const UTF8_ENCODER = new TextEncoder();
|
|
136
|
+
const UTF8_DECODER = new TextDecoder("utf-8");
|
|
137
|
+
const ASCII_DECODER = new TextDecoder("ascii");
|
|
138
|
+
const EMPTY_BYTES = new Uint8Array(0);
|
|
139
|
+
// Concatenate two byte arrays into a fresh Uint8Array. Replaces
|
|
140
|
+
// `Buffer.concat([...])` so the parser holds no node-specific globals.
|
|
141
|
+
function concatBytes(a, b) {
|
|
142
|
+
if (a.length === 0)
|
|
143
|
+
return b;
|
|
144
|
+
if (b.length === 0)
|
|
145
|
+
return a;
|
|
146
|
+
const merged = new Uint8Array(a.length + b.length);
|
|
147
|
+
merged.set(a, 0);
|
|
148
|
+
merged.set(b, a.length);
|
|
149
|
+
return merged;
|
|
150
|
+
}
|
|
151
|
+
export class InputParser {
|
|
152
|
+
sink;
|
|
153
|
+
// [LAW:types-are-the-program] The parse buffer is `Uint8Array`, not
|
|
154
|
+
// `Buffer` — node's Buffer extends Uint8Array, so Buffer chunks from
|
|
155
|
+
// process.stdin satisfy this type, while a browser host can emit native
|
|
156
|
+
// Uint8Array without depending on a Buffer global polyfill.
|
|
157
|
+
buffer = EMPTY_BYTES;
|
|
158
|
+
// [LAW:types-are-the-program] `setTimeout`/`clearTimeout` are universal
|
|
159
|
+
// across node and browser; `setImmediate` is node-only.
|
|
160
|
+
escTimer;
|
|
161
|
+
constructor(sink) {
|
|
162
|
+
this.sink = sink;
|
|
163
|
+
}
|
|
164
|
+
/** Feed a chunk of bytes (or a string of them) into the parser. */
|
|
165
|
+
feed(chunk) {
|
|
166
|
+
const next = typeof chunk === "string" ? UTF8_ENCODER.encode(chunk) : chunk;
|
|
167
|
+
this.buffer = concatBytes(this.buffer, next);
|
|
168
|
+
this.cancelEscape();
|
|
169
|
+
this.drain();
|
|
170
|
+
// [LAW:dataflow-not-control-flow] If a lone ESC remains, defer emission
|
|
171
|
+
// until the next macrotask so a follow-up chunk can extend it.
|
|
172
|
+
if (this.buffer.length === 1 && this.buffer[0] === ESC) {
|
|
173
|
+
this.escTimer = setTimeout(() => {
|
|
174
|
+
this.escTimer = undefined;
|
|
175
|
+
this.flush();
|
|
176
|
+
}, 0);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/** Force any pending lone ESC out of the buffer. */
|
|
180
|
+
flush() {
|
|
181
|
+
this.cancelEscape();
|
|
182
|
+
if (this.buffer.length === 1 && this.buffer[0] === ESC) {
|
|
183
|
+
this.buffer = EMPTY_BYTES;
|
|
184
|
+
this.sink.key(({ key: "escape", character: "", shift: false, ctrl: false, meta: false }));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/** Drop what is buffered and any pending lone ESC: the parser as constructed. */
|
|
188
|
+
reset() {
|
|
189
|
+
this.cancelEscape();
|
|
190
|
+
this.buffer = EMPTY_BYTES;
|
|
191
|
+
}
|
|
192
|
+
cancelEscape() {
|
|
193
|
+
clearTimeout(this.escTimer);
|
|
194
|
+
this.escTimer = undefined;
|
|
195
|
+
}
|
|
196
|
+
drain() {
|
|
197
|
+
while (this.buffer.length > 0) {
|
|
198
|
+
const result = this.consumeOne(this.buffer);
|
|
199
|
+
if (result.kind === "incomplete")
|
|
200
|
+
return;
|
|
201
|
+
this.buffer = this.buffer.subarray(result.bytes);
|
|
202
|
+
if (result.kind === "key")
|
|
203
|
+
this.sink.key(result.event);
|
|
204
|
+
else if (result.kind === "mouse")
|
|
205
|
+
this.sink.mouse(result.event);
|
|
206
|
+
// skip → drop bytes silently
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
consumeOne(buf) {
|
|
210
|
+
const b0 = buf[0];
|
|
211
|
+
if (b0 === ESC)
|
|
212
|
+
return this.consumeEscape(buf);
|
|
213
|
+
// Ctrl+C
|
|
214
|
+
if (b0 === 0x03) {
|
|
215
|
+
return {
|
|
216
|
+
kind: "key",
|
|
217
|
+
bytes: 1,
|
|
218
|
+
event: ({ key: "c", character: "", shift: false, ctrl: true, meta: false }),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
// Named single-byte keys (tab/enter/space/backspace).
|
|
222
|
+
const named = SINGLE_BYTE_KEYS[b0];
|
|
223
|
+
if (named && named !== "escape") {
|
|
224
|
+
return {
|
|
225
|
+
kind: "key",
|
|
226
|
+
bytes: 1,
|
|
227
|
+
event: ({
|
|
228
|
+
key: named,
|
|
229
|
+
character: named === "space" ? " " : "",
|
|
230
|
+
shift: false,
|
|
231
|
+
ctrl: false,
|
|
232
|
+
meta: false,
|
|
233
|
+
}),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
if (b0 < 0x20)
|
|
237
|
+
return { kind: "key", bytes: 1, event: ctrlKey(b0) };
|
|
238
|
+
// Printable ASCII / start of a UTF-8 multibyte character.
|
|
239
|
+
return this.consumePrintable(buf);
|
|
240
|
+
}
|
|
241
|
+
consumePrintable(buf) {
|
|
242
|
+
const b0 = buf[0];
|
|
243
|
+
let len = 1;
|
|
244
|
+
if (b0 >= 0xc0 && b0 < 0xe0)
|
|
245
|
+
len = 2;
|
|
246
|
+
else if (b0 >= 0xe0 && b0 < 0xf0)
|
|
247
|
+
len = 3;
|
|
248
|
+
else if (b0 >= 0xf0)
|
|
249
|
+
len = 4;
|
|
250
|
+
if (buf.length < len)
|
|
251
|
+
return { kind: "incomplete" };
|
|
252
|
+
const character = UTF8_DECODER.decode(buf.subarray(0, len));
|
|
253
|
+
return {
|
|
254
|
+
kind: "key",
|
|
255
|
+
bytes: len,
|
|
256
|
+
event: ({
|
|
257
|
+
key: character.toLowerCase(),
|
|
258
|
+
character,
|
|
259
|
+
shift: character.length === 1 && character !== character.toLowerCase(),
|
|
260
|
+
ctrl: false,
|
|
261
|
+
meta: false,
|
|
262
|
+
}),
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
consumeEscape(buf) {
|
|
266
|
+
if (buf.length === 1)
|
|
267
|
+
return { kind: "incomplete" };
|
|
268
|
+
const b1 = buf[1];
|
|
269
|
+
// ESC [ ... → CSI
|
|
270
|
+
if (b1 === LBRACKET)
|
|
271
|
+
return this.consumeCSI(buf);
|
|
272
|
+
// ESC O X → SS3 (F1–F4 / arrows on some terms)
|
|
273
|
+
if (b1 === O_BYTE)
|
|
274
|
+
return this.consumeSS3(buf);
|
|
275
|
+
// ESC ESC [ … / ESC ESC O … → Alt on a key the terminal sends as a
|
|
276
|
+
// sequence (macOS Terminal and iTerm send Option+Up as `ESC ESC [ A`): the
|
|
277
|
+
// inner sequence, with meta held.
|
|
278
|
+
if (b1 === ESC && buf.length > 2 && (buf[2] === LBRACKET || buf[2] === O_BYTE)) {
|
|
279
|
+
// A pointer report is never Alt-prefixed (SGR carries modifiers in its
|
|
280
|
+
// button byte), so before anything but a key the first ESC is Escape.
|
|
281
|
+
const inner = this.consumeEscape(buf.subarray(1));
|
|
282
|
+
if (inner.kind === "incomplete")
|
|
283
|
+
return inner;
|
|
284
|
+
if (inner.kind === "key") {
|
|
285
|
+
return { kind: "key", bytes: inner.bytes + 1, event: { ...inner.event, meta: true } };
|
|
286
|
+
}
|
|
287
|
+
return { kind: "key", bytes: 1, event: ESCAPE };
|
|
288
|
+
}
|
|
289
|
+
// ESC ESC → escape key (some terminals double-send). Consume BOTH bytes
|
|
290
|
+
// so the user sees one escape event, not two. Without this, the second
|
|
291
|
+
// ESC remained in the buffer and produced a second escape via the
|
|
292
|
+
// lone-ESC flush path.
|
|
293
|
+
if (b1 === ESC) {
|
|
294
|
+
return {
|
|
295
|
+
kind: "key",
|
|
296
|
+
bytes: 2,
|
|
297
|
+
event: ({ key: "escape", character: "", shift: false, ctrl: false, meta: false }),
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
// ESC <named> / ESC <printable> → Alt-modified key.
|
|
301
|
+
// Terminals encode Alt+<key> as the literal byte preceded by ESC, so
|
|
302
|
+
// `ESC b` is Alt+B, `ESC <0x7f>` is Alt+Backspace, `ESC <0x20>` is
|
|
303
|
+
// Alt+Space, etc. The parser surfaces this as `{ key, meta: true }` —
|
|
304
|
+
// matching the shape used for Ctrl-modified keys, so handlers can
|
|
305
|
+
// branch on `event.meta` without parsing escape sequences themselves.
|
|
306
|
+
//
|
|
307
|
+
// [LAW:one-source-of-truth] Named single-byte keys (space, tab,
|
|
308
|
+
// enter, backspace) use the SAME canonical key names on the Alt path
|
|
309
|
+
// as on the non-Alt path. Without this, `Alt+Space` decoded as
|
|
310
|
+
// `key: " "` while a bare space decoded as `key: "space"`, so a
|
|
311
|
+
// handler couldn't match Alt+Space via `event.key === "space" &&
|
|
312
|
+
// event.meta`. Routing through SINGLE_BYTE_KEYS first preserves the
|
|
313
|
+
// canonical naming.
|
|
314
|
+
//
|
|
315
|
+
// [LAW:one-source-of-truth] Modifier decoding for *all* navigation keys
|
|
316
|
+
// lives in this file: CSI param-style modifiers (e.g. `ESC[1;3D` for
|
|
317
|
+
// Alt+Left) flow through `decodeModifier`, and ESC-prefixed Alt forms
|
|
318
|
+
// flow through this branch. Widgets read `event.meta` and never re-parse.
|
|
319
|
+
const namedAlt = SINGLE_BYTE_KEYS[b1];
|
|
320
|
+
if (namedAlt && namedAlt !== "escape") {
|
|
321
|
+
return {
|
|
322
|
+
kind: "key",
|
|
323
|
+
bytes: 2,
|
|
324
|
+
event: ({
|
|
325
|
+
key: namedAlt,
|
|
326
|
+
character: "",
|
|
327
|
+
shift: false,
|
|
328
|
+
ctrl: false,
|
|
329
|
+
meta: true,
|
|
330
|
+
}),
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
// The key is the glyph the terminal sent, as for Alt+`>`: the glyph
|
|
334
|
+
// already carries shift, so Alt+G is `meta+G` and never `meta+shift+g`.
|
|
335
|
+
if (b1 >= 0x20 && b1 <= 0x7e) {
|
|
336
|
+
const ch = String.fromCharCode(b1);
|
|
337
|
+
return {
|
|
338
|
+
kind: "key",
|
|
339
|
+
bytes: 2,
|
|
340
|
+
event: ({ key: ch, character: "", shift: false, ctrl: false, meta: true }),
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
// ESC <control byte> is read as Escape, then the Ctrl chord — never as
|
|
344
|
+
// Alt+Ctrl. The bytes cannot tell the two apart, and Escape then Ctrl+C
|
|
345
|
+
// typed during a stalled frame must still reach the quit keys as Ctrl+C.
|
|
346
|
+
// Any other byte after ESC (a UTF-8 lead) is likewise re-read on its own.
|
|
347
|
+
return {
|
|
348
|
+
kind: "key",
|
|
349
|
+
bytes: 1,
|
|
350
|
+
event: ({ key: "escape", character: "", shift: false, ctrl: false, meta: false }),
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
consumeSS3(buf) {
|
|
354
|
+
if (buf.length < 3)
|
|
355
|
+
return { kind: "incomplete" };
|
|
356
|
+
const final = String.fromCharCode(buf[2]);
|
|
357
|
+
const name = SS3_KEYS[final];
|
|
358
|
+
if (!name)
|
|
359
|
+
return { kind: "skip", bytes: 3 };
|
|
360
|
+
return {
|
|
361
|
+
kind: "key",
|
|
362
|
+
bytes: 3,
|
|
363
|
+
event: ({ key: name, character: "", shift: false, ctrl: false, meta: false }),
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
consumeCSI(buf) {
|
|
367
|
+
// buf starts with ESC [
|
|
368
|
+
const next = buf[2];
|
|
369
|
+
if (next === undefined)
|
|
370
|
+
return { kind: "incomplete" };
|
|
371
|
+
// X10 mouse: ESC [ M b x y (3 raw bytes after M)
|
|
372
|
+
if (next === M_UPPER) {
|
|
373
|
+
if (buf.length < 6)
|
|
374
|
+
return { kind: "incomplete" };
|
|
375
|
+
const cb = buf[3] - 32;
|
|
376
|
+
const col = buf[4] - 32 - 1;
|
|
377
|
+
const row = buf[5] - 32 - 1;
|
|
378
|
+
return { kind: "mouse", bytes: 6, event: decodeMouseFromCb(cb, col, row, true) };
|
|
379
|
+
}
|
|
380
|
+
// SGR mouse: ESC [ < cb ; x ; y M|m
|
|
381
|
+
if (next === LANGLE) {
|
|
382
|
+
// Find terminator M or m.
|
|
383
|
+
for (let i = 3; i < buf.length; i++) {
|
|
384
|
+
const b = buf[i];
|
|
385
|
+
if (b === M_UPPER || b === M_LOWER) {
|
|
386
|
+
const params = ASCII_DECODER.decode(buf.subarray(3, i));
|
|
387
|
+
const parts = params.split(";");
|
|
388
|
+
if (parts.length !== 3)
|
|
389
|
+
return { kind: "skip", bytes: i + 1 };
|
|
390
|
+
const cb = parseInt(parts[0], 10);
|
|
391
|
+
const col = parseInt(parts[1], 10) - 1;
|
|
392
|
+
const row = parseInt(parts[2], 10) - 1;
|
|
393
|
+
if (Number.isNaN(cb) || Number.isNaN(col) || Number.isNaN(row)) {
|
|
394
|
+
return { kind: "skip", bytes: i + 1 };
|
|
395
|
+
}
|
|
396
|
+
return {
|
|
397
|
+
kind: "mouse",
|
|
398
|
+
bytes: i + 1,
|
|
399
|
+
event: decodeMouseFromCb(cb, col, row, b === M_UPPER),
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return { kind: "incomplete" };
|
|
404
|
+
}
|
|
405
|
+
// Generic CSI: collect parameter / intermediate bytes until a final byte
|
|
406
|
+
// in the range 0x40–0x7e is found.
|
|
407
|
+
let params = "";
|
|
408
|
+
for (let i = 2; i < buf.length; i++) {
|
|
409
|
+
const b = buf[i];
|
|
410
|
+
if (b >= 0x40 && b <= 0x7e) {
|
|
411
|
+
const final = String.fromCharCode(b);
|
|
412
|
+
return decodeCSI(params, final, i + 1);
|
|
413
|
+
}
|
|
414
|
+
params += String.fromCharCode(b);
|
|
415
|
+
}
|
|
416
|
+
return { kind: "incomplete" };
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
// --- Helpers ---
|
|
420
|
+
// The wheel's button bits: vertical, then the horizontal wheel or tilt.
|
|
421
|
+
const SCROLL = ["scroll_up", "scroll_down", "scroll_left", "scroll_right"];
|
|
422
|
+
// A C0 control byte as the Ctrl chord that types it, with Alt held or not.
|
|
423
|
+
// 0x00 is Ctrl+Space; 0x01–0x1a are Ctrl+A–Z; 0x1c–0x1f are Ctrl+\ ] ^ _.
|
|
424
|
+
// The bytes SINGLE_BYTE_KEYS names (tab, enter, backspace, escape) never reach here.
|
|
425
|
+
function ctrlKey(byte) {
|
|
426
|
+
const key = byte === 0 ? "space" : String.fromCharCode(byte + (byte <= 0x1a ? 0x60 : 0x40));
|
|
427
|
+
return { key, character: "", shift: false, ctrl: true, meta: false };
|
|
428
|
+
}
|
|
429
|
+
const ESCAPE = { key: "escape", character: "", shift: false, ctrl: false, meta: false };
|
|
430
|
+
function decodeMouseFromCb(cb, x, y, isPress) {
|
|
431
|
+
const isMotion = (cb & 32) !== 0;
|
|
432
|
+
const isScroll = (cb & 64) !== 0;
|
|
433
|
+
const button = cb & 3;
|
|
434
|
+
const shift = !!(cb & 4);
|
|
435
|
+
const ctrl = !!(cb & 16); // bit 16 = ctrl in xterm encoding
|
|
436
|
+
if (isScroll)
|
|
437
|
+
return { type: SCROLL[button], x, y, button: 0, shift, ctrl };
|
|
438
|
+
if (isMotion) {
|
|
439
|
+
return { type: "mouse_move", x, y, button, shift, ctrl };
|
|
440
|
+
}
|
|
441
|
+
return {
|
|
442
|
+
type: isPress ? "mouse_down" : "mouse_up",
|
|
443
|
+
x,
|
|
444
|
+
y,
|
|
445
|
+
button,
|
|
446
|
+
shift,
|
|
447
|
+
ctrl,
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
function decodeCSI(params, final, bytes) {
|
|
451
|
+
// Handle modifier suffixes like `1;2A` (shift+up). We split params on `;`.
|
|
452
|
+
const parts = params.split(";");
|
|
453
|
+
const first = parts[0] ?? "";
|
|
454
|
+
const mod = parseInt(parts[1] ?? "", 10);
|
|
455
|
+
const { shift, ctrl, meta } = decodeModifier(mod);
|
|
456
|
+
if (final === "~") {
|
|
457
|
+
const name = CSI_TILDE_KEYS[first];
|
|
458
|
+
if (!name)
|
|
459
|
+
return { kind: "skip", bytes };
|
|
460
|
+
return {
|
|
461
|
+
kind: "key",
|
|
462
|
+
bytes,
|
|
463
|
+
event: ({ key: name, character: "", shift, ctrl, meta }),
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
const name = CSI_LETTER_KEYS[final];
|
|
467
|
+
if (!name)
|
|
468
|
+
return { kind: "skip", bytes };
|
|
469
|
+
// Special case: ESC[Z is shift+tab regardless of explicit modifier.
|
|
470
|
+
// [LAW:one-source-of-truth] `character` is the printable character the
|
|
471
|
+
// key would produce, or "" for non-printable / modifier-only events.
|
|
472
|
+
// The non-shifted tab path emits character: "" (Tab is named, not
|
|
473
|
+
// printed) — keep shift+tab consistent. Distinguish via key === "tab"
|
|
474
|
+
// + shift, not character.
|
|
475
|
+
if (final === "Z") {
|
|
476
|
+
return {
|
|
477
|
+
kind: "key",
|
|
478
|
+
bytes,
|
|
479
|
+
event: ({ key: "tab", character: "", shift: true, ctrl: false, meta: false }),
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
return {
|
|
483
|
+
kind: "key",
|
|
484
|
+
bytes,
|
|
485
|
+
event: ({ key: name, character: "", shift, ctrl, meta }),
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
function decodeModifier(mod) {
|
|
489
|
+
if (!Number.isFinite(mod) || mod <= 1) {
|
|
490
|
+
return { shift: false, ctrl: false, meta: false };
|
|
491
|
+
}
|
|
492
|
+
const bits = mod - 1;
|
|
493
|
+
return {
|
|
494
|
+
shift: (bits & 1) !== 0,
|
|
495
|
+
meta: (bits & 2) !== 0,
|
|
496
|
+
ctrl: (bits & 4) !== 0,
|
|
497
|
+
};
|
|
498
|
+
}
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
* not an omniscient handle to "the process."
|
|
38
38
|
*/
|
|
39
39
|
import type { Unsubscribe } from "../core/subscription.js";
|
|
40
|
+
import type { Env } from "../core/env.js";
|
|
40
41
|
export interface TerminalSize {
|
|
41
42
|
readonly cols: number;
|
|
42
43
|
readonly rows: number;
|
|
@@ -90,7 +91,13 @@ export interface TerminalHost {
|
|
|
90
91
|
* rather than being read off whatever `process` the renderer happens to
|
|
91
92
|
* share a runtime with, which in a browser is none.
|
|
92
93
|
*/
|
|
93
|
-
readonly env:
|
|
94
|
+
readonly env: Env;
|
|
95
|
+
/**
|
|
96
|
+
* Scroll whatever holds this terminal by `lines` (positive towards the end
|
|
97
|
+
* of its content): a wheel turn that moved nothing in the program, passed
|
|
98
|
+
* outward. A terminal that is the outermost thing does nothing with it.
|
|
99
|
+
*/
|
|
100
|
+
passWheel(lines: number): void;
|
|
94
101
|
/**
|
|
95
102
|
* Run `handler` once, when the program ends by any path this host can
|
|
96
103
|
* observe, so whoever changed the terminal can hand it back. The program
|
|
@@ -156,6 +163,11 @@ export interface BrowserTerminalHostOptions {
|
|
|
156
163
|
* `NodeTerminalHost`'s relationship to `process.stdin`/`process.stdout`.
|
|
157
164
|
*/
|
|
158
165
|
terminal: XtermTerminal;
|
|
166
|
+
/**
|
|
167
|
+
* Scroll the page by `lines` of this terminal's rows: what the host does
|
|
168
|
+
* with a wheel turn the program passed outward (`TerminalHost.passWheel`).
|
|
169
|
+
*/
|
|
170
|
+
passWheel: (lines: number) => void;
|
|
159
171
|
}
|
|
160
172
|
export declare class BrowserTerminalHost implements TerminalHost {
|
|
161
173
|
private readonly terminal;
|
|
@@ -163,10 +175,11 @@ export declare class BrowserTerminalHost implements TerminalHost {
|
|
|
163
175
|
private readonly resizeHandlers;
|
|
164
176
|
private dataSubscription;
|
|
165
177
|
private resizeSubscription;
|
|
178
|
+
readonly passWheel: (lines: number) => void;
|
|
166
179
|
constructor(options: BrowserTerminalHostOptions);
|
|
167
180
|
get isTTY(): boolean;
|
|
168
181
|
get writesToTerminal(): boolean;
|
|
169
|
-
get env():
|
|
182
|
+
get env(): Env;
|
|
170
183
|
write(data: Uint8Array | string): void;
|
|
171
184
|
size(): TerminalSize;
|
|
172
185
|
setRawMode(_raw: boolean): void;
|
|
@@ -46,8 +46,10 @@ export class BrowserTerminalHost {
|
|
|
46
46
|
resizeHandlers = new Set();
|
|
47
47
|
dataSubscription;
|
|
48
48
|
resizeSubscription;
|
|
49
|
+
passWheel;
|
|
49
50
|
constructor(options) {
|
|
50
51
|
this.terminal = options.terminal;
|
|
52
|
+
this.passWheel = options.passWheel;
|
|
51
53
|
}
|
|
52
54
|
// [LAW:dataflow-not-control-flow] xterm.js is always an interactive
|
|
53
55
|
// terminal — there is no "non-TTY" code path in the browser. The
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { cellLen, setCellSize, splitText, chopCells, cellFit, asCellCol, asCodePoint, } from "./core/cells.js";
|
|
1
|
+
export { cellLen, setCellSize, splitText, chopCells, cellFit, graphemes, asCellCol, asCodePoint, } from "./core/cells.js";
|
|
2
2
|
export type { CellCol, CodeUnit, CodePoint } from "./core/cells.js";
|
|
3
|
-
export { ColorRgba, ColorTable, ColorDepth, ColorSpec, ColorParseError, TerminalTheme, parseRgbHex, parseRgbaHex, blendRgb, resolveColorSystem, detectColorSystem, resolveDestination, STANDARD_TABLE, EIGHT_BIT_TABLE, WINDOWS_TABLE, ANSI_COLOR_NAMES, } from "./core/color.js";
|
|
4
|
-
export type { DetectColorOptions, Destination } from "./core/color.js";
|
|
3
|
+
export { ColorRgba, ColorTable, ColorDepth, ColorSpec, ColorParseError, TerminalTheme, parseRgbHex, parseRgbaHex, parseHexColor, blendRgb, resolveColorSystem, detectColorSystem, resolveDestination, STANDARD_TABLE, EIGHT_BIT_TABLE, WINDOWS_TABLE, ANSI_COLOR_NAMES, } from "./core/color.js";
|
|
4
|
+
export type { ColorSystemName, DetectColorOptions, Destination } from "./core/color.js";
|
|
5
5
|
export { Oklch, IDENTITY, INVERT_LIGHTNESS, isIdentityKey, } from "./core/oklch.js";
|
|
6
6
|
export type { ThemeKey, OklchWeights } from "./core/oklch.js";
|
|
7
7
|
export { Palette } from "./themes/palette.js";
|
|
8
|
-
export { resolveColorRef,
|
|
8
|
+
export { resolveColorRef, ColorRefError } from "./themes/colorRef.js";
|
|
9
9
|
export { buildPalette } from "./themes/buildPalette.js";
|
|
10
10
|
export type { BaseColors } from "./themes/buildPalette.js";
|
|
11
11
|
export { DEFAULT_TERMINAL_THEME, MONOKAI, SVG_EXPORT_THEME, NORD, GRUVBOX, DRACULA, TOKYO_NIGHT, FLEXOKI, CYBERPUNK, CATPPUCCIN_MOCHA, CATPPUCCIN_LATTE, CATPPUCCIN_FRAPPE, CATPPUCCIN_MACCHIATO, SOLARIZED_DARK, SOLARIZED_LIGHT, ROSE_PINE, ROSE_PINE_MOON, ROSE_PINE_DAWN, ATOM_ONE_DARK, ATOM_ONE_LIGHT, TEXTUAL_DARK, TEXTUAL_LIGHT, TEXTUAL_ANSI, } from "./themes/terminalThemes.js";
|
|
@@ -13,10 +13,14 @@ export { getThemePalette, listThemePalettes } from "./themes/registry.js";
|
|
|
13
13
|
export type { ThemeName } from "./themes/registry.js";
|
|
14
14
|
export { transposePalette, themeKeyForRoot, isAnchored, ANCHORED_ROOTS, } from "./themes/transpose.js";
|
|
15
15
|
export { lighten, darken, relativeLuminance, contrastRatio, contrastFor, ensureContrast, ensureDrawn, drawnColour, } from "./themes/colorMath.js";
|
|
16
|
-
export { ColorRamp
|
|
17
|
-
export type { ColorStop
|
|
16
|
+
export { ColorRamp } from "./themes/ramp.js";
|
|
17
|
+
export type { ColorStop } from "./themes/ramp.js";
|
|
18
|
+
export { EASES, Phase, cubicBezier, parseEase, steps } from "./core/easing.js";
|
|
19
|
+
export type { Ease, StepPosition } from "./core/easing.js";
|
|
20
|
+
export { frameRate, systemClock } from "./core/clock.js";
|
|
21
|
+
export type { Clock, FrameRate } from "./core/clock.js";
|
|
18
22
|
export { Style, StyleSyntaxError, StyleStack, Theme, NULL_STYLE, DEFAULT_STYLES, } from "./core/style.js";
|
|
19
|
-
export type { StyleOptions } from "./core/style.js";
|
|
23
|
+
export type { StyleOptions, TextStyle, LayeredStyle } from "./core/style.js";
|
|
20
24
|
export { Segment, ControlType, } from "./core/segment.js";
|
|
21
25
|
export type { ControlCode } from "./core/segment.js";
|
|
22
26
|
export type { Anchor } from "./core/anchor.js";
|
|
@@ -29,8 +33,8 @@ export type { Unsubscribe } from "./core/subscription.js";
|
|
|
29
33
|
export { Measurement, measureRenderables } from "./core/measure.js";
|
|
30
34
|
export { Span, RichText } from "./core/text.js";
|
|
31
35
|
export type { RichTextOptions } from "./core/text.js";
|
|
32
|
-
export { Strip,
|
|
33
|
-
export type { StyledRenderable, Joiner,
|
|
36
|
+
export { Strip, CellJoiner, SEAM_MIN_DELTA_E, POWERLINE_JOINER, CAPSULE_JOINER, PLAIN_JOINER, gradientJoiner, } from "./core/strip.js";
|
|
37
|
+
export type { StyledRenderable, Joiner, JoinShape, JoinCell, CellColor, Paint } from "./core/strip.js";
|
|
34
38
|
export { renderToString, segmentToString, segmentsToString, } from "./core/render.js";
|
|
35
39
|
export type { RenderToStringOptions } from "./core/render.js";
|
|
36
40
|
export { OSC8, osc8Sequences } from "./core/osc8.js";
|
|
@@ -48,13 +52,21 @@ export type { JSONOptions } from "./core/json.js";
|
|
|
48
52
|
export { SPINNERS, DEFAULT_SPINNER } from "./core/spinnerData.js";
|
|
49
53
|
export type { SpinnerData } from "./core/spinnerData.js";
|
|
50
54
|
export { Console } from "./core/console.js";
|
|
51
|
-
export type { ConsoleOptions, ConsoleSink, ConsoleStream, ConsoleEnvironment, PrintOptions, } from "./core/console.js";
|
|
55
|
+
export type { ConsoleOptions, ConsoleSink, ConsoleStream, ConsoleEnvironment, LiveRegion, PrintOptions, } from "./core/console.js";
|
|
56
|
+
export type { Env } from "./core/env.js";
|
|
52
57
|
export { Constrain } from "./renderables/constrain.js";
|
|
58
|
+
export { Effected } from "./renderables/effect.js";
|
|
59
|
+
export type { CellColors, Effect, EffectCell, EffectedOptions } from "./renderables/effect.js";
|
|
60
|
+
export { EFFECT_CURVES, EFFECT_LIGHTS, SHIMMER_WIDTH, dissolveOut, fadeIn, onColors, pulse, shares, shimmer, sparkle, wheel, } from "./renderables/effects.js";
|
|
61
|
+
export type { Curve, Field, Loop, Pair, Touch, Transition } from "./renderables/effects.js";
|
|
53
62
|
export { Align } from "./renderables/align.js";
|
|
54
63
|
export type { Alignment } from "./core/place.js";
|
|
55
64
|
export { Padding } from "./renderables/padding.js";
|
|
56
65
|
export type { PaddingDimensions } from "./renderables/padding.js";
|
|
57
|
-
export { Viewport, SCROLLBAR } from "./renderables/viewport.js";
|
|
66
|
+
export { Viewport, ViewportPerKey, SCROLLBAR } from "./renderables/viewport.js";
|
|
67
|
+
export { ListView } from "./renderables/list-view.js";
|
|
68
|
+
export { moveSelection } from "./core/selection.js";
|
|
69
|
+
export type { ListViewOptions } from "./renderables/list-view.js";
|
|
58
70
|
export type { Scrollbar, ScrollbarPart, ViewportOptions } from "./renderables/viewport.js";
|
|
59
71
|
export { Rule } from "./renderables/rule.js";
|
|
60
72
|
export type { RuleAlign, RuleOptions } from "./renderables/rule.js";
|
|
@@ -78,13 +90,13 @@ export type { LiveOptions } from "./renderables/live.js";
|
|
|
78
90
|
export { Status } from "./renderables/status.js";
|
|
79
91
|
export type { StatusOptions } from "./renderables/status.js";
|
|
80
92
|
export { Progress, TextColumn, BarColumn, TaskProgressColumn, TimeRemainingColumn, TimeElapsedColumn, SpinnerColumn, MofNCompleteColumn, track, } from "./renderables/progress.js";
|
|
81
|
-
export type { ProgressOptions, TaskOptions, TaskUpdateOptions } from "./renderables/progress.js";
|
|
93
|
+
export type { MofNCompleteColumnOptions, ProgressColumn, ProgressOptions, SpinnerColumnOptions, Task, TaskOptions, TaskUpdateOptions, TimeRemainingColumnOptions, } from "./renderables/progress.js";
|
|
82
94
|
export { Prompt, IntPrompt, FloatPrompt, Confirm } from "./renderables/prompt.js";
|
|
83
|
-
export type { PromptInput, PromptOptions } from "./renderables/prompt.js";
|
|
95
|
+
export type { ConfirmOptions, PromptInput, PromptOptions } from "./renderables/prompt.js";
|
|
84
96
|
export { Traceback } from "./renderables/traceback.js";
|
|
85
97
|
export type { TracebackOptions } from "./renderables/traceback.js";
|
|
86
98
|
export { Syntax } from "./renderables/syntax.js";
|
|
87
|
-
export type { SyntaxOptions } from "./renderables/syntax.js";
|
|
99
|
+
export type { SyntaxLanguage, SyntaxOptions } from "./renderables/syntax.js";
|
|
88
100
|
export { Markdown } from "./renderables/markdown.js";
|
|
89
101
|
export type { MarkdownOptions } from "./renderables/markdown.js";
|
|
90
102
|
export { Layout } from "./renderables/layout.js";
|