@valyrianjs/terminal 0.2.2 → 0.2.4

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/src/session.ts CHANGED
@@ -7,18 +7,19 @@ import { mergeVertical } from "./layout.js";
7
7
  import { cursorFromHitbox, parseTerminalInput, parseTerminalMousePrefix, resolvePointerTarget } from "./mouse.js";
8
8
  import { createOutputWriter } from "./output-writer.js";
9
9
  import { parseBracketedPaste } from "./paste.js";
10
- import { renderTerminalFrame } from "./render.js";
10
+ import { renderTerminalFrame } from "./render-internal.js";
11
11
  import { createRenderScheduler } from "./scheduler.js";
12
12
  import { plainText, stripTerminalControls } from "./text.js";
13
13
  import { collectActiveFocusScopeFocusableNodes, collectDirectOverlayFocusableNodes, collectFocusableNodes, findFocusableById, findFocused } from "./tree.js";
14
14
  import { createValyrianTerminalRuntime } from "./runtime.js";
15
15
 
16
- import type { TerminalRenderContext } from "./render.js";
16
+ import type { TerminalRenderContext } from "./render-internal.js";
17
17
 
18
18
  import type { EditorState } from "./editor-state.js";
19
19
 
20
20
  import type {
21
21
  InputInteractionState,
22
+ TerminalButtonPressEventPayload,
22
23
  TerminalCommand,
23
24
  TerminalCommandContext,
24
25
  TerminalCaptureEventPayload,
@@ -40,13 +41,18 @@ import type {
40
41
 
41
42
  type TerminalInputStream = NonNullable<TerminalMountOptions["stdin"]>;
42
43
 
44
+ type InternalTerminalHitbox = TerminalHitbox & {
45
+ __listItemIndex?: number;
46
+ __pressHandler?: (event: TerminalButtonPressEventPayload) => void;
47
+ };
48
+
43
49
  interface ResolvedRuntimeOptions {
44
50
  runtime: "app" | "headless";
45
51
  stdin?: TerminalInputStream;
46
52
  stdout?: TerminalOutputStream;
47
53
  alternateScreen: boolean;
48
54
  hideCursor: boolean;
49
- mouseReporting: boolean;
55
+ mouseInput: boolean;
50
56
  writesAnsi: boolean;
51
57
  }
52
58
 
@@ -82,6 +88,7 @@ const KNOWN_TERMINAL_KEY_SEQUENCES = [
82
88
  const ESCAPE = "\u001b";
83
89
  const CSI_PREFIX = "\u001b[";
84
90
  const DOUBLE_PRESS_INTERVAL_MS = 500;
91
+ const MODAL_OVERLAY_HITBOX_ID = "\u0000valyrian-overlay-modal-shield";
85
92
 
86
93
  function isBracketedPasteStartPrefix(value: string) {
87
94
  return value.length > 0 && value.length < BRACKETED_PASTE_START.length && BRACKETED_PASTE_START.startsWith(value);
@@ -95,6 +102,38 @@ function isKnownTerminalKeySequencePrefix(value: string) {
95
102
  return KNOWN_TERMINAL_KEY_SEQUENCES.some((sequence) => value.length > 0 && value.length < sequence.length && sequence.startsWith(value));
96
103
  }
97
104
 
105
+ function isSgrMouseSequencePrefix(value: string) {
106
+ return /^\u001b\[<(?:\d+)?(?:;(?:\d+)?)?(?:;(?:\d+)?)?$/.test(value);
107
+ }
108
+
109
+ function isDigit(value: string) {
110
+ return value >= "0" && value <= "9";
111
+ }
112
+
113
+ function restAfterInvalidSgrMouseSequence(value: string) {
114
+ if (!value.startsWith("\u001b[<")) {
115
+ return null;
116
+ }
117
+
118
+ let separators = 0;
119
+ for (let index = "\u001b[<".length; index < value.length; index += 1) {
120
+ const char = value[index];
121
+ if (isDigit(char)) {
122
+ continue;
123
+ }
124
+ if (char === ";" && separators < 2) {
125
+ separators += 1;
126
+ continue;
127
+ }
128
+ if (char === "M" || char === "m") {
129
+ return value.slice(index + 1);
130
+ }
131
+ return value.slice(index);
132
+ }
133
+
134
+ return null;
135
+ }
136
+
98
137
  function canContinueEscapeSequence(value: string) {
99
138
  return value.startsWith("[") || value.startsWith("b") || value.startsWith("f");
100
139
  }
@@ -110,6 +149,20 @@ function isValidTerminalDimension(value: number | undefined): value is number {
110
149
  return Number.isInteger(value) && Number(value) >= 1;
111
150
  }
112
151
 
152
+ function isModalOverlayShieldHitbox(hitbox: TerminalHitbox | null | undefined) {
153
+ return hitbox?.id === MODAL_OVERLAY_HITBOX_ID;
154
+ }
155
+
156
+ function hitboxIsAboveModalShield(hitboxes: TerminalHitbox[], id: string) {
157
+ const shieldIndex = hitboxes.findIndex((box) => isModalOverlayShieldHitbox(box));
158
+ if (shieldIndex < 0) {
159
+ return true;
160
+ }
161
+
162
+ const hitboxIndex = hitboxes.findIndex((box) => box.id === id);
163
+ return hitboxIndex >= 0 && hitboxIndex < shieldIndex;
164
+ }
165
+
113
166
 
114
167
  function getProcessStdin(): TerminalInputStream | undefined {
115
168
  const candidate = globalThis.process?.stdin as TerminalInputStream | undefined;
@@ -140,7 +193,7 @@ function resolveRuntimeOptions(options: TerminalMountOptions): ResolvedRuntimeOp
140
193
  stdout,
141
194
  alternateScreen: options.alternateScreen ?? ownsInteractiveTTY,
142
195
  hideCursor: options.hideCursor ?? ownsInteractiveTTY,
143
- mouseReporting: ownsInteractiveTTY,
196
+ mouseInput: ownsInteractiveTTY,
144
197
  writesAnsi: runtime === "app" && Boolean(stdout)
145
198
  };
146
199
  }
@@ -254,7 +307,7 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
254
307
  applyInteractiveState(currentTree, focusedId, inputStateById, editorStateById, listIndexById, listSelectedIndexById, listViewportOffsetById, scrollOffsetById, listHoverById, scrollHoverRowById);
255
308
  let currentFrame = renderTreeFrame(currentTree);
256
309
  let currentOutput = formatPlainFrame(currentFrame, { theme: options.theme }).trimEnd();
257
- let currentHitboxes = currentFrame.hitboxes;
310
+ let currentHitboxes = currentFrame.hitboxes as InternalTerminalHitbox[];
258
311
 
259
312
  const outputWriter = createOutputWriter(runtimeOptions.stdout);
260
313
  const toAnsiDiff = createAnsiDiffWriter({ showCursor: !runtimeOptions.hideCursor, showCursorWhenFrameHasCursor: true, theme: options.theme });
@@ -272,6 +325,28 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
272
325
  return mergeVertical(nodes.map((node) => renderTerminalFrame(node, context)));
273
326
  }
274
327
 
328
+ function publicTerminalNodes(nodes: TerminalNode[]): TerminalNode[] {
329
+ return nodes.map((node) => {
330
+ if (node.type === "text") {
331
+ return { ...node };
332
+ }
333
+
334
+ const publicProps: Record<string, any> = {};
335
+ for (const [key, value] of Object.entries(node.props)) {
336
+ if (!key.startsWith("__")) {
337
+ publicProps[key] = value;
338
+ }
339
+ }
340
+
341
+ return {
342
+ type: node.type,
343
+ tag: node.tag,
344
+ props: publicProps,
345
+ children: publicTerminalNodes(node.children)
346
+ };
347
+ });
348
+ }
349
+
275
350
  function emitLifecycleSetup() {
276
351
  const writes: string[] = [];
277
352
  if (runtimeOptions.alternateScreen) {
@@ -280,7 +355,7 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
280
355
  if (runtimeOptions.hideCursor) {
281
356
  writes.push(ANSI_HIDE_CURSOR);
282
357
  }
283
- if (runtimeOptions.mouseReporting) {
358
+ if (runtimeOptions.mouseInput) {
284
359
  writes.push(ANSI_ENABLE_MOUSE_REPORTING);
285
360
  }
286
361
  if (writes.length > 0) {
@@ -293,7 +368,7 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
293
368
  return;
294
369
  }
295
370
  const writes: string[] = [];
296
- if (runtimeOptions.mouseReporting) {
371
+ if (runtimeOptions.mouseInput) {
297
372
  writes.push(ANSI_DISABLE_MOUSE_REPORTING);
298
373
  }
299
374
  if (runtimeOptions.hideCursor) {
@@ -308,9 +383,10 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
308
383
  }
309
384
 
310
385
  function emitOutput() {
311
- if (!destroyed) {
312
- outputWriter.write(runtimeOptions.writesAnsi ? toAnsiDiff(currentFrame.lines, currentFrame.cursor, currentFrame.spans) : currentOutput);
386
+ if (destroyed) {
387
+ return;
313
388
  }
389
+ outputWriter.write(runtimeOptions.writesAnsi ? toAnsiDiff(currentFrame.lines, currentFrame.cursor, currentFrame.spans) : currentOutput);
314
390
  }
315
391
 
316
392
  function renderNow() {
@@ -329,7 +405,7 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
329
405
  applyInteractiveState(currentTree, focusedId, inputStateById, editorStateById, listIndexById, listSelectedIndexById, listViewportOffsetById, scrollOffsetById, listHoverById, scrollHoverRowById);
330
406
  currentFrame = renderTreeFrame(currentTree);
331
407
  currentOutput = formatPlainFrame(currentFrame, { theme: options.theme }).trimEnd();
332
- currentHitboxes = currentFrame.hitboxes;
408
+ currentHitboxes = currentFrame.hitboxes as InternalTerminalHitbox[];
333
409
  emitOutput();
334
410
  return currentOutput;
335
411
  }
@@ -480,7 +556,7 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
480
556
  return 1;
481
557
  }
482
558
 
483
- function sourceRowFromHitbox(node: TerminalFocusNode, hitbox: { itemOffset?: number; itemIndexes?: number[]; y1: number; y2: number; contentY?: number; __listItemIndex?: number }, y: number) {
559
+ function sourceRowFromHitbox(node: TerminalFocusNode, hitbox: InternalTerminalHitbox, y: number) {
484
560
  if (node.tag === "terminal-list" && typeof hitbox.__listItemIndex === "number" && y >= hitbox.y1 && y <= hitbox.y2) {
485
561
  return Math.max(1, Math.min(rowCountForNode(node), hitbox.__listItemIndex + 1));
486
562
  }
@@ -541,7 +617,6 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
541
617
  }
542
618
  }
543
619
 
544
-
545
620
  function listItemKey(node: TerminalFocusNode, index: number) {
546
621
  const items = Array.isArray(node.props.items) ? node.props.items : [];
547
622
  const item = items[index];
@@ -670,7 +745,7 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
670
745
  return dispatchNodeEvent(node, type, { type, id });
671
746
  }
672
747
 
673
- function dispatchHitboxButtonPressEvent(hitbox: TerminalHitbox, type: "press" | "doublepress" | "contextpress") {
748
+ function dispatchHitboxButtonPressEvent(hitbox: InternalTerminalHitbox, type: "press" | "doublepress" | "contextpress") {
674
749
  if (type !== "press" || typeof hitbox.__pressHandler !== "function") {
675
750
  return false;
676
751
  }
@@ -804,11 +879,19 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
804
879
 
805
880
  function hoverAt(x: number, y: number) {
806
881
  const hitbox = resolvePointerTarget(currentHitboxes, x, y);
807
- if (!hitbox) {
808
- if (pointerCaptureId) {
882
+ if (!hitbox || isModalOverlayShieldHitbox(hitbox)) {
883
+ if (pointerCaptureId && (!hitbox || hitboxIsAboveModalShield(currentHitboxes, pointerCaptureId))) {
809
884
  setSemanticHoverFromHitbox(pointerCaptureId, x, y);
810
885
  return rerender();
811
886
  }
887
+ if (pointerCaptureId) {
888
+ const capturedHitbox = currentHitboxes.find((box) => box.id === pointerCaptureId);
889
+ const capturedNode = findFocusableById(currentTree, pointerCaptureId);
890
+ const capturedRow = capturedHitbox && capturedNode
891
+ ? sourceRowFromHitbox(capturedNode, capturedHitbox, y)
892
+ : hoveredRowForNode(capturedNode);
893
+ setPointerCapture(null, "drag", capturedRow, x, y);
894
+ }
812
895
  clearSemanticHover(undefined, x, y);
813
896
  return rerender();
814
897
  }
@@ -910,7 +993,7 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
910
993
 
911
994
  function wheelAt(x: number, y: number, direction: -1 | 1) {
912
995
  const hitbox = resolvePointerTarget(currentHitboxes, x, y);
913
- if (!hitbox) {
996
+ if (!hitbox || isModalOverlayShieldHitbox(hitbox)) {
914
997
  return currentOutput;
915
998
  }
916
999
 
@@ -1165,7 +1248,7 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
1165
1248
  return toAnsiFrame(currentFrame.lines, currentFrame.cursor, currentFrame.spans, { showCursor: !options.hideCursor, showCursorWhenFrameHasCursor: true, theme: options.theme });
1166
1249
  },
1167
1250
  tree() {
1168
- return currentTree;
1251
+ return publicTerminalNodes(currentTree);
1169
1252
  },
1170
1253
  focus(id: string) {
1171
1254
  const node = findFocusableById(currentTree, id);
@@ -1178,7 +1261,7 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
1178
1261
  },
1179
1262
  focusAt(x: number, y: number) {
1180
1263
  const hitbox = resolvePointerTarget(currentHitboxes, x, y);
1181
- if (!hitbox) {
1264
+ if (!hitbox || isModalOverlayShieldHitbox(hitbox)) {
1182
1265
  clearSemanticHover(undefined, x, y);
1183
1266
  return false;
1184
1267
  }
@@ -1238,7 +1321,7 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
1238
1321
  },
1239
1322
  clickAt(x: number, y: number) {
1240
1323
  const hitbox = resolvePointerTarget(currentHitboxes, x, y);
1241
- if (!hitbox) {
1324
+ if (!hitbox || isModalOverlayShieldHitbox(hitbox)) {
1242
1325
  clearSemanticHover(undefined, x, y);
1243
1326
  return currentOutput;
1244
1327
  }
@@ -1343,6 +1426,18 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
1343
1426
  return;
1344
1427
  }
1345
1428
 
1429
+ const parsedMouse = parseTerminalMousePrefix(value);
1430
+ if (parsedMouse) {
1431
+ processParsedMouseInput(parsedMouse.input);
1432
+ processInputStream(parsedMouse.rest);
1433
+ return;
1434
+ }
1435
+
1436
+ if (isSgrMouseSequencePrefix(value)) {
1437
+ pendingKeyChunk = value;
1438
+ return;
1439
+ }
1440
+
1346
1441
  for (const sequence of KNOWN_TERMINAL_KEY_SEQUENCES) {
1347
1442
  if (value.startsWith(sequence)) {
1348
1443
  session.dispatchKey(parseTerminalKey(sequence));
@@ -1400,7 +1495,6 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
1400
1495
  }
1401
1496
  }
1402
1497
 
1403
-
1404
1498
  function isPrimaryMouseButton(button: number) {
1405
1499
  return button < 64 && (button & 3) === 0;
1406
1500
  }
@@ -1442,7 +1536,7 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
1442
1536
 
1443
1537
  function contextPressAt(x: number, y: number) {
1444
1538
  const hitbox = resolvePointerTarget(currentHitboxes, x, y);
1445
- if (!hitbox) {
1539
+ if (!hitbox || isModalOverlayShieldHitbox(hitbox)) {
1446
1540
  clearSemanticHover(undefined, x, y);
1447
1541
  return currentOutput;
1448
1542
  }
@@ -1514,7 +1608,12 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
1514
1608
  }
1515
1609
  } else if (parsed.action === "drag") {
1516
1610
  if (mouseSelectionId) {
1517
- setCursorFromHitbox(mouseSelectionId, parsed.x, true);
1611
+ if (!hitboxIsAboveModalShield(currentHitboxes, mouseSelectionId)) {
1612
+ mouseSelectionId = null;
1613
+ hoverAt(parsed.x, parsed.y);
1614
+ } else {
1615
+ setCursorFromHitbox(mouseSelectionId, parsed.x, true);
1616
+ }
1518
1617
  } else {
1519
1618
  hoverAt(parsed.x, parsed.y);
1520
1619
  }
@@ -1574,6 +1673,21 @@ export function mountTerminal(input: any, options: TerminalMountOptions = {}): T
1574
1673
  const buffered = pendingKeyChunk + value;
1575
1674
  cancelPendingEscapeFlush();
1576
1675
  pendingKeyChunk = "";
1676
+ if (isSgrMouseSequencePrefix(buffered)) {
1677
+ pendingKeyChunk = buffered;
1678
+ return;
1679
+ }
1680
+ const parsedBufferedMouse = parseTerminalMousePrefix(buffered);
1681
+ if (parsedBufferedMouse) {
1682
+ processParsedMouseInput(parsedBufferedMouse.input);
1683
+ processInputStream(parsedBufferedMouse.rest);
1684
+ return;
1685
+ }
1686
+ const restAfterInvalidSgrMouse = restAfterInvalidSgrMouseSequence(buffered);
1687
+ if (typeof restAfterInvalidSgrMouse === "string") {
1688
+ processInputStream(restAfterInvalidSgrMouse);
1689
+ return;
1690
+ }
1577
1691
  processKeyStream(buffered);
1578
1692
  return;
1579
1693
  }
package/src/text.ts CHANGED
@@ -5,6 +5,8 @@ const C1_CSI_TERMINAL_CONTROL = /\u009b[0-?]*[ -/]*[@-~]/g;
5
5
  const ESC_TERMINAL_CONTROL = /\u001b[ -/]*[0-~]/g;
6
6
  const C1_TERMINAL_CONTROL = /[\u0080-\u009f]/g;
7
7
  const C0_TERMINAL_CONTROL = /[\u0000-\u0009\u000b-\u001f\u007f]/g;
8
+ const CELL_WIDTH_CACHE_LIMIT = 4096;
9
+ const cellWidthCache = new Map<string, number>();
8
10
  const COMBINING_MARK = /\p{Mark}/u;
9
11
  const EMOJI_PRESENTATION = /\p{Extended_Pictographic}/u;
10
12
 
@@ -92,7 +94,17 @@ function graphemeCellWidth(grapheme: string) {
92
94
 
93
95
  export function terminalCellWidth(value: unknown) {
94
96
  const text = stripTerminalControls(value);
95
- return terminalGraphemes(text).reduce((width, grapheme) => width + graphemeCellWidth(grapheme), 0);
97
+ const cached = cellWidthCache.get(text);
98
+ if (typeof cached === "number") {
99
+ return cached;
100
+ }
101
+
102
+ const width = terminalGraphemes(text).reduce((total, grapheme) => total + graphemeCellWidth(grapheme), 0);
103
+ if (cellWidthCache.size >= CELL_WIDTH_CACHE_LIMIT) {
104
+ cellWidthCache.clear();
105
+ }
106
+ cellWidthCache.set(text, width);
107
+ return width;
96
108
  }
97
109
 
98
110
  export function sliceTerminalCells(value: string, maxCells: number) {
package/src/theme.ts CHANGED
@@ -80,7 +80,7 @@ export const defaultTerminalTheme: TerminalTheme = {
80
80
  list: { base: { color: "#d8dee9" }, selected: { color: "#ffffff", background: "#2e3440" }, current: { color: "#ffffff", background: "#3b4252" }, hover: { color: "#ffffff", background: "#2b3137" }, empty: { color: "#777777" }, expanded: { color: "#b48ead" }, collapsed: { color: "#81a1c1" } },
81
81
  scroll: { base: { color: "#d8dee9" }, hover: { color: "#dddddd" } },
82
82
  log: { base: { color: "#d8dee9" }, empty: { color: "#777777" }, error: { color: "#bf616a" }, warning: { color: "#ebcb8b" }, success: { color: "#a3be8c" }, muted: { color: "#777777" } },
83
- overlay: { base: { background: "#111111" }, dragging: { color: "#b48ead" }, dropTarget: { background: "#243b53" }, capturing: { color: "#d08770" } },
83
+ overlay: { base: { background: "#111111" }, backdrop: { background: "#000000" }, dragging: { color: "#b48ead" }, dropTarget: { background: "#243b53" }, capturing: { color: "#d08770" } },
84
84
  pane: {
85
85
  header: { background: "#3a3a3a", color: "#ffffff" },
86
86
  transcript: { background: "#303030", color: "#dddddd" },
@@ -107,6 +107,9 @@ export const defaultTerminalTheme: TerminalTheme = {
107
107
  focus: {
108
108
  background: "#1f2328"
109
109
  },
110
+ "editor.focus": {
111
+ background: "#161b22"
112
+ },
110
113
  "current-row": reverseVideoToken,
111
114
  hover: {
112
115
  ansiOpen: "\u001b[4m",
@@ -183,6 +186,26 @@ export function mergeTerminalTheme(theme?: TerminalTheme): TerminalTheme {
183
186
  };
184
187
  }
185
188
 
189
+ const DEFAULT_MERGED_THEME = mergeTerminalTheme();
190
+ // Maintainer note: theme objects are treated as immutable for the CLI lifetime.
191
+ // Restart the CLI to apply theme changes instead of mutating a cached source theme.
192
+ const MERGED_THEME_BY_SOURCE = new WeakMap<TerminalTheme, TerminalTheme>();
193
+
194
+ function resolveMergedTerminalTheme(theme?: TerminalTheme): TerminalTheme {
195
+ if (typeof theme === "undefined") {
196
+ return DEFAULT_MERGED_THEME;
197
+ }
198
+
199
+ const cached = MERGED_THEME_BY_SOURCE.get(theme);
200
+ if (cached) {
201
+ return cached;
202
+ }
203
+
204
+ const merged = mergeTerminalTheme(theme);
205
+ MERGED_THEME_BY_SOURCE.set(theme, merged);
206
+ return merged;
207
+ }
208
+
186
209
  function isPlainObject(value: unknown): value is Record<string, unknown> {
187
210
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
188
211
  }
@@ -239,7 +262,7 @@ export function resolveTerminalStyle(value: TerminalStyleValue | undefined, them
239
262
  if (typeof value !== "string") {
240
263
  return { ...value, border: isPlainObject(value.border) ? { ...value.border } : value.border, padding: isPlainObject(value.padding) ? { ...value.padding } : value.padding };
241
264
  }
242
- const merged = mergeTerminalTheme(theme);
265
+ const merged = resolveMergedTerminalTheme(theme);
243
266
  const parts = value.split(".").filter(Boolean);
244
267
  let node: unknown = merged.styles;
245
268
  for (const part of parts) {
@@ -262,5 +285,5 @@ export function resolveTerminalStyleToken(
262
285
  kind: TerminalSemanticStyleKind | (string & {}),
263
286
  theme?: TerminalTheme
264
287
  ): TerminalStyleToken | undefined {
265
- return mergeTerminalTheme(theme).spans?.[kind];
288
+ return resolveMergedTerminalTheme(theme).spans?.[kind];
266
289
  }
package/src/types.ts CHANGED
@@ -134,8 +134,6 @@ export interface TerminalHitbox {
134
134
  itemIndexes?: number[];
135
135
  contentY?: number;
136
136
  pointerLayer?: number;
137
- __listItemIndex?: number;
138
- __pressHandler?: (event: TerminalButtonPressEventPayload) => void;
139
137
  }
140
138
 
141
139
  export interface CursorPosition {
@@ -507,6 +505,7 @@ export interface TerminalOverlayMarginAxes {
507
505
  export interface TerminalOverlayProps extends TerminalFocusableProps, TerminalStyleProps {
508
506
  margin: TerminalOverlayMarginValue | TerminalOverlayMarginAxes;
509
507
  trapFocus?: boolean;
508
+ backdrop?: boolean | TerminalStyleValue;
510
509
  }
511
510
 
512
511
  export interface TerminalFocusScopeProps {