@opentui/core 0.0.0-20250912-12c969f4 → 0.0.0-20250915-7be4d9eb
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/3d.js +1 -1
- package/3d.js.map +1 -1
- package/Renderable.d.ts +0 -2
- package/buffer.d.ts +1 -0
- package/{index-mh94hn7d.js → index-dgjbzqw3.js} +524 -123
- package/index-dgjbzqw3.js.map +38 -0
- package/index.js +24 -13
- package/index.js.map +5 -5
- package/lib/KeyHandler.d.ts +7 -3
- package/lib/parse.keypress-kitty.d.ts +2 -0
- package/lib/parse.keypress.d.ts +11 -1
- package/package.json +12 -7
- package/renderables/TextNode.d.ts +5 -2
- package/renderer.d.ts +8 -0
- package/testing/test-renderer.d.ts +3 -0
- package/testing.d.ts +3 -0
- package/testing.js +343 -0
- package/testing.js.map +12 -0
- package/types.d.ts +2 -0
- package/zig.d.ts +3 -1
- package/index-mh94hn7d.js.map +0 -37
package/lib/KeyHandler.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { EventEmitter } from "events";
|
|
2
2
|
import { type ParsedKey } from "./parse.keypress";
|
|
3
|
+
export type { ParsedKey };
|
|
3
4
|
type KeyHandlerEventMap = {
|
|
4
5
|
keypress: [ParsedKey];
|
|
6
|
+
keyrepeat: [ParsedKey];
|
|
7
|
+
keyrelease: [ParsedKey];
|
|
5
8
|
};
|
|
6
9
|
export declare class KeyHandler extends EventEmitter<KeyHandlerEventMap> {
|
|
7
|
-
|
|
10
|
+
private stdin;
|
|
11
|
+
private useKittyKeyboard;
|
|
12
|
+
constructor(stdin?: NodeJS.ReadStream, useKittyKeyboard?: boolean);
|
|
8
13
|
destroy(): void;
|
|
9
14
|
}
|
|
10
|
-
export declare function getKeyHandler(): KeyHandler;
|
|
11
|
-
export {};
|
|
15
|
+
export declare function getKeyHandler(useKittyKeyboard?: boolean): KeyHandler;
|
package/lib/parse.keypress.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
2
|
export declare const nonAlphanumericKeys: string[];
|
|
3
|
+
export type KeyEventType = "press" | "repeat" | "release";
|
|
3
4
|
export type ParsedKey = {
|
|
4
5
|
name: string;
|
|
5
6
|
ctrl: boolean;
|
|
@@ -9,6 +10,15 @@ export type ParsedKey = {
|
|
|
9
10
|
sequence: string;
|
|
10
11
|
number: boolean;
|
|
11
12
|
raw: string;
|
|
13
|
+
eventType: KeyEventType;
|
|
12
14
|
code?: string;
|
|
15
|
+
super?: boolean;
|
|
16
|
+
hyper?: boolean;
|
|
17
|
+
capsLock?: boolean;
|
|
18
|
+
numLock?: boolean;
|
|
19
|
+
baseCode?: number;
|
|
13
20
|
};
|
|
14
|
-
export
|
|
21
|
+
export type ParseKeypressOptions = {
|
|
22
|
+
useKittyKeyboard?: boolean;
|
|
23
|
+
};
|
|
24
|
+
export declare const parseKeypress: (s?: Buffer | string, options?: ParseKeypressOptions) => ParsedKey;
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"version": "0.0.0-
|
|
7
|
+
"version": "0.0.0-20250915-7be4d9eb",
|
|
8
8
|
"description": "OpenTUI is a TypeScript library for building terminal user interfaces (TUIs)",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"repository": {
|
|
@@ -22,6 +22,11 @@
|
|
|
22
22
|
"import": "./3d.js",
|
|
23
23
|
"require": "./3d.js",
|
|
24
24
|
"types": "./3d.d.ts"
|
|
25
|
+
},
|
|
26
|
+
"./testing": {
|
|
27
|
+
"import": "./testing.js",
|
|
28
|
+
"require": "./testing.js",
|
|
29
|
+
"types": "./testing.d.ts"
|
|
25
30
|
}
|
|
26
31
|
},
|
|
27
32
|
"dependencies": {
|
|
@@ -38,11 +43,11 @@
|
|
|
38
43
|
"bun-webgpu": "0.1.3",
|
|
39
44
|
"planck": "^1.4.2",
|
|
40
45
|
"three": "0.177.0",
|
|
41
|
-
"@opentui/core-darwin-x64": "0.0.0-
|
|
42
|
-
"@opentui/core-darwin-arm64": "0.0.0-
|
|
43
|
-
"@opentui/core-linux-x64": "0.0.0-
|
|
44
|
-
"@opentui/core-linux-arm64": "0.0.0-
|
|
45
|
-
"@opentui/core-win32-x64": "0.0.0-
|
|
46
|
-
"@opentui/core-win32-arm64": "0.0.0-
|
|
46
|
+
"@opentui/core-darwin-x64": "0.0.0-20250915-7be4d9eb",
|
|
47
|
+
"@opentui/core-darwin-arm64": "0.0.0-20250915-7be4d9eb",
|
|
48
|
+
"@opentui/core-linux-x64": "0.0.0-20250915-7be4d9eb",
|
|
49
|
+
"@opentui/core-linux-arm64": "0.0.0-20250915-7be4d9eb",
|
|
50
|
+
"@opentui/core-win32-x64": "0.0.0-20250915-7be4d9eb",
|
|
51
|
+
"@opentui/core-win32-arm64": "0.0.0-20250915-7be4d9eb"
|
|
47
52
|
}
|
|
48
53
|
}
|
|
@@ -51,9 +51,12 @@ export declare class TextNodeRenderable extends BaseRenderable {
|
|
|
51
51
|
getChildren(): BaseRenderable[];
|
|
52
52
|
getChildrenCount(): number;
|
|
53
53
|
getRenderable(id: string): BaseRenderable | undefined;
|
|
54
|
-
|
|
55
|
-
set
|
|
54
|
+
get fg(): RGBA | undefined;
|
|
55
|
+
set fg(fg: RGBA | string | undefined);
|
|
56
|
+
set bg(bg: RGBA | string | undefined);
|
|
57
|
+
get bg(): RGBA | undefined;
|
|
56
58
|
set attributes(attributes: number);
|
|
59
|
+
get attributes(): number;
|
|
57
60
|
}
|
|
58
61
|
export declare class RootTextNodeRenderable extends TextNodeRenderable {
|
|
59
62
|
private readonly ctx;
|
package/renderer.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { TerminalConsole, type ConsoleOptions } from "./console";
|
|
|
8
8
|
import { type MouseEventType, type RawMouseEvent, type ScrollInfo } from "./lib/parse.mouse";
|
|
9
9
|
import { Selection } from "./lib/selection";
|
|
10
10
|
import { EventEmitter } from "events";
|
|
11
|
+
import { KeyHandler } from "./lib/KeyHandler";
|
|
11
12
|
export interface CliRendererConfig {
|
|
12
13
|
stdin?: NodeJS.ReadStream;
|
|
13
14
|
stdout?: NodeJS.WriteStream;
|
|
@@ -25,6 +26,7 @@ export interface CliRendererConfig {
|
|
|
25
26
|
useAlternateScreen?: boolean;
|
|
26
27
|
useConsole?: boolean;
|
|
27
28
|
experimental_splitHeight?: number;
|
|
29
|
+
useKittyKeyboard?: boolean;
|
|
28
30
|
}
|
|
29
31
|
export type PixelResolution = {
|
|
30
32
|
width: number;
|
|
@@ -111,6 +113,7 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
|
|
|
111
113
|
};
|
|
112
114
|
private _console;
|
|
113
115
|
private _resolution;
|
|
116
|
+
private _keyHandler;
|
|
114
117
|
private animationRequest;
|
|
115
118
|
private resizeTimeoutId;
|
|
116
119
|
private resizeDebounceDelay;
|
|
@@ -136,6 +139,9 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
|
|
|
136
139
|
private _latestPointer;
|
|
137
140
|
private _currentFocusedRenderable;
|
|
138
141
|
private lifecyclePasses;
|
|
142
|
+
private handleError;
|
|
143
|
+
private exitHandler;
|
|
144
|
+
private warningHandler;
|
|
139
145
|
constructor(lib: RenderLib, rendererPtr: Pointer, stdin: NodeJS.ReadStream, stdout: NodeJS.WriteStream, width: number, height: number, config?: CliRendererConfig);
|
|
140
146
|
registerLifecyclePass(renderable: Renderable): void;
|
|
141
147
|
unregisterLifecyclePass(renderable: Renderable): void;
|
|
@@ -151,6 +157,7 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
|
|
|
151
157
|
get isRunning(): boolean;
|
|
152
158
|
get resolution(): PixelResolution | null;
|
|
153
159
|
get console(): TerminalConsole;
|
|
160
|
+
get keyInput(): KeyHandler;
|
|
154
161
|
get terminalWidth(): number;
|
|
155
162
|
get terminalHeight(): number;
|
|
156
163
|
get useThread(): boolean;
|
|
@@ -170,6 +177,7 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
|
|
|
170
177
|
disableKittyKeyboard(): void;
|
|
171
178
|
set useThread(useThread: boolean);
|
|
172
179
|
setupTerminal(): Promise<void>;
|
|
180
|
+
private stdinListener;
|
|
173
181
|
private setupInput;
|
|
174
182
|
private handleMouseData;
|
|
175
183
|
private takeMemorySnapshot;
|
|
@@ -2,6 +2,8 @@ import { CliRenderer, type CliRendererConfig } from "../renderer";
|
|
|
2
2
|
import { createMockKeys } from "./mock-keys";
|
|
3
3
|
import { createMockMouse } from "./mock-mouse";
|
|
4
4
|
export interface TestRendererOptions extends CliRendererConfig {
|
|
5
|
+
width?: number;
|
|
6
|
+
height?: number;
|
|
5
7
|
}
|
|
6
8
|
export interface TestRenderer extends CliRenderer {
|
|
7
9
|
}
|
|
@@ -12,4 +14,5 @@ export declare function createTestRenderer(options: TestRendererOptions): Promis
|
|
|
12
14
|
mockInput: MockInput;
|
|
13
15
|
mockMouse: MockMouse;
|
|
14
16
|
renderOnce: () => Promise<void>;
|
|
17
|
+
captureCharFrame: () => string;
|
|
15
18
|
}>;
|
package/testing.d.ts
ADDED
package/testing.js
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
CliRenderer,
|
|
4
|
+
resolveRenderLib
|
|
5
|
+
} from "./index-dgjbzqw3.js";
|
|
6
|
+
|
|
7
|
+
// src/testing/mock-keys.ts
|
|
8
|
+
var KeyCodes = {
|
|
9
|
+
ENTER: "\r",
|
|
10
|
+
TAB: "\t",
|
|
11
|
+
BACKSPACE: "\b",
|
|
12
|
+
DELETE: "\x1B[3~",
|
|
13
|
+
HOME: "\x1B[H",
|
|
14
|
+
END: "\x1B[F",
|
|
15
|
+
ESCAPE: "\x1B",
|
|
16
|
+
ARROW_UP: "\x1B[A",
|
|
17
|
+
ARROW_DOWN: "\x1B[B",
|
|
18
|
+
ARROW_RIGHT: "\x1B[C",
|
|
19
|
+
ARROW_LEFT: "\x1B[D",
|
|
20
|
+
F1: "\x1BOP",
|
|
21
|
+
F2: "\x1BOQ",
|
|
22
|
+
F3: "\x1BOR",
|
|
23
|
+
F4: "\x1BOS",
|
|
24
|
+
F5: "\x1B[15~",
|
|
25
|
+
F6: "\x1B[17~",
|
|
26
|
+
F7: "\x1B[18~",
|
|
27
|
+
F8: "\x1B[19~",
|
|
28
|
+
F9: "\x1B[20~",
|
|
29
|
+
F10: "\x1B[21~",
|
|
30
|
+
F11: "\x1B[23~",
|
|
31
|
+
F12: "\x1B[24~",
|
|
32
|
+
CTRL_A: "\x01",
|
|
33
|
+
CTRL_B: "\x02",
|
|
34
|
+
CTRL_C: "\x03",
|
|
35
|
+
CTRL_D: "\x04",
|
|
36
|
+
CTRL_E: "\x05",
|
|
37
|
+
CTRL_F: "\x06",
|
|
38
|
+
CTRL_G: "\x07",
|
|
39
|
+
CTRL_H: "\b",
|
|
40
|
+
CTRL_I: "\t",
|
|
41
|
+
CTRL_J: `
|
|
42
|
+
`,
|
|
43
|
+
CTRL_K: "\v",
|
|
44
|
+
CTRL_L: "\f",
|
|
45
|
+
CTRL_M: "\r",
|
|
46
|
+
CTRL_N: "\x0E",
|
|
47
|
+
CTRL_O: "\x0F",
|
|
48
|
+
CTRL_P: "\x10",
|
|
49
|
+
CTRL_Q: "\x11",
|
|
50
|
+
CTRL_R: "\x12",
|
|
51
|
+
CTRL_S: "\x13",
|
|
52
|
+
CTRL_T: "\x14",
|
|
53
|
+
CTRL_U: "\x15",
|
|
54
|
+
CTRL_V: "\x16",
|
|
55
|
+
CTRL_W: "\x17",
|
|
56
|
+
CTRL_X: "\x18",
|
|
57
|
+
CTRL_Y: "\x19",
|
|
58
|
+
CTRL_Z: "\x1A",
|
|
59
|
+
ALT_A: "\x1Ba",
|
|
60
|
+
ALT_B: "\x1Bb",
|
|
61
|
+
ALT_C: "\x1Bc"
|
|
62
|
+
};
|
|
63
|
+
function createMockKeys(renderer) {
|
|
64
|
+
const pressKeys = async (keys, delayMs = 0) => {
|
|
65
|
+
for (const key of keys) {
|
|
66
|
+
let keyCode;
|
|
67
|
+
if (typeof key === "string") {
|
|
68
|
+
if (key in KeyCodes) {
|
|
69
|
+
keyCode = KeyCodes[key];
|
|
70
|
+
} else {
|
|
71
|
+
keyCode = key;
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
keyCode = KeyCodes[key];
|
|
75
|
+
if (!keyCode) {
|
|
76
|
+
throw new Error(`Unknown key: ${key}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
renderer.stdin.emit("data", Buffer.from(keyCode));
|
|
80
|
+
if (delayMs > 0) {
|
|
81
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const pressKey = (key) => {
|
|
86
|
+
let keyCode;
|
|
87
|
+
if (typeof key === "string") {
|
|
88
|
+
if (key in KeyCodes) {
|
|
89
|
+
keyCode = KeyCodes[key];
|
|
90
|
+
} else {
|
|
91
|
+
keyCode = key;
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
keyCode = KeyCodes[key];
|
|
95
|
+
if (!keyCode) {
|
|
96
|
+
throw new Error(`Unknown key: ${key}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
renderer.stdin.emit("data", Buffer.from(keyCode));
|
|
100
|
+
};
|
|
101
|
+
const typeText = async (text, delayMs = 0) => {
|
|
102
|
+
const keys = text.split("");
|
|
103
|
+
await pressKeys(keys, delayMs);
|
|
104
|
+
};
|
|
105
|
+
const pressEnter = () => {
|
|
106
|
+
pressKey(KeyCodes.ENTER);
|
|
107
|
+
};
|
|
108
|
+
const pressEscape = () => {
|
|
109
|
+
pressKey(KeyCodes.ESCAPE);
|
|
110
|
+
};
|
|
111
|
+
const pressTab = () => {
|
|
112
|
+
pressKey(KeyCodes.TAB);
|
|
113
|
+
};
|
|
114
|
+
const pressBackspace = () => {
|
|
115
|
+
pressKey(KeyCodes.BACKSPACE);
|
|
116
|
+
};
|
|
117
|
+
const pressArrow = (direction) => {
|
|
118
|
+
const keyMap = {
|
|
119
|
+
up: KeyCodes.ARROW_UP,
|
|
120
|
+
down: KeyCodes.ARROW_DOWN,
|
|
121
|
+
left: KeyCodes.ARROW_LEFT,
|
|
122
|
+
right: KeyCodes.ARROW_RIGHT
|
|
123
|
+
};
|
|
124
|
+
pressKey(keyMap[direction]);
|
|
125
|
+
};
|
|
126
|
+
const pressCtrlC = () => {
|
|
127
|
+
pressKey(KeyCodes.CTRL_C);
|
|
128
|
+
};
|
|
129
|
+
return {
|
|
130
|
+
pressKeys,
|
|
131
|
+
pressKey,
|
|
132
|
+
typeText,
|
|
133
|
+
pressEnter,
|
|
134
|
+
pressEscape,
|
|
135
|
+
pressTab,
|
|
136
|
+
pressBackspace,
|
|
137
|
+
pressArrow,
|
|
138
|
+
pressCtrlC
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/testing/mock-mouse.ts
|
|
143
|
+
var MouseButtons = {
|
|
144
|
+
LEFT: 0,
|
|
145
|
+
MIDDLE: 1,
|
|
146
|
+
RIGHT: 2,
|
|
147
|
+
WHEEL_UP: 64,
|
|
148
|
+
WHEEL_DOWN: 65,
|
|
149
|
+
WHEEL_LEFT: 66,
|
|
150
|
+
WHEEL_RIGHT: 67
|
|
151
|
+
};
|
|
152
|
+
function createMockMouse(renderer) {
|
|
153
|
+
let currentPosition = { x: 0, y: 0 };
|
|
154
|
+
let buttonsPressed = new Set;
|
|
155
|
+
const generateMouseEvent = (type, x, y, button = MouseButtons.LEFT, modifiers = {}) => {
|
|
156
|
+
let buttonCode = button;
|
|
157
|
+
if (modifiers.shift)
|
|
158
|
+
buttonCode |= 4;
|
|
159
|
+
if (modifiers.alt)
|
|
160
|
+
buttonCode |= 8;
|
|
161
|
+
if (modifiers.ctrl)
|
|
162
|
+
buttonCode |= 16;
|
|
163
|
+
switch (type) {
|
|
164
|
+
case "move":
|
|
165
|
+
buttonCode = 32 | 3;
|
|
166
|
+
if (modifiers.shift)
|
|
167
|
+
buttonCode |= 4;
|
|
168
|
+
if (modifiers.alt)
|
|
169
|
+
buttonCode |= 8;
|
|
170
|
+
if (modifiers.ctrl)
|
|
171
|
+
buttonCode |= 16;
|
|
172
|
+
break;
|
|
173
|
+
case "drag":
|
|
174
|
+
buttonCode = (buttonsPressed.size > 0 ? Array.from(buttonsPressed)[0] : button) | 32;
|
|
175
|
+
if (modifiers.shift)
|
|
176
|
+
buttonCode |= 4;
|
|
177
|
+
if (modifiers.alt)
|
|
178
|
+
buttonCode |= 8;
|
|
179
|
+
if (modifiers.ctrl)
|
|
180
|
+
buttonCode |= 16;
|
|
181
|
+
break;
|
|
182
|
+
case "scroll":
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
const ansiX = x + 1;
|
|
186
|
+
const ansiY = y + 1;
|
|
187
|
+
let pressRelease = "M";
|
|
188
|
+
if (type === "up" || type === "move" || type === "drag") {
|
|
189
|
+
pressRelease = "m";
|
|
190
|
+
}
|
|
191
|
+
return `\x1B[<${buttonCode};${ansiX};${ansiY}${pressRelease}`;
|
|
192
|
+
};
|
|
193
|
+
const emitMouseEvent = async (type, x, y, button = MouseButtons.LEFT, options = {}) => {
|
|
194
|
+
const { modifiers = {}, delayMs = 0 } = options;
|
|
195
|
+
const eventSequence = generateMouseEvent(type, x, y, button, modifiers);
|
|
196
|
+
renderer.stdin.emit("data", Buffer.from(eventSequence));
|
|
197
|
+
currentPosition = { x, y };
|
|
198
|
+
if (type === "down" && button < 64) {
|
|
199
|
+
buttonsPressed.add(button);
|
|
200
|
+
} else if (type === "up") {
|
|
201
|
+
buttonsPressed.delete(button);
|
|
202
|
+
}
|
|
203
|
+
if (delayMs > 0) {
|
|
204
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
const moveTo = async (x, y, options = {}) => {
|
|
208
|
+
const { button = MouseButtons.LEFT, delayMs = 0, modifiers = {} } = options;
|
|
209
|
+
if (buttonsPressed.size > 0) {
|
|
210
|
+
await emitMouseEvent("drag", x, y, Array.from(buttonsPressed)[0], { modifiers, delayMs });
|
|
211
|
+
} else {
|
|
212
|
+
await emitMouseEvent("move", x, y, button, { modifiers, delayMs });
|
|
213
|
+
}
|
|
214
|
+
currentPosition = { x, y };
|
|
215
|
+
};
|
|
216
|
+
const click = async (x, y, button = MouseButtons.LEFT, options = {}) => {
|
|
217
|
+
const { delayMs = 10, modifiers = {} } = options;
|
|
218
|
+
await emitMouseEvent("down", x, y, button, { modifiers, delayMs });
|
|
219
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
220
|
+
await emitMouseEvent("up", x, y, button, { modifiers, delayMs });
|
|
221
|
+
};
|
|
222
|
+
const doubleClick = async (x, y, button = MouseButtons.LEFT, options = {}) => {
|
|
223
|
+
const { delayMs = 10, modifiers = {} } = options;
|
|
224
|
+
await click(x, y, button, { modifiers, delayMs });
|
|
225
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
226
|
+
await click(x, y, button, { modifiers, delayMs });
|
|
227
|
+
};
|
|
228
|
+
const pressDown = async (x, y, button = MouseButtons.LEFT, options = {}) => {
|
|
229
|
+
const { modifiers = {}, delayMs = 0 } = options;
|
|
230
|
+
await emitMouseEvent("down", x, y, button, { modifiers, delayMs });
|
|
231
|
+
};
|
|
232
|
+
const release = async (x, y, button = MouseButtons.LEFT, options = {}) => {
|
|
233
|
+
const { modifiers = {}, delayMs = 0 } = options;
|
|
234
|
+
await emitMouseEvent("up", x, y, button, { modifiers, delayMs });
|
|
235
|
+
};
|
|
236
|
+
const drag = async (startX, startY, endX, endY, button = MouseButtons.LEFT, options = {}) => {
|
|
237
|
+
const { delayMs = 10, modifiers = {} } = options;
|
|
238
|
+
await pressDown(startX, startY, button, { modifiers });
|
|
239
|
+
const steps = 5;
|
|
240
|
+
const dx = (endX - startX) / steps;
|
|
241
|
+
const dy = (endY - startY) / steps;
|
|
242
|
+
for (let i = 1;i <= steps; i++) {
|
|
243
|
+
const currentX = Math.round(startX + dx * i);
|
|
244
|
+
const currentY = Math.round(startY + dy * i);
|
|
245
|
+
await emitMouseEvent("drag", currentX, currentY, button, { modifiers, delayMs });
|
|
246
|
+
}
|
|
247
|
+
await release(endX, endY, button, { modifiers });
|
|
248
|
+
};
|
|
249
|
+
const scroll = async (x, y, direction, options = {}) => {
|
|
250
|
+
const { modifiers = {}, delayMs = 0 } = options;
|
|
251
|
+
let button;
|
|
252
|
+
switch (direction) {
|
|
253
|
+
case "up":
|
|
254
|
+
button = MouseButtons.WHEEL_UP;
|
|
255
|
+
break;
|
|
256
|
+
case "down":
|
|
257
|
+
button = MouseButtons.WHEEL_DOWN;
|
|
258
|
+
break;
|
|
259
|
+
case "left":
|
|
260
|
+
button = MouseButtons.WHEEL_LEFT;
|
|
261
|
+
break;
|
|
262
|
+
case "right":
|
|
263
|
+
button = MouseButtons.WHEEL_RIGHT;
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
await emitMouseEvent("scroll", x, y, button, { modifiers, delayMs });
|
|
267
|
+
};
|
|
268
|
+
const getCurrentPosition = () => {
|
|
269
|
+
return { ...currentPosition };
|
|
270
|
+
};
|
|
271
|
+
const getPressedButtons = () => {
|
|
272
|
+
return Array.from(buttonsPressed);
|
|
273
|
+
};
|
|
274
|
+
return {
|
|
275
|
+
moveTo,
|
|
276
|
+
click,
|
|
277
|
+
doubleClick,
|
|
278
|
+
pressDown,
|
|
279
|
+
release,
|
|
280
|
+
drag,
|
|
281
|
+
scroll,
|
|
282
|
+
getCurrentPosition,
|
|
283
|
+
getPressedButtons,
|
|
284
|
+
emitMouseEvent
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// src/testing/test-renderer.ts
|
|
289
|
+
var decoder = new TextDecoder;
|
|
290
|
+
async function createTestRenderer(options) {
|
|
291
|
+
const renderer = await setupTestRenderer({
|
|
292
|
+
...options,
|
|
293
|
+
useAlternateScreen: false,
|
|
294
|
+
useConsole: false
|
|
295
|
+
});
|
|
296
|
+
renderer.disableStdoutInterception();
|
|
297
|
+
const mockInput = createMockKeys(renderer);
|
|
298
|
+
const mockMouse = createMockMouse(renderer);
|
|
299
|
+
return {
|
|
300
|
+
renderer,
|
|
301
|
+
mockInput,
|
|
302
|
+
mockMouse,
|
|
303
|
+
renderOnce: async () => {
|
|
304
|
+
await renderer.loop();
|
|
305
|
+
},
|
|
306
|
+
captureCharFrame: () => {
|
|
307
|
+
const currentBuffer = renderer.currentRenderBuffer;
|
|
308
|
+
const frameBytes = currentBuffer.getRealCharBytes(true);
|
|
309
|
+
return decoder.decode(frameBytes);
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
async function setupTestRenderer(config) {
|
|
314
|
+
const stdin = config.stdin || process.stdin;
|
|
315
|
+
const stdout = config.stdout || process.stdout;
|
|
316
|
+
const width = config.width || stdout.columns || 80;
|
|
317
|
+
const height = config.height || stdout.rows || 24;
|
|
318
|
+
const renderHeight = config.experimental_splitHeight && config.experimental_splitHeight > 0 ? config.experimental_splitHeight : height;
|
|
319
|
+
const ziglib = resolveRenderLib();
|
|
320
|
+
const rendererPtr = ziglib.createRenderer(width, renderHeight, { testing: true });
|
|
321
|
+
if (!rendererPtr) {
|
|
322
|
+
throw new Error("Failed to create test renderer");
|
|
323
|
+
}
|
|
324
|
+
if (config.useThread === undefined) {
|
|
325
|
+
config.useThread = true;
|
|
326
|
+
}
|
|
327
|
+
if (process.platform === "linux") {
|
|
328
|
+
config.useThread = false;
|
|
329
|
+
}
|
|
330
|
+
ziglib.setUseThread(rendererPtr, config.useThread);
|
|
331
|
+
const renderer = new CliRenderer(ziglib, rendererPtr, stdin, stdout, width, height, config);
|
|
332
|
+
return renderer;
|
|
333
|
+
}
|
|
334
|
+
export {
|
|
335
|
+
createTestRenderer,
|
|
336
|
+
createMockMouse,
|
|
337
|
+
createMockKeys,
|
|
338
|
+
MouseButtons,
|
|
339
|
+
KeyCodes
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
//# debugId=8F861C9D239D4E3664756E2164756E21
|
|
343
|
+
//# sourceMappingURL=testing.js.map
|
package/testing.js.map
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/testing/mock-keys.ts", "../src/testing/mock-mouse.ts", "../src/testing/test-renderer.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { CliRenderer } from \"../renderer\"\n\nexport const KeyCodes = {\n // Control keys\n ENTER: \"\\r\",\n TAB: \"\\t\",\n BACKSPACE: \"\\b\",\n // NOTE: This may depend on the platform and terminals\n DELETE: \"\\x1b[3~\",\n HOME: \"\\x1b[H\",\n END: \"\\x1b[F\",\n ESCAPE: \"\\x1b\",\n\n // Arrow keys\n ARROW_UP: \"\\x1b[A\",\n ARROW_DOWN: \"\\x1b[B\",\n ARROW_RIGHT: \"\\x1b[C\",\n ARROW_LEFT: \"\\x1b[D\",\n\n // Function keys\n F1: \"\\x1bOP\",\n F2: \"\\x1bOQ\",\n F3: \"\\x1bOR\",\n F4: \"\\x1bOS\",\n F5: \"\\x1b[15~\",\n F6: \"\\x1b[17~\",\n F7: \"\\x1b[18~\",\n F8: \"\\x1b[19~\",\n F9: \"\\x1b[20~\",\n F10: \"\\x1b[21~\",\n F11: \"\\x1b[23~\",\n F12: \"\\x1b[24~\",\n\n // Control combinations\n CTRL_A: \"\\x01\",\n CTRL_B: \"\\x02\",\n CTRL_C: \"\\x03\",\n CTRL_D: \"\\x04\",\n CTRL_E: \"\\x05\",\n CTRL_F: \"\\x06\",\n CTRL_G: \"\\x07\",\n CTRL_H: \"\\x08\",\n CTRL_I: \"\\t\",\n CTRL_J: \"\\n\",\n CTRL_K: \"\\x0b\",\n CTRL_L: \"\\x0c\",\n CTRL_M: \"\\r\",\n CTRL_N: \"\\x0e\",\n CTRL_O: \"\\x0f\",\n CTRL_P: \"\\x10\",\n CTRL_Q: \"\\x11\",\n CTRL_R: \"\\x12\",\n CTRL_S: \"\\x13\",\n CTRL_T: \"\\x14\",\n CTRL_U: \"\\x15\",\n CTRL_V: \"\\x16\",\n CTRL_W: \"\\x17\",\n CTRL_X: \"\\x18\",\n CTRL_Y: \"\\x19\",\n CTRL_Z: \"\\x1a\",\n\n // Alt combinations\n ALT_A: \"\\x1ba\",\n ALT_B: \"\\x1bb\",\n ALT_C: \"\\x1bc\",\n // ... add more as needed\n} as const\n\nexport type KeyInput = string | keyof typeof KeyCodes\n\nexport function createMockKeys(renderer: CliRenderer) {\n const pressKeys = async (keys: KeyInput[], delayMs: number = 0): Promise<void> => {\n for (const key of keys) {\n let keyCode: string\n if (typeof key === \"string\") {\n // If it's a string but also exists in KeyCodes, use the KeyCodes value\n if (key in KeyCodes) {\n keyCode = KeyCodes[key as keyof typeof KeyCodes]\n } else {\n keyCode = key\n }\n } else {\n // It's a KeyCode enum value\n keyCode = KeyCodes[key]\n if (!keyCode) {\n throw new Error(`Unknown key: ${key}`)\n }\n }\n\n renderer.stdin.emit(\"data\", Buffer.from(keyCode))\n\n if (delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, delayMs))\n }\n }\n }\n\n const pressKey = (key: KeyInput): void => {\n let keyCode: string\n if (typeof key === \"string\") {\n // If it's a string but also exists in KeyCodes, use the KeyCodes value\n if (key in KeyCodes) {\n keyCode = KeyCodes[key as keyof typeof KeyCodes]\n } else {\n keyCode = key\n }\n } else {\n // This branch handles KeyCode enum values (though they're strings at runtime)\n keyCode = KeyCodes[key]\n if (!keyCode) {\n throw new Error(`Unknown key: ${key}`)\n }\n }\n\n renderer.stdin.emit(\"data\", Buffer.from(keyCode))\n }\n\n const typeText = async (text: string, delayMs: number = 0): Promise<void> => {\n const keys = text.split(\"\")\n await pressKeys(keys, delayMs)\n }\n\n const pressEnter = (): void => {\n pressKey(KeyCodes.ENTER)\n }\n\n const pressEscape = (): void => {\n pressKey(KeyCodes.ESCAPE)\n }\n\n const pressTab = (): void => {\n pressKey(KeyCodes.TAB)\n }\n\n const pressBackspace = (): void => {\n pressKey(KeyCodes.BACKSPACE)\n }\n\n const pressArrow = (direction: \"up\" | \"down\" | \"left\" | \"right\"): void => {\n const keyMap = {\n up: KeyCodes.ARROW_UP,\n down: KeyCodes.ARROW_DOWN,\n left: KeyCodes.ARROW_LEFT,\n right: KeyCodes.ARROW_RIGHT,\n }\n pressKey(keyMap[direction])\n }\n\n const pressCtrlC = (): void => {\n pressKey(KeyCodes.CTRL_C)\n }\n\n return {\n pressKeys,\n pressKey,\n typeText,\n pressEnter,\n pressEscape,\n pressTab,\n pressBackspace,\n pressArrow,\n pressCtrlC,\n }\n}\n",
|
|
6
|
+
"import type { CliRenderer } from \"../renderer\"\n\nexport const MouseButtons = {\n LEFT: 0,\n MIDDLE: 1,\n RIGHT: 2,\n\n WHEEL_UP: 64, // 64 = scroll flag + 0\n WHEEL_DOWN: 65, // 64 + 1\n WHEEL_LEFT: 66, // 64 + 2\n WHEEL_RIGHT: 67, // 64 + 3\n} as const\n\nexport type MouseButton = (typeof MouseButtons)[keyof typeof MouseButtons]\n\nexport interface MousePosition {\n x: number\n y: number\n}\n\nexport interface MouseModifiers {\n shift?: boolean\n alt?: boolean\n ctrl?: boolean\n}\n\nexport type MouseEventType = \"down\" | \"up\" | \"move\" | \"drag\" | \"scroll\"\n\nexport interface MouseEventOptions {\n button?: MouseButton\n modifiers?: MouseModifiers\n delayMs?: number\n}\n\nexport function createMockMouse(renderer: CliRenderer) {\n let currentPosition: MousePosition = { x: 0, y: 0 }\n let buttonsPressed = new Set<MouseButton>()\n\n // Generate SGR mouse event sequence\n const generateMouseEvent = (\n type: MouseEventType,\n x: number,\n y: number,\n button: MouseButton = MouseButtons.LEFT,\n modifiers: MouseModifiers = {},\n ): string => {\n // SGR format: \\x1b[<b;x;yM or \\x1b[<b;x;ym\n // where b = button code + modifier flags + motion/scroll flags\n\n let buttonCode: number = button\n\n // Add modifier flags\n if (modifiers.shift) buttonCode |= 4\n if (modifiers.alt) buttonCode |= 8\n if (modifiers.ctrl) buttonCode |= 16\n\n switch (type) {\n case \"move\":\n buttonCode = 32 | 3 // motion flag (32) + button 3 for motion without button press\n if (modifiers.shift) buttonCode |= 4\n if (modifiers.alt) buttonCode |= 8\n if (modifiers.ctrl) buttonCode |= 16\n break\n case \"drag\":\n buttonCode = (buttonsPressed.size > 0 ? Array.from(buttonsPressed)[0] : button) | 32\n if (modifiers.shift) buttonCode |= 4\n if (modifiers.alt) buttonCode |= 8\n if (modifiers.ctrl) buttonCode |= 16\n break\n case \"scroll\":\n // Scroll events already have the scroll flag set in the button code\n break\n }\n\n // Convert to 1-based coordinates for ANSI\n const ansiX = x + 1\n const ansiY = y + 1\n\n let pressRelease = \"M\" // Default to press\n if (type === \"up\" || type === \"move\" || type === \"drag\") {\n pressRelease = \"m\"\n }\n\n return `\\x1b[<${buttonCode};${ansiX};${ansiY}${pressRelease}`\n }\n\n const emitMouseEvent = async (\n type: MouseEventType,\n x: number,\n y: number,\n button: MouseButton = MouseButtons.LEFT,\n options: Omit<MouseEventOptions, \"button\"> = {},\n ): Promise<void> => {\n const { modifiers = {}, delayMs = 0 } = options\n\n const eventSequence = generateMouseEvent(type, x, y, button, modifiers)\n renderer.stdin.emit(\"data\", Buffer.from(eventSequence))\n\n currentPosition = { x, y }\n\n if (type === \"down\" && button < 64) {\n buttonsPressed.add(button)\n } else if (type === \"up\") {\n buttonsPressed.delete(button)\n }\n\n if (delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, delayMs))\n }\n }\n\n const moveTo = async (x: number, y: number, options: MouseEventOptions = {}): Promise<void> => {\n const { button = MouseButtons.LEFT, delayMs = 0, modifiers = {} } = options\n\n if (buttonsPressed.size > 0) {\n await emitMouseEvent(\"drag\", x, y, Array.from(buttonsPressed)[0], { modifiers, delayMs })\n } else {\n await emitMouseEvent(\"move\", x, y, button, { modifiers, delayMs })\n }\n\n currentPosition = { x, y }\n }\n\n const click = async (\n x: number,\n y: number,\n button: MouseButton = MouseButtons.LEFT,\n options: MouseEventOptions = {},\n ): Promise<void> => {\n const { delayMs = 10, modifiers = {} } = options\n\n await emitMouseEvent(\"down\", x, y, button, { modifiers, delayMs })\n await new Promise((resolve) => setTimeout(resolve, delayMs))\n await emitMouseEvent(\"up\", x, y, button, { modifiers, delayMs })\n }\n\n const doubleClick = async (\n x: number,\n y: number,\n button: MouseButton = MouseButtons.LEFT,\n options: MouseEventOptions = {},\n ): Promise<void> => {\n const { delayMs = 10, modifiers = {} } = options\n\n await click(x, y, button, { modifiers, delayMs })\n await new Promise((resolve) => setTimeout(resolve, delayMs))\n await click(x, y, button, { modifiers, delayMs })\n }\n\n const pressDown = async (\n x: number,\n y: number,\n button: MouseButton = MouseButtons.LEFT,\n options: MouseEventOptions = {},\n ): Promise<void> => {\n const { modifiers = {}, delayMs = 0 } = options\n await emitMouseEvent(\"down\", x, y, button, { modifiers, delayMs })\n }\n\n const release = async (\n x: number,\n y: number,\n button: MouseButton = MouseButtons.LEFT,\n options: MouseEventOptions = {},\n ): Promise<void> => {\n const { modifiers = {}, delayMs = 0 } = options\n await emitMouseEvent(\"up\", x, y, button, { modifiers, delayMs })\n }\n\n const drag = async (\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n button: MouseButton = MouseButtons.LEFT,\n options: MouseEventOptions = {},\n ): Promise<void> => {\n const { delayMs = 10, modifiers = {} } = options\n\n await pressDown(startX, startY, button, { modifiers })\n\n const steps = 5\n const dx = (endX - startX) / steps\n const dy = (endY - startY) / steps\n\n for (let i = 1; i <= steps; i++) {\n const currentX = Math.round(startX + dx * i)\n const currentY = Math.round(startY + dy * i)\n await emitMouseEvent(\"drag\", currentX, currentY, button, { modifiers, delayMs })\n }\n\n await release(endX, endY, button, { modifiers })\n }\n\n const scroll = async (\n x: number,\n y: number,\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n options: MouseEventOptions = {},\n ): Promise<void> => {\n const { modifiers = {}, delayMs = 0 } = options\n\n let button: MouseButton\n switch (direction) {\n case \"up\":\n button = MouseButtons.WHEEL_UP\n break\n case \"down\":\n button = MouseButtons.WHEEL_DOWN\n break\n case \"left\":\n button = MouseButtons.WHEEL_LEFT\n break\n case \"right\":\n button = MouseButtons.WHEEL_RIGHT\n break\n }\n\n await emitMouseEvent(\"scroll\", x, y, button, { modifiers, delayMs })\n }\n\n const getCurrentPosition = (): MousePosition => {\n return { ...currentPosition }\n }\n\n const getPressedButtons = (): MouseButton[] => {\n return Array.from(buttonsPressed)\n }\n\n return {\n // Core interaction methods\n moveTo,\n click,\n doubleClick,\n pressDown,\n release,\n drag,\n scroll,\n\n // State getters\n getCurrentPosition,\n getPressedButtons,\n\n // Low-level event emission (for advanced use cases)\n emitMouseEvent,\n }\n}\n",
|
|
7
|
+
"import { CliRenderer, type CliRendererConfig } from \"../renderer\"\nimport { resolveRenderLib } from \"../zig\"\nimport { createMockKeys } from \"./mock-keys\"\nimport { createMockMouse } from \"./mock-mouse\"\n\nexport interface TestRendererOptions extends CliRendererConfig {\n width?: number\n height?: number\n}\nexport interface TestRenderer extends CliRenderer {}\nexport type MockInput = ReturnType<typeof createMockKeys>\nexport type MockMouse = ReturnType<typeof createMockMouse>\n\nconst decoder = new TextDecoder()\n\nexport async function createTestRenderer(options: TestRendererOptions): Promise<{\n renderer: TestRenderer\n mockInput: MockInput\n mockMouse: MockMouse\n renderOnce: () => Promise<void>\n captureCharFrame: () => string\n}> {\n const renderer = await setupTestRenderer({\n ...options,\n useAlternateScreen: false,\n useConsole: false,\n })\n\n renderer.disableStdoutInterception()\n\n const mockInput = createMockKeys(renderer)\n const mockMouse = createMockMouse(renderer)\n return {\n renderer,\n mockInput,\n mockMouse,\n renderOnce: async () => {\n //@ts-expect-error - this is a test renderer\n await renderer.loop()\n },\n captureCharFrame: () => {\n const currentBuffer = renderer.currentRenderBuffer\n const frameBytes = currentBuffer.getRealCharBytes(true)\n return decoder.decode(frameBytes)\n },\n }\n}\n\nasync function setupTestRenderer(config: TestRendererOptions) {\n const stdin = config.stdin || process.stdin\n const stdout = config.stdout || process.stdout\n\n const width = config.width || stdout.columns || 80\n const height = config.height || stdout.rows || 24\n const renderHeight =\n config.experimental_splitHeight && config.experimental_splitHeight > 0 ? config.experimental_splitHeight : height\n\n const ziglib = resolveRenderLib()\n const rendererPtr = ziglib.createRenderer(width, renderHeight, { testing: true })\n if (!rendererPtr) {\n throw new Error(\"Failed to create test renderer\")\n }\n if (config.useThread === undefined) {\n config.useThread = true\n }\n\n if (process.platform === \"linux\") {\n config.useThread = false\n }\n ziglib.setUseThread(rendererPtr, config.useThread)\n\n const renderer = new CliRenderer(ziglib, rendererPtr, stdin, stdout, width, height, config)\n\n // Do not setup the terminal for testing as we will not actualy output anything to the terminal\n // await renderer.setupTerminal()\n\n return renderer\n}\n"
|
|
8
|
+
],
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "8F861C9D239D4E3664756E2164756E21",
|
|
11
|
+
"names": []
|
|
12
|
+
}
|
package/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { RGBA } from "./lib/RGBA";
|
|
|
2
2
|
import type { EventEmitter } from "events";
|
|
3
3
|
import type { Selection } from "./lib/selection";
|
|
4
4
|
import type { Renderable } from "./Renderable";
|
|
5
|
+
import type { KeyHandler } from "./lib";
|
|
5
6
|
export declare const TextAttributes: {
|
|
6
7
|
NONE: number;
|
|
7
8
|
BOLD: number;
|
|
@@ -52,6 +53,7 @@ export interface RenderContext extends EventEmitter {
|
|
|
52
53
|
registerLifecyclePass: (renderable: Renderable) => void;
|
|
53
54
|
unregisterLifecyclePass: (renderable: Renderable) => void;
|
|
54
55
|
getLifecyclePasses: () => Set<Renderable>;
|
|
56
|
+
keyInput: KeyHandler;
|
|
55
57
|
}
|
|
56
58
|
export type Timeout = ReturnType<typeof setTimeout> | undefined;
|
|
57
59
|
export interface ViewportBounds {
|
package/zig.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface RenderLib {
|
|
|
13
13
|
createRenderer: (width: number, height: number, options?: {
|
|
14
14
|
testing: boolean;
|
|
15
15
|
}) => Pointer | null;
|
|
16
|
-
destroyRenderer: (renderer: Pointer
|
|
16
|
+
destroyRenderer: (renderer: Pointer) => void;
|
|
17
17
|
setUseThread: (renderer: Pointer, useThread: boolean) => void;
|
|
18
18
|
setBackgroundColor: (renderer: Pointer, color: RGBA) => void;
|
|
19
19
|
setRenderOffset: (renderer: Pointer, offset: number) => void;
|
|
@@ -35,6 +35,8 @@ export interface RenderLib {
|
|
|
35
35
|
bufferGetRespectAlpha: (buffer: Pointer) => boolean;
|
|
36
36
|
bufferSetRespectAlpha: (buffer: Pointer, respectAlpha: boolean) => void;
|
|
37
37
|
bufferGetId: (buffer: Pointer) => string;
|
|
38
|
+
bufferGetRealCharSize: (buffer: Pointer) => number;
|
|
39
|
+
bufferWriteResolvedChars: (buffer: Pointer, outputBuffer: Uint8Array, addLineBreaks: boolean) => number;
|
|
38
40
|
bufferDrawText: (buffer: Pointer, text: string, x: number, y: number, color: RGBA, bgColor?: RGBA, attributes?: number) => void;
|
|
39
41
|
bufferSetCellWithAlphaBlending: (buffer: Pointer, x: number, y: number, char: string, color: RGBA, bgColor: RGBA, attributes?: number) => void;
|
|
40
42
|
bufferSetCell: (buffer: Pointer, x: number, y: number, char: string, color: RGBA, bgColor: RGBA, attributes?: number) => void;
|