@promptctl/rich-js 0.23.0 → 0.24.1
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/THIRD-PARTY-NOTICES +29 -1
- package/dist/core/animation.d.ts +78 -0
- package/dist/core/animation.js +107 -0
- package/dist/core/cell-widths.d.ts +9 -0
- package/dist/core/cell-widths.js +140 -0
- package/dist/core/cells.d.ts +17 -11
- package/dist/core/cells.js +100 -25
- package/dist/core/clock.d.ts +9 -1
- package/dist/core/clock.js +22 -2
- package/dist/core/color.d.ts +10 -0
- package/dist/core/color.js +36 -1
- package/dist/core/console.js +5 -5
- package/dist/core/easing.d.ts +138 -7
- package/dist/core/easing.js +355 -17
- package/dist/core/json.js +2 -1
- package/dist/core/measure.js +2 -2
- package/dist/core/place.js +2 -1
- package/dist/core/pretty.js +2 -2
- package/dist/core/protocol.d.ts +73 -19
- package/dist/core/protocol.js +56 -15
- package/dist/core/render.js +2 -1
- package/dist/core/segment.d.ts +28 -1
- package/dist/core/segment.js +60 -44
- package/dist/core/strip.d.ts +107 -29
- package/dist/core/strip.js +242 -131
- package/dist/core/style.d.ts +18 -1
- package/dist/core/style.js +49 -9
- package/dist/core/text.js +26 -15
- package/dist/core/timeline.d.ts +84 -0
- package/dist/core/timeline.js +144 -0
- package/dist/core/tween.d.ts +49 -0
- package/dist/core/tween.js +69 -0
- package/dist/host/app.js +4 -6
- package/dist/host/index.d.ts +1 -1
- package/dist/host/input.d.ts +37 -13
- package/dist/host/input.js +146 -56
- package/dist/host/terminal-host.d.ts +16 -0
- package/dist/host/terminal-host.js +1 -0
- package/dist/index.d.ts +16 -11
- package/dist/index.js +15 -5
- package/dist/node/terminal-host.d.ts +8 -1
- package/dist/node/terminal-host.js +2 -0
- package/dist/renderables/align.d.ts +3 -2
- package/dist/renderables/align.js +3 -0
- package/dist/renderables/columns.d.ts +3 -2
- package/dist/renderables/columns.js +7 -2
- package/dist/renderables/constrain.d.ts +3 -2
- package/dist/renderables/constrain.js +5 -1
- package/dist/renderables/effect.d.ts +83 -30
- package/dist/renderables/effect.js +155 -57
- package/dist/renderables/effects.d.ts +88 -39
- package/dist/renderables/effects.js +444 -105
- package/dist/renderables/embed.d.ts +10 -0
- package/dist/renderables/embed.js +18 -9
- package/dist/renderables/flexStrip.d.ts +3 -2
- package/dist/renderables/flexStrip.js +6 -1
- package/dist/renderables/frames.d.ts +116 -0
- package/dist/renderables/frames.js +133 -0
- package/dist/renderables/group.d.ts +3 -2
- package/dist/renderables/group.js +5 -2
- package/dist/renderables/html-entities.d.ts +8 -0
- package/dist/renderables/html-entities.js +386 -0
- package/dist/renderables/layout.d.ts +3 -2
- package/dist/renderables/layout.js +15 -2
- package/dist/renderables/list-view.d.ts +3 -2
- package/dist/renderables/list-view.js +12 -5
- package/dist/renderables/live.d.ts +23 -7
- package/dist/renderables/live.js +69 -35
- package/dist/renderables/markdown-parse.d.ts +109 -0
- package/dist/renderables/markdown-parse.js +1421 -0
- package/dist/renderables/markdown-url.d.ts +19 -0
- package/dist/renderables/markdown-url.js +314 -0
- package/dist/renderables/markdown.d.ts +7 -6
- package/dist/renderables/markdown.js +363 -499
- package/dist/renderables/padding.d.ts +8 -20
- package/dist/renderables/padding.js +32 -50
- package/dist/renderables/panel.d.ts +26 -26
- package/dist/renderables/panel.js +67 -103
- package/dist/renderables/progress.d.ts +5 -3
- package/dist/renderables/progress.js +14 -3
- package/dist/renderables/progressBar.js +4 -4
- package/dist/renderables/python-space.d.ts +13 -0
- package/dist/renderables/python-space.js +24 -0
- package/dist/renderables/spinner.d.ts +73 -27
- package/dist/renderables/spinner.js +110 -51
- package/dist/renderables/status.d.ts +8 -3
- package/dist/renderables/status.js +8 -5
- package/dist/renderables/syntax.js +2 -1
- package/dist/renderables/table.d.ts +19 -11
- package/dist/renderables/table.js +140 -156
- package/dist/renderables/traceback.d.ts +1 -1
- package/dist/renderables/traceback.js +6 -5
- package/dist/renderables/tree.d.ts +6 -5
- package/dist/renderables/tree.js +11 -7
- package/dist/renderables/viewport.d.ts +13 -5
- package/dist/renderables/viewport.js +41 -20
- package/dist/template-bindings/animation-funcs.d.ts +37 -0
- package/dist/template-bindings/animation-funcs.js +83 -0
- package/dist/template-bindings/color-funcs.d.ts +13 -0
- package/dist/template-bindings/color-funcs.js +1 -1
- package/dist/template-bindings/helpers.d.ts +6 -0
- package/dist/template-bindings/helpers.js +12 -3
- package/dist/template-bindings/index.d.ts +6 -2
- package/dist/template-bindings/index.js +8 -3
- package/dist/themes/ramp.d.ts +18 -3
- package/dist/themes/ramp.js +23 -2
- package/dist/widgets/focus-manager.d.ts +21 -14
- package/dist/widgets/focus-manager.js +28 -29
- package/dist/widgets/index.d.ts +1 -1
- package/dist/widgets/static-item.d.ts +4 -3
- package/dist/widgets/static-item.js +9 -7
- package/dist/widgets/text-input.d.ts +28 -18
- package/dist/widgets/text-input.js +144 -101
- package/dist/widgets/widget-app.d.ts +19 -3
- package/dist/widgets/widget-app.js +39 -21
- package/dist/widgets/widget-base.js +0 -3
- package/package.json +2 -5
package/dist/host/input.d.ts
CHANGED
|
@@ -9,17 +9,28 @@
|
|
|
9
9
|
*
|
|
10
10
|
* [LAW:dataflow-not-control-flow] The same parse pipeline runs for every
|
|
11
11
|
* input chunk: append → consume one event at a time until the buffer can't
|
|
12
|
-
* yield more. The byte's value
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* split across two chunks is completed by the second.
|
|
12
|
+
* yield more. The byte's value decides which event is emitted; there is no
|
|
13
|
+
* "are we mid-sequence" mode flag — the buffer head carries that state, so on
|
|
14
|
+
* a host whose chunks can split a key, a UTF-8 character or an escape
|
|
15
|
+
* sequence split across two chunks is completed by the second. What a chunk
|
|
16
|
+
* end means is the host's `InputChunks`, the one input to the parser that is
|
|
17
|
+
* not a byte, and it decides only what becomes of an unfinished ESC.
|
|
16
18
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* `
|
|
21
|
-
*
|
|
19
|
+
* An unfinished escape sequence is ambiguous: `ESC` alone is the Escape key
|
|
20
|
+
* or the start of a sequence, and `ESC [` is Alt+[ or the start of a CSI.
|
|
21
|
+
* Only the host's `InputChunks` and the clock can settle it. On a
|
|
22
|
+
* `"whole-keys"` host a chunk ends on a key boundary, so an ESC still waiting
|
|
23
|
+
* at a chunk's end opened nothing: it is Escape, and what followed it is read
|
|
24
|
+
* again on its own. On a `"split"` host a read can end anywhere, so the
|
|
25
|
+
* parser holds the unfinished sequence for the escape delay — ncurses'
|
|
26
|
+
* ESCDELAY, tmux's escape-time — and, when nothing has extended it by then,
|
|
27
|
+
* settles it by the same whole-keys rule. `ESC ESC` is held too, since the
|
|
28
|
+
* byte after it decides whether it is Alt on a sequence or one Escape. A held
|
|
29
|
+
* lone ESC is also settled early by a next chunk that opens with anything but
|
|
30
|
+
* `[` or `O`, because a busy worker can queue the next key behind it.
|
|
31
|
+
* `flush()` settles the hold synchronously.
|
|
22
32
|
*/
|
|
33
|
+
import type { InputChunks } from "./terminal-host.js";
|
|
23
34
|
/** A key as the terminal reported it: plain data, with no say over who hears it. */
|
|
24
35
|
export interface KeyPress {
|
|
25
36
|
readonly key: string;
|
|
@@ -63,18 +74,31 @@ export interface InputSink {
|
|
|
63
74
|
* one place a program hands names in, rather than binding a key that never fires.
|
|
64
75
|
*/
|
|
65
76
|
export declare function parseKeyName(name: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* How long a `"split"` host's parser waits for the rest of an unfinished
|
|
79
|
+
* escape sequence before reading it as the keys it already holds. Textual's
|
|
80
|
+
* ESCAPE_DELAY and vim's `ttimeoutlen` default to the same: long enough for
|
|
81
|
+
* the rest of a sequence a read split (over ssh, say) to arrive, short
|
|
82
|
+
* enough that Escape does not feel late.
|
|
83
|
+
*/
|
|
84
|
+
export declare const ESCAPE_DELAY_MS = 100;
|
|
66
85
|
export declare class InputParser {
|
|
67
86
|
private readonly sink;
|
|
87
|
+
private readonly chunks;
|
|
68
88
|
private buffer;
|
|
69
89
|
private escTimer;
|
|
70
|
-
constructor(sink: InputSink);
|
|
90
|
+
constructor(sink: InputSink, chunks: InputChunks);
|
|
71
91
|
/** Feed a chunk of bytes (or a string of them) into the parser. */
|
|
72
92
|
feed(chunk: Uint8Array | string): void;
|
|
73
|
-
|
|
93
|
+
private drainAndHold;
|
|
94
|
+
private hold;
|
|
95
|
+
private settleChunk;
|
|
96
|
+
private drainFully;
|
|
97
|
+
/** Settle a held escape sequence now, as the end of a whole-key chunk. */
|
|
74
98
|
flush(): void;
|
|
75
|
-
/** Drop what is buffered and any
|
|
99
|
+
/** Drop what is buffered and any held escape sequence: the parser as constructed. */
|
|
76
100
|
reset(): void;
|
|
77
|
-
/**
|
|
101
|
+
/** A lone ESC, the one hold a next chunk can settle before its bytes are read. */
|
|
78
102
|
private holdingEscape;
|
|
79
103
|
private cancelEscape;
|
|
80
104
|
private drain;
|
package/dist/host/input.js
CHANGED
|
@@ -9,16 +9,26 @@
|
|
|
9
9
|
*
|
|
10
10
|
* [LAW:dataflow-not-control-flow] The same parse pipeline runs for every
|
|
11
11
|
* input chunk: append → consume one event at a time until the buffer can't
|
|
12
|
-
* yield more. The byte's value
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* split across two chunks is completed by the second.
|
|
12
|
+
* yield more. The byte's value decides which event is emitted; there is no
|
|
13
|
+
* "are we mid-sequence" mode flag — the buffer head carries that state, so on
|
|
14
|
+
* a host whose chunks can split a key, a UTF-8 character or an escape
|
|
15
|
+
* sequence split across two chunks is completed by the second. What a chunk
|
|
16
|
+
* end means is the host's `InputChunks`, the one input to the parser that is
|
|
17
|
+
* not a byte, and it decides only what becomes of an unfinished ESC.
|
|
16
18
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* `
|
|
21
|
-
*
|
|
19
|
+
* An unfinished escape sequence is ambiguous: `ESC` alone is the Escape key
|
|
20
|
+
* or the start of a sequence, and `ESC [` is Alt+[ or the start of a CSI.
|
|
21
|
+
* Only the host's `InputChunks` and the clock can settle it. On a
|
|
22
|
+
* `"whole-keys"` host a chunk ends on a key boundary, so an ESC still waiting
|
|
23
|
+
* at a chunk's end opened nothing: it is Escape, and what followed it is read
|
|
24
|
+
* again on its own. On a `"split"` host a read can end anywhere, so the
|
|
25
|
+
* parser holds the unfinished sequence for the escape delay — ncurses'
|
|
26
|
+
* ESCDELAY, tmux's escape-time — and, when nothing has extended it by then,
|
|
27
|
+
* settles it by the same whole-keys rule. `ESC ESC` is held too, since the
|
|
28
|
+
* byte after it decides whether it is Alt on a sequence or one Escape. A held
|
|
29
|
+
* lone ESC is also settled early by a next chunk that opens with anything but
|
|
30
|
+
* `[` or `O`, because a busy worker can queue the next key behind it.
|
|
31
|
+
* `flush()` settles the hold synchronously.
|
|
22
32
|
*/
|
|
23
33
|
/**
|
|
24
34
|
* The one name a key goes by — what a keymap is keyed by and what
|
|
@@ -137,6 +147,14 @@ const UTF8_ENCODER = new TextEncoder();
|
|
|
137
147
|
const UTF8_DECODER = new TextDecoder("utf-8");
|
|
138
148
|
const ASCII_DECODER = new TextDecoder("ascii");
|
|
139
149
|
const EMPTY_BYTES = new Uint8Array(0);
|
|
150
|
+
/**
|
|
151
|
+
* How long a `"split"` host's parser waits for the rest of an unfinished
|
|
152
|
+
* escape sequence before reading it as the keys it already holds. Textual's
|
|
153
|
+
* ESCAPE_DELAY and vim's `ttimeoutlen` default to the same: long enough for
|
|
154
|
+
* the rest of a sequence a read split (over ssh, say) to arrive, short
|
|
155
|
+
* enough that Escape does not feel late.
|
|
156
|
+
*/
|
|
157
|
+
export const ESCAPE_DELAY_MS = 100;
|
|
140
158
|
// Concatenate two byte arrays into a fresh Uint8Array. Replaces
|
|
141
159
|
// `Buffer.concat([...])` so the parser holds no node-specific globals.
|
|
142
160
|
function concatBytes(a, b) {
|
|
@@ -149,8 +167,30 @@ function concatBytes(a, b) {
|
|
|
149
167
|
merged.set(b, a.length);
|
|
150
168
|
return merged;
|
|
151
169
|
}
|
|
170
|
+
// Alt on a printable byte: the glyph the terminal sent, with meta held.
|
|
171
|
+
function altKey(byte) {
|
|
172
|
+
return { key: String.fromCharCode(byte), character: "", shift: false, ctrl: false, meta: true };
|
|
173
|
+
}
|
|
174
|
+
// ECMA-48: an escape sequence is built of bytes 0x20–0x7E after its ESC, so
|
|
175
|
+
// any other byte (ESC itself, a control, a UTF-8 byte) ends one unfinished.
|
|
176
|
+
function inSequence(byte) {
|
|
177
|
+
return byte >= 0x20 && byte <= 0x7e;
|
|
178
|
+
}
|
|
179
|
+
// [LAW:one-source-of-truth] An escape sequence that opened no key — ended
|
|
180
|
+
// before its final byte (at a whole-key chunk's end, at the escape delay, or at
|
|
181
|
+
// a byte that cannot belong to it), or an SS3 no terminal sends — is reissued
|
|
182
|
+
// as the keys it holds, as Textual reissues one. `ESC ESC` is one Escape, as a
|
|
183
|
+
// terminal that double-sends it means, whatever followed it; `ESC [` / `ESC O`
|
|
184
|
+
// alone is the whole key Alt+[ / Alt+O; any other ESC is Escape. What followed
|
|
185
|
+
// the Escape is read again on its own.
|
|
186
|
+
function reissue(sequence) {
|
|
187
|
+
if (sequence[1] === ESC)
|
|
188
|
+
return { bytes: 2, event: ESCAPE };
|
|
189
|
+
return sequence.length === 2 ? { bytes: 2, event: altKey(sequence[1]) } : { bytes: 1, event: ESCAPE };
|
|
190
|
+
}
|
|
152
191
|
export class InputParser {
|
|
153
192
|
sink;
|
|
193
|
+
chunks;
|
|
154
194
|
// [LAW:types-are-the-program] The parse buffer is `Uint8Array`, not
|
|
155
195
|
// `Buffer` — node's Buffer extends Uint8Array, so Buffer chunks from
|
|
156
196
|
// process.stdin satisfy this type, while a browser host can emit native
|
|
@@ -159,12 +199,17 @@ export class InputParser {
|
|
|
159
199
|
// [LAW:types-are-the-program] `setTimeout`/`clearTimeout` are universal
|
|
160
200
|
// across node and browser; `setImmediate` is node-only.
|
|
161
201
|
escTimer;
|
|
162
|
-
constructor(sink) {
|
|
202
|
+
constructor(sink, chunks) {
|
|
163
203
|
this.sink = sink;
|
|
204
|
+
this.chunks = chunks;
|
|
164
205
|
}
|
|
165
206
|
/** Feed a chunk of bytes (or a string of them) into the parser. */
|
|
166
207
|
feed(chunk) {
|
|
167
208
|
const next = typeof chunk === "string" ? UTF8_ENCODER.encode(chunk) : chunk;
|
|
209
|
+
if (this.chunks === "whole-keys") {
|
|
210
|
+
this.buffer = concatBytes(this.buffer, next);
|
|
211
|
+
return this.settleChunk();
|
|
212
|
+
}
|
|
168
213
|
// A held lone ESC waits only for the rest of a split CSI/SS3 introducer.
|
|
169
214
|
// Any other next chunk means Escape was its own key, even when the hold
|
|
170
215
|
// timer has not run yet: a busy worker can queue the next key ahead of it,
|
|
@@ -179,32 +224,77 @@ export class InputParser {
|
|
|
179
224
|
this.sink.key(ESCAPE);
|
|
180
225
|
}
|
|
181
226
|
finally {
|
|
227
|
+
this.drainAndHold();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
drainAndHold() {
|
|
231
|
+
try {
|
|
232
|
+
this.drainFully();
|
|
233
|
+
}
|
|
234
|
+
finally {
|
|
235
|
+
this.hold();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
// [LAW:no-ambient-temporal-coupling] Whatever drain leaves at an ESC is an
|
|
239
|
+
// unfinished sequence, and the escape delay is what tells one whose rest is
|
|
240
|
+
// still in flight from one that stalled: a stalled `ESC [` held for good
|
|
241
|
+
// would read the next key as its final byte (rich-host-input-gnl7). The delay
|
|
242
|
+
// counts time the program could have read the rest in: node runs an expired
|
|
243
|
+
// timer before it reads input queued behind a long frame, so the delay's end
|
|
244
|
+
// settles the hold only after one more turn of the event loop has read what
|
|
245
|
+
// was waiting. The parser holds one timer, so arming it replaces any other.
|
|
246
|
+
hold() {
|
|
247
|
+
this.cancelEscape();
|
|
248
|
+
if (this.buffer[0] !== ESC)
|
|
249
|
+
return;
|
|
250
|
+
this.escTimer = setTimeout(() => {
|
|
251
|
+
this.escTimer = setTimeout(() => this.flush(), 0);
|
|
252
|
+
}, ESCAPE_DELAY_MS);
|
|
253
|
+
}
|
|
254
|
+
// A whole-key chunk has ended, so an ESC still at the buffer head opens no
|
|
255
|
+
// sequence, and is read as `reissue` reads it. Each key is taken off the
|
|
256
|
+
// buffer before the sink hears it, so no byte of one chunk outlives it.
|
|
257
|
+
settleChunk() {
|
|
258
|
+
try {
|
|
259
|
+
this.drainFully();
|
|
260
|
+
}
|
|
261
|
+
finally {
|
|
262
|
+
if (this.buffer[0] === ESC) {
|
|
263
|
+
const { bytes, event } = reissue(this.buffer);
|
|
264
|
+
this.buffer = this.buffer.subarray(bytes);
|
|
265
|
+
try {
|
|
266
|
+
this.sink.key(event);
|
|
267
|
+
}
|
|
268
|
+
finally {
|
|
269
|
+
this.settleChunk();
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// Drain, and when a handler throws, read the rest of the buffer in full
|
|
275
|
+
// before the throw goes on, so a throwing handler strands no key behind it.
|
|
276
|
+
drainFully() {
|
|
277
|
+
let drained = false;
|
|
278
|
+
try {
|
|
182
279
|
this.drain();
|
|
280
|
+
drained = true;
|
|
183
281
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (this.holdingEscape()) {
|
|
188
|
-
this.escTimer = setTimeout(() => {
|
|
189
|
-
this.escTimer = undefined;
|
|
190
|
-
this.flush();
|
|
191
|
-
}, 0);
|
|
282
|
+
finally {
|
|
283
|
+
if (!drained)
|
|
284
|
+
this.drainFully();
|
|
192
285
|
}
|
|
193
286
|
}
|
|
194
|
-
/**
|
|
287
|
+
/** Settle a held escape sequence now, as the end of a whole-key chunk. */
|
|
195
288
|
flush() {
|
|
196
289
|
this.cancelEscape();
|
|
197
|
-
|
|
198
|
-
this.buffer = EMPTY_BYTES;
|
|
199
|
-
this.sink.key(ESCAPE);
|
|
200
|
-
}
|
|
290
|
+
this.settleChunk();
|
|
201
291
|
}
|
|
202
|
-
/** Drop what is buffered and any
|
|
292
|
+
/** Drop what is buffered and any held escape sequence: the parser as constructed. */
|
|
203
293
|
reset() {
|
|
204
294
|
this.cancelEscape();
|
|
205
295
|
this.buffer = EMPTY_BYTES;
|
|
206
296
|
}
|
|
207
|
-
/**
|
|
297
|
+
/** A lone ESC, the one hold a next chunk can settle before its bytes are read. */
|
|
208
298
|
holdingEscape() {
|
|
209
299
|
return this.buffer.length === 1 && this.buffer[0] === ESC;
|
|
210
300
|
}
|
|
@@ -218,7 +308,7 @@ export class InputParser {
|
|
|
218
308
|
if (result.kind === "incomplete")
|
|
219
309
|
return;
|
|
220
310
|
this.buffer = this.buffer.subarray(result.bytes);
|
|
221
|
-
if (result.kind === "key")
|
|
311
|
+
if (result.kind === "key" || result.kind === "reissued")
|
|
222
312
|
this.sink.key(result.event);
|
|
223
313
|
else if (result.kind === "mouse")
|
|
224
314
|
this.sink.mouse(result.event);
|
|
@@ -291,30 +381,28 @@ export class InputParser {
|
|
|
291
381
|
// ESC O X → SS3 (F1–F4 / arrows on some terms)
|
|
292
382
|
if (b1 === O_BYTE)
|
|
293
383
|
return this.consumeSS3(buf);
|
|
294
|
-
// ESC ESC [ … / ESC ESC O … → Alt on a key the terminal sends as a
|
|
295
|
-
// sequence (macOS Terminal and iTerm send Option+Up as `ESC ESC [ A`): the
|
|
296
|
-
// inner sequence, with meta held.
|
|
297
|
-
if (b1 === ESC && buf.length > 2 && (buf[2] === LBRACKET || buf[2] === O_BYTE)) {
|
|
298
|
-
// A pointer report is never Alt-prefixed (SGR carries modifiers in its
|
|
299
|
-
// button byte), so before anything but a key the first ESC is Escape.
|
|
300
|
-
const inner = this.consumeEscape(buf.subarray(1));
|
|
301
|
-
if (inner.kind === "incomplete")
|
|
302
|
-
return inner;
|
|
303
|
-
if (inner.kind === "key") {
|
|
304
|
-
return { kind: "key", bytes: inner.bytes + 1, event: { ...inner.event, meta: true } };
|
|
305
|
-
}
|
|
306
|
-
return { kind: "key", bytes: 1, event: ESCAPE };
|
|
307
|
-
}
|
|
308
|
-
// ESC ESC → escape key (some terminals double-send). Consume BOTH bytes
|
|
309
|
-
// so the user sees one escape event, not two. Without this, the second
|
|
310
|
-
// ESC remained in the buffer and produced a second escape via the
|
|
311
|
-
// lone-ESC flush path.
|
|
312
384
|
if (b1 === ESC) {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
385
|
+
// The byte after `ESC ESC` decides what it opens, so a read that ends
|
|
386
|
+
// between them leaves it unfinished, held like any other.
|
|
387
|
+
if (buf.length === 2)
|
|
388
|
+
return { kind: "incomplete" };
|
|
389
|
+
// ESC ESC [ … / ESC ESC O … → Alt on a key the terminal sends as a
|
|
390
|
+
// sequence (macOS Terminal and iTerm send Option+Up as `ESC ESC [ A`):
|
|
391
|
+
// the inner sequence, with meta held.
|
|
392
|
+
if (buf[2] === LBRACKET || buf[2] === O_BYTE) {
|
|
393
|
+
const inner = this.consumeEscape(buf.subarray(1));
|
|
394
|
+
if (inner.kind === "incomplete")
|
|
395
|
+
return inner;
|
|
396
|
+
if (inner.kind === "key") {
|
|
397
|
+
return { kind: "key", bytes: inner.bytes + 1, event: { ...inner.event, meta: true } };
|
|
398
|
+
}
|
|
399
|
+
// A pointer report is never Alt-prefixed (SGR carries modifiers in its
|
|
400
|
+
// button byte): the second ESC is the report's, and the first is Escape.
|
|
401
|
+
if (inner.kind !== "reissued")
|
|
402
|
+
return { kind: "key", bytes: 1, event: ESCAPE };
|
|
403
|
+
}
|
|
404
|
+
// `ESC ESC` before a byte that opens no key opened none itself.
|
|
405
|
+
return { kind: "reissued", ...reissue(buf) };
|
|
318
406
|
}
|
|
319
407
|
// ESC <named> / ESC <printable> → Alt-modified key.
|
|
320
408
|
// Terminals encode Alt+<key> as the literal byte preceded by ESC, so
|
|
@@ -352,12 +440,7 @@ export class InputParser {
|
|
|
352
440
|
// The key is the glyph the terminal sent, as for Alt+`>`: the glyph
|
|
353
441
|
// already carries shift, so Alt+G is `meta+G` and never `meta+shift+g`.
|
|
354
442
|
if (b1 >= 0x20 && b1 <= 0x7e) {
|
|
355
|
-
|
|
356
|
-
return {
|
|
357
|
-
kind: "key",
|
|
358
|
-
bytes: 2,
|
|
359
|
-
event: ({ key: ch, character: "", shift: false, ctrl: false, meta: true }),
|
|
360
|
-
};
|
|
443
|
+
return { kind: "key", bytes: 2, event: altKey(b1) };
|
|
361
444
|
}
|
|
362
445
|
// ESC <control byte> is read as Escape, then the Ctrl chord — never as
|
|
363
446
|
// Alt+Ctrl. The bytes cannot tell the two apart, and Escape then Ctrl+C
|
|
@@ -372,10 +455,13 @@ export class InputParser {
|
|
|
372
455
|
consumeSS3(buf) {
|
|
373
456
|
if (buf.length < 3)
|
|
374
457
|
return { kind: "incomplete" };
|
|
458
|
+
if (!inSequence(buf[2]))
|
|
459
|
+
return { kind: "reissued", ...reissue(buf.subarray(0, 2)) };
|
|
375
460
|
const final = String.fromCharCode(buf[2]);
|
|
376
461
|
const name = SS3_KEYS[final];
|
|
462
|
+
// No terminal reports in SS3, so an unknown final was typed: Escape, then O.
|
|
377
463
|
if (!name)
|
|
378
|
-
return { kind: "
|
|
464
|
+
return { kind: "reissued", ...reissue(buf.subarray(0, 3)) };
|
|
379
465
|
return {
|
|
380
466
|
kind: "key",
|
|
381
467
|
bytes: 3,
|
|
@@ -418,6 +504,8 @@ export class InputParser {
|
|
|
418
504
|
event: decodeMouseFromCb(cb, col, row, b === M_UPPER),
|
|
419
505
|
};
|
|
420
506
|
}
|
|
507
|
+
if (!inSequence(b))
|
|
508
|
+
return { kind: "reissued", ...reissue(buf.subarray(0, i)) };
|
|
421
509
|
}
|
|
422
510
|
return { kind: "incomplete" };
|
|
423
511
|
}
|
|
@@ -430,6 +518,8 @@ export class InputParser {
|
|
|
430
518
|
const final = String.fromCharCode(b);
|
|
431
519
|
return decodeCSI(params, final, i + 1);
|
|
432
520
|
}
|
|
521
|
+
if (!inSequence(b))
|
|
522
|
+
return { kind: "reissued", ...reissue(buf.subarray(0, i)) };
|
|
433
523
|
params += String.fromCharCode(b);
|
|
434
524
|
}
|
|
435
525
|
return { kind: "incomplete" };
|
|
@@ -43,6 +43,13 @@ export interface TerminalSize {
|
|
|
43
43
|
readonly rows: number;
|
|
44
44
|
}
|
|
45
45
|
export type DataHandler = (chunk: Uint8Array | string) => void;
|
|
46
|
+
/**
|
|
47
|
+
* Where a host's input chunks may end. `"whole-keys"`: every chunk ends on a
|
|
48
|
+
* key boundary, so no escape sequence is ever split across two (xterm.js
|
|
49
|
+
* emits one key, or one paste, per event). `"split"`: a chunk may end
|
|
50
|
+
* anywhere, as a read from a tty can.
|
|
51
|
+
*/
|
|
52
|
+
export type InputChunks = "whole-keys" | "split";
|
|
46
53
|
export type ResizeHandler = (size: TerminalSize) => void;
|
|
47
54
|
export type ExitHandler = () => void;
|
|
48
55
|
export interface TerminalHost {
|
|
@@ -60,6 +67,14 @@ export interface TerminalHost {
|
|
|
60
67
|
* runtime's parser accepts either.
|
|
61
68
|
*/
|
|
62
69
|
onData(handler: DataHandler): Unsubscribe;
|
|
70
|
+
/**
|
|
71
|
+
* Where `onData`'s chunks may end. The parser holds an unfinished escape
|
|
72
|
+
* sequence open for its rest, for the escape delay, only on a host whose
|
|
73
|
+
* chunks can split one; a whole-keys host settles each chunk as it arrives,
|
|
74
|
+
* because a busy worker there reads a queued next key before any timer
|
|
75
|
+
* runs (rich-host-input-ab9n).
|
|
76
|
+
*/
|
|
77
|
+
readonly inputChunks: InputChunks;
|
|
63
78
|
/**
|
|
64
79
|
* Subscribe to terminal resize events. The handler fires with the new
|
|
65
80
|
* size after a resize is observed.
|
|
@@ -176,6 +191,7 @@ export declare class BrowserTerminalHost implements TerminalHost {
|
|
|
176
191
|
private dataSubscription;
|
|
177
192
|
private resizeSubscription;
|
|
178
193
|
readonly passWheel: (lines: number) => void;
|
|
194
|
+
readonly inputChunks = "whole-keys";
|
|
179
195
|
constructor(options: BrowserTerminalHostOptions);
|
|
180
196
|
get isTTY(): boolean;
|
|
181
197
|
get writesToTerminal(): boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -15,8 +15,11 @@ export { transposePalette, themeKeyForRoot, isAnchored, ANCHORED_ROOTS, } from "
|
|
|
15
15
|
export { lighten, darken, relativeLuminance, contrastRatio, contrastFor, ensureContrast, ensureDrawn, drawnColour, } from "./themes/colorMath.js";
|
|
16
16
|
export { ColorRamp } from "./themes/ramp.js";
|
|
17
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";
|
|
18
|
+
export { EASES, Phase, beat, cubicBezier, parseEase, spring, steps } from "./core/easing.js";
|
|
19
|
+
export type { Beat, Ease, SpringOptions, StepPosition, Timing } from "./core/easing.js";
|
|
20
|
+
export { Animation } from "./core/animation.js";
|
|
21
|
+
export { tween } from "./core/tween.js";
|
|
22
|
+
export { Timeline } from "./core/timeline.js";
|
|
20
23
|
export { frameRate, systemClock } from "./core/clock.js";
|
|
21
24
|
export type { Clock, FrameRate } from "./core/clock.js";
|
|
22
25
|
export { Style, StyleSyntaxError, StyleStack, Theme, NULL_STYLE, DEFAULT_STYLES, } from "./core/style.js";
|
|
@@ -27,14 +30,14 @@ export type { Anchor } from "./core/anchor.js";
|
|
|
27
30
|
export { Box } from "./core/box.js";
|
|
28
31
|
export type { EdgeChars, ContentChars, RowLevel, SubstituteOptions } from "./core/box.js";
|
|
29
32
|
export { ASCII, ASCII2, ASCII_DOUBLE_HEAD, SQUARE, SQUARE_DOUBLE_HEAD, MINIMAL, MINIMAL_HEAVY_HEAD, MINIMAL_DOUBLE_HEAD, SIMPLE, SIMPLE_HEAD, SIMPLE_HEAVY, HORIZONTALS, ROUNDED, HEAVY, HEAVY_EDGE, HEAVY_HEAD, DOUBLE, DOUBLE_EDGE, MARKDOWN, } from "./core/box.js";
|
|
30
|
-
export { isRenderable, isMeasurable, withCellWidth, withBoundedWidth, insetHeight, stackedHeight, regionRows, fitHeight, getStyle, } from "./core/protocol.js";
|
|
31
|
-
export type { RenderOptions, OverflowMethod, Height, Renderable, Measurable, StyleErrorHandler, } from "./core/protocol.js";
|
|
33
|
+
export { render, isRenderable, isMeasurable, withCellWidth, withBoundedWidth, insetHeight, stackedHeight, regionRows, fitHeight, getStyle, } from "./core/protocol.js";
|
|
34
|
+
export type { RenderOptions, OverflowMethod, Height, Renderable, Measurable, Composite, Presence, StyleErrorHandler, } from "./core/protocol.js";
|
|
32
35
|
export type { Unsubscribe } from "./core/subscription.js";
|
|
33
36
|
export { Measurement, measureRenderables } from "./core/measure.js";
|
|
34
37
|
export { Span, RichText } from "./core/text.js";
|
|
35
38
|
export type { RichTextOptions } from "./core/text.js";
|
|
36
|
-
export { Strip, CellJoiner, SEAM_MIN_DELTA_E, JOINERS, joinerNamed,
|
|
37
|
-
export type { StyledRenderable, Joiner, JoinContext,
|
|
39
|
+
export { Strip, CellJoiner, SEAM_MIN_DELTA_E, SEAMS, CAPS, JOINERS, joinerNamed, gradientSeam, } from "./core/strip.js";
|
|
40
|
+
export type { StyledRenderable, Joiner, JoinContext, JoinSeam, JoinCaps, SeamForm, CapsForm, SeamCell, JoinCell, CellColor, Paint, JoinerSpec, } from "./core/strip.js";
|
|
38
41
|
export { renderToString, segmentToString, segmentsToString, } from "./core/render.js";
|
|
39
42
|
export type { RenderToStringOptions } from "./core/render.js";
|
|
40
43
|
export { OSC8, osc8Sequences } from "./core/osc8.js";
|
|
@@ -55,10 +58,10 @@ export { Console } from "./core/console.js";
|
|
|
55
58
|
export type { ConsoleOptions, ConsoleSink, ConsoleStream, ConsoleEnvironment, LiveRegion, PrintOptions, } from "./core/console.js";
|
|
56
59
|
export type { Env } from "./core/env.js";
|
|
57
60
|
export { Constrain } from "./renderables/constrain.js";
|
|
58
|
-
export { Effected, confined, drawnOf } from "./renderables/effect.js";
|
|
59
|
-
export type { CellColors, Drawn, Effect, EffectCell, EffectedOptions, Pair } from "./renderables/effect.js";
|
|
60
|
-
export { EFFECT_CATALOGUE, EFFECT_CURVES, EFFECT_LIGHTS, dissolveOut, fadeIn, onColors, pulse, shimmer, sparkle, wheel, } from "./renderables/effects.js";
|
|
61
|
-
export type { Curve, EffectTarget, Field, Loop, LoopName, Touch, Transition, TransitionName } from "./renderables/effects.js";
|
|
61
|
+
export { Effected, confined, drawnOf, onBeat } from "./renderables/effect.js";
|
|
62
|
+
export type { CellColors, Drawn, Effect, EffectCell, EffectedOptions, EffectFrame, Pair, Placed } from "./renderables/effect.js";
|
|
63
|
+
export { EFFECT_CATALOGUE, EFFECT_CURVES, EFFECT_LIGHTS, dissolveOut, fadeIn, onColors, pulse, shimmer, sparkle, steppedInk, wheel, } from "./renderables/effects.js";
|
|
64
|
+
export type { ColorStep, Curve, EffectTarget, Field, Loop, LoopName, Touch, Transition, TransitionName } from "./renderables/effects.js";
|
|
62
65
|
export { Align } from "./renderables/align.js";
|
|
63
66
|
export type { Alignment } from "./core/place.js";
|
|
64
67
|
export { Padding } from "./renderables/padding.js";
|
|
@@ -77,6 +80,8 @@ export { ProgressBar } from "./renderables/progressBar.js";
|
|
|
77
80
|
export type { ProgressBarOptions } from "./renderables/progressBar.js";
|
|
78
81
|
export { Spinner } from "./renderables/spinner.js";
|
|
79
82
|
export type { SpinnerOptions } from "./renderables/spinner.js";
|
|
83
|
+
export { FrameSequence, Frames, frameAt } from "./renderables/frames.js";
|
|
84
|
+
export type { Frame, FramesOptions } from "./renderables/frames.js";
|
|
80
85
|
export { Table, Column } from "./renderables/table.js";
|
|
81
86
|
export type { TableOptions, ColumnOptions } from "./renderables/table.js";
|
|
82
87
|
export { Tree } from "./renderables/tree.js";
|
|
@@ -86,7 +91,7 @@ export type { ColumnsOptions } from "./renderables/columns.js";
|
|
|
86
91
|
export { FlexStrip } from "./renderables/flexStrip.js";
|
|
87
92
|
export type { FlexStripOptions, FlexAlign } from "./renderables/flexStrip.js";
|
|
88
93
|
export { Live } from "./renderables/live.js";
|
|
89
|
-
export type { LiveOptions } from "./renderables/live.js";
|
|
94
|
+
export type { LiveOptions, LiveView } from "./renderables/live.js";
|
|
90
95
|
export { Status } from "./renderables/status.js";
|
|
91
96
|
export type { StatusOptions } from "./renderables/status.js";
|
|
92
97
|
export { Progress, TextColumn, BarColumn, TaskProgressColumn, TimeRemainingColumn, TimeElapsedColumn, SpinnerColumn, MofNCompleteColumn, track, } from "./renderables/progress.js";
|
package/dist/index.js
CHANGED
|
@@ -29,7 +29,16 @@ export { lighten, darken, relativeLuminance, contrastRatio, contrastFor, ensureC
|
|
|
29
29
|
export { ColorRamp } from "./themes/ramp.js";
|
|
30
30
|
// Progress in [0, 1]: phases turn seconds into it, eases reshape it. One
|
|
31
31
|
// vocabulary for ramps and time-based effects alike, CSS's names throughout.
|
|
32
|
-
export { EASES, Phase, cubicBezier, parseEase, steps } from "./core/easing.js";
|
|
32
|
+
export { EASES, Phase, beat, cubicBezier, parseEase, spring, steps } from "./core/easing.js";
|
|
33
|
+
// A value for a time, and when it next changes: the one type every kind of
|
|
34
|
+
// motion is an instance of — beats, frame sequences, spinners, effects.
|
|
35
|
+
export { Animation } from "./core/animation.js";
|
|
36
|
+
// A number eased from one value to another over seconds, then held: the
|
|
37
|
+
// value animation a fill, a counter or a width moves by instead of jumping.
|
|
38
|
+
export { tween } from "./core/tween.js";
|
|
39
|
+
// The map from the host's clock to the time an animation is asked for:
|
|
40
|
+
// pause, reverse, scrub and speed, once, above every kind of motion.
|
|
41
|
+
export { Timeline } from "./core/timeline.js";
|
|
33
42
|
// The time source and timer whoever draws frames is handed, and the one
|
|
34
43
|
// parser of the rate it ticks at.
|
|
35
44
|
export { frameRate, systemClock } from "./core/clock.js";
|
|
@@ -38,13 +47,13 @@ export { Segment, ControlType, } from "./core/segment.js";
|
|
|
38
47
|
export { Box } from "./core/box.js";
|
|
39
48
|
export { ASCII, ASCII2, ASCII_DOUBLE_HEAD, SQUARE, SQUARE_DOUBLE_HEAD, MINIMAL, MINIMAL_HEAVY_HEAD, MINIMAL_DOUBLE_HEAD, SIMPLE, SIMPLE_HEAD, SIMPLE_HEAVY, HORIZONTALS, ROUNDED, HEAVY, HEAVY_EDGE, HEAVY_HEAD, DOUBLE, DOUBLE_EDGE, MARKDOWN, } from "./core/box.js";
|
|
40
49
|
// Protocol
|
|
41
|
-
export { isRenderable, isMeasurable, withCellWidth, withBoundedWidth, insetHeight, stackedHeight, regionRows, fitHeight, getStyle, } from "./core/protocol.js";
|
|
50
|
+
export { render, isRenderable, isMeasurable, withCellWidth, withBoundedWidth, insetHeight, stackedHeight, regionRows, fitHeight, getStyle, } from "./core/protocol.js";
|
|
42
51
|
// Measurement
|
|
43
52
|
export { Measurement, measureRenderables } from "./core/measure.js";
|
|
44
53
|
// Text
|
|
45
54
|
export { Span, RichText } from "./core/text.js";
|
|
46
55
|
// Strip + Joiner
|
|
47
|
-
export { Strip, CellJoiner, SEAM_MIN_DELTA_E, JOINERS, joinerNamed,
|
|
56
|
+
export { Strip, CellJoiner, SEAM_MIN_DELTA_E, SEAMS, CAPS, JOINERS, joinerNamed, gradientSeam, } from "./core/strip.js";
|
|
48
57
|
// renderToString — stateless one-shot emission
|
|
49
58
|
export { renderToString, segmentToString, segmentsToString, } from "./core/render.js";
|
|
50
59
|
// OSC 8 hyperlink wire grammar — for consumers that read rendered bytes back
|
|
@@ -69,8 +78,8 @@ export { SPINNERS, DEFAULT_SPINNER } from "./core/spinnerData.js";
|
|
|
69
78
|
export { Console } from "./core/console.js";
|
|
70
79
|
// Renderables
|
|
71
80
|
export { Constrain } from "./renderables/constrain.js";
|
|
72
|
-
export { Effected, confined, drawnOf } from "./renderables/effect.js";
|
|
73
|
-
export { EFFECT_CATALOGUE, EFFECT_CURVES, EFFECT_LIGHTS, dissolveOut, fadeIn, onColors, pulse, shimmer, sparkle, wheel, } from "./renderables/effects.js";
|
|
81
|
+
export { Effected, confined, drawnOf, onBeat } from "./renderables/effect.js";
|
|
82
|
+
export { EFFECT_CATALOGUE, EFFECT_CURVES, EFFECT_LIGHTS, dissolveOut, fadeIn, onColors, pulse, shimmer, sparkle, steppedInk, wheel, } from "./renderables/effects.js";
|
|
74
83
|
export { Align } from "./renderables/align.js";
|
|
75
84
|
export { Padding } from "./renderables/padding.js";
|
|
76
85
|
export { Viewport, ViewportPerKey, SCROLLBAR } from "./renderables/viewport.js";
|
|
@@ -81,6 +90,7 @@ export { Panel } from "./renderables/panel.js";
|
|
|
81
90
|
export { Group } from "./renderables/group.js";
|
|
82
91
|
export { ProgressBar } from "./renderables/progressBar.js";
|
|
83
92
|
export { Spinner } from "./renderables/spinner.js";
|
|
93
|
+
export { FrameSequence, Frames, frameAt } from "./renderables/frames.js";
|
|
84
94
|
export { Table, Column } from "./renderables/table.js";
|
|
85
95
|
export { Tree } from "./renderables/tree.js";
|
|
86
96
|
export { Columns } from "./renderables/columns.js";
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* `setRawMode` in the runtime or in a demo, take a `TerminalHost` parameter
|
|
28
28
|
* instead. The seam is already here.
|
|
29
29
|
*/
|
|
30
|
-
import type { DataHandler, ExitHandler, ResizeHandler, TerminalHost, TerminalSize } from "../host/terminal-host.js";
|
|
30
|
+
import type { DataHandler, ExitHandler, InputChunks, ResizeHandler, TerminalHost, TerminalSize } from "../host/terminal-host.js";
|
|
31
31
|
import type { Unsubscribe } from "../core/subscription.js";
|
|
32
32
|
import type { Env } from "../core/env.js";
|
|
33
33
|
/**
|
|
@@ -42,6 +42,12 @@ interface NodeReadable {
|
|
|
42
42
|
resume?(): unknown;
|
|
43
43
|
pause?(): unknown;
|
|
44
44
|
readonly isTTY?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Set by a stream that delivers whole keys — the docs site's simulated
|
|
47
|
+
* stdin forwards xterm.js's events one to one. Node's own stdin is a tty
|
|
48
|
+
* read and sets nothing, so it is `"split"`.
|
|
49
|
+
*/
|
|
50
|
+
readonly inputChunks?: InputChunks;
|
|
45
51
|
}
|
|
46
52
|
interface NodeWritable {
|
|
47
53
|
write(chunk: string | Uint8Array): unknown;
|
|
@@ -98,6 +104,7 @@ export declare class NodeTerminalHost implements TerminalHost {
|
|
|
98
104
|
private readonly stdout;
|
|
99
105
|
private readonly process;
|
|
100
106
|
readonly env: Env;
|
|
107
|
+
readonly inputChunks: InputChunks;
|
|
101
108
|
private readonly dataHandlers;
|
|
102
109
|
private readonly resizeHandlers;
|
|
103
110
|
private dataListener;
|
|
@@ -45,6 +45,7 @@ export class NodeTerminalHost {
|
|
|
45
45
|
stdout;
|
|
46
46
|
process;
|
|
47
47
|
env;
|
|
48
|
+
inputChunks;
|
|
48
49
|
dataHandlers = new Set();
|
|
49
50
|
resizeHandlers = new Set();
|
|
50
51
|
dataListener;
|
|
@@ -55,6 +56,7 @@ export class NodeTerminalHost {
|
|
|
55
56
|
this.stdout = options.stdout ?? process.stdout;
|
|
56
57
|
this.env = options.env ?? process.env;
|
|
57
58
|
this.process = options.process ?? process;
|
|
59
|
+
this.inputChunks = this.stdin.inputChunks ?? "split";
|
|
58
60
|
}
|
|
59
61
|
get isTTY() {
|
|
60
62
|
return !!this.stdin.isTTY && this.writesToTerminal;
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Align — wraps a renderable and places its output horizontally, as one block.
|
|
3
3
|
*/
|
|
4
4
|
import { Segment } from "../core/segment.js";
|
|
5
|
-
import type { Renderable, Measurable, RenderOptions } from "../core/protocol.js";
|
|
5
|
+
import type { Composite, Renderable, Measurable, RenderOptions } from "../core/protocol.js";
|
|
6
6
|
import { type Alignment } from "../core/place.js";
|
|
7
|
-
export declare class Align implements Renderable, Measurable {
|
|
7
|
+
export declare class Align implements Renderable, Measurable, Composite {
|
|
8
8
|
readonly renderable: Renderable;
|
|
9
9
|
readonly align: Alignment;
|
|
10
10
|
constructor(renderable: Renderable, align?: Alignment);
|
|
@@ -13,4 +13,5 @@ export declare class Align implements Renderable, Measurable {
|
|
|
13
13
|
minimum: number;
|
|
14
14
|
maximum: number;
|
|
15
15
|
};
|
|
16
|
+
contents(): Iterable<Renderable>;
|
|
16
17
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { Segment } from "../core/segment.js";
|
|
12
12
|
import type { PaddingDimensions } from "./padding.js";
|
|
13
|
-
import type { Renderable, Measurable, RenderOptions } from "../core/protocol.js";
|
|
13
|
+
import type { Composite, Renderable, Measurable, RenderOptions } from "../core/protocol.js";
|
|
14
14
|
export interface ColumnsOptions {
|
|
15
15
|
expand?: boolean;
|
|
16
16
|
equal?: boolean;
|
|
@@ -18,7 +18,7 @@ export interface ColumnsOptions {
|
|
|
18
18
|
padding?: PaddingDimensions;
|
|
19
19
|
columnFirst?: boolean;
|
|
20
20
|
}
|
|
21
|
-
export declare class Columns implements Renderable, Measurable {
|
|
21
|
+
export declare class Columns implements Renderable, Measurable, Composite {
|
|
22
22
|
renderables: (Renderable & Partial<Measurable>)[];
|
|
23
23
|
readonly expand: boolean;
|
|
24
24
|
readonly equal: boolean;
|
|
@@ -27,6 +27,7 @@ export declare class Columns implements Renderable, Measurable {
|
|
|
27
27
|
private readonly padding;
|
|
28
28
|
constructor(items?: Iterable<unknown>, options?: ColumnsOptions);
|
|
29
29
|
render(rawOptions: RenderOptions): Iterable<Segment>;
|
|
30
|
+
contents(): Iterable<Renderable>;
|
|
30
31
|
measure(rawOptions: RenderOptions): {
|
|
31
32
|
minimum: number;
|
|
32
33
|
maximum: number;
|