@next_term/native 0.1.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/NativeTerminal.d.ts +41 -0
- package/dist/NativeTerminal.d.ts.map +1 -0
- package/dist/NativeTerminal.js +205 -0
- package/dist/NativeTerminal.js.map +1 -0
- package/dist/TerminalSurface.d.ts.map +1 -0
- package/dist/TerminalSurface.js +36 -0
- package/dist/TerminalSurface.js.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/input/GestureHandler.d.ts +10 -0
- package/dist/input/GestureHandler.d.ts.map +1 -0
- package/dist/input/GestureHandler.js +9 -0
- package/dist/input/GestureHandler.js.map +1 -0
- package/dist/input/KeyboardHandler.d.ts +40 -0
- package/dist/input/KeyboardHandler.d.ts.map +1 -0
- package/dist/input/KeyboardHandler.js +146 -0
- package/dist/input/KeyboardHandler.js.map +1 -0
- package/dist/renderer/NativeRenderer.d.ts +48 -0
- package/dist/renderer/NativeRenderer.d.ts.map +1 -0
- package/dist/renderer/NativeRenderer.js +14 -0
- package/dist/renderer/NativeRenderer.js.map +1 -0
- package/dist/renderer/SkiaRenderer.d.ts +57 -0
- package/dist/renderer/SkiaRenderer.d.ts.map +1 -0
- package/dist/renderer/SkiaRenderer.js +288 -0
- package/dist/renderer/SkiaRenderer.js.map +1 -0
- package/dist/turbo-module/NativeTerminalCore.d.ts +57 -0
- package/dist/turbo-module/NativeTerminalCore.d.ts.map +1 -0
- package/dist/turbo-module/NativeTerminalCore.js +14 -0
- package/dist/turbo-module/NativeTerminalCore.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NativeTerminal — React Native terminal component.
|
|
3
|
+
*
|
|
4
|
+
* Uses @next_term/core's BufferSet + VTParser for terminal emulation, and
|
|
5
|
+
* the SkiaRenderer to generate declarative render commands. Touch input is
|
|
6
|
+
* handled by GestureHandler; keyboard input by KeyboardHandler via a hidden
|
|
7
|
+
* TextInput equivalent.
|
|
8
|
+
*
|
|
9
|
+
* Architecture:
|
|
10
|
+
* - Core VT parsing runs in JS (same as web, could be moved to a JSI thread)
|
|
11
|
+
* - SkiaRenderer produces RenderCommand[] for a Skia Canvas
|
|
12
|
+
* - GestureHandler translates touch events to terminal actions
|
|
13
|
+
* - KeyboardHandler translates key events to VT sequences
|
|
14
|
+
*/
|
|
15
|
+
import type { Theme } from "@next_term/core";
|
|
16
|
+
import React from "react";
|
|
17
|
+
import type { RenderCommand } from "./renderer/SkiaRenderer.js";
|
|
18
|
+
export interface NativeTerminalProps {
|
|
19
|
+
cols?: number;
|
|
20
|
+
rows?: number;
|
|
21
|
+
fontSize?: number;
|
|
22
|
+
fontFamily?: string;
|
|
23
|
+
theme?: Partial<Theme>;
|
|
24
|
+
scrollback?: number;
|
|
25
|
+
onData?: (data: Uint8Array) => void;
|
|
26
|
+
onResize?: (size: {
|
|
27
|
+
cols: number;
|
|
28
|
+
rows: number;
|
|
29
|
+
}) => void;
|
|
30
|
+
/** Called each frame with render commands for the Skia Canvas. */
|
|
31
|
+
onRenderCommands?: (commands: RenderCommand[]) => void;
|
|
32
|
+
style?: Record<string, unknown>;
|
|
33
|
+
}
|
|
34
|
+
export interface NativeTerminalHandle {
|
|
35
|
+
write(data: string | Uint8Array): void;
|
|
36
|
+
resize(cols: number, rows: number): void;
|
|
37
|
+
focus(): void;
|
|
38
|
+
blur(): void;
|
|
39
|
+
}
|
|
40
|
+
export declare const NativeTerminal: React.ForwardRefExoticComponent<NativeTerminalProps & React.RefAttributes<NativeTerminalHandle>>;
|
|
41
|
+
//# sourceMappingURL=NativeTerminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeTerminal.d.ts","sourceRoot":"","sources":["../src/NativeTerminal.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAkB,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,KAON,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAOhE,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC1D,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;IACvC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;CACd;AAqBD,eAAO,MAAM,cAAc,kGAoN1B,CAAC"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NativeTerminal — React Native terminal component.
|
|
3
|
+
*
|
|
4
|
+
* Uses @next_term/core's BufferSet + VTParser for terminal emulation, and
|
|
5
|
+
* the SkiaRenderer to generate declarative render commands. Touch input is
|
|
6
|
+
* handled by GestureHandler; keyboard input by KeyboardHandler via a hidden
|
|
7
|
+
* TextInput equivalent.
|
|
8
|
+
*
|
|
9
|
+
* Architecture:
|
|
10
|
+
* - Core VT parsing runs in JS (same as web, could be moved to a JSI thread)
|
|
11
|
+
* - SkiaRenderer produces RenderCommand[] for a Skia Canvas
|
|
12
|
+
* - GestureHandler translates touch events to terminal actions
|
|
13
|
+
* - KeyboardHandler translates key events to VT sequences
|
|
14
|
+
*/
|
|
15
|
+
import { BufferSet, DEFAULT_THEME, VTParser } from "@next_term/core";
|
|
16
|
+
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState, } from "react";
|
|
17
|
+
import { GestureHandler } from "./input/GestureHandler.js";
|
|
18
|
+
import { KeyboardHandler } from "./input/KeyboardHandler.js";
|
|
19
|
+
import { SkiaRenderer } from "./renderer/SkiaRenderer.js";
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Defaults
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
const DEFAULT_COLS = 80;
|
|
24
|
+
const DEFAULT_ROWS = 24;
|
|
25
|
+
const DEFAULT_FONT_SIZE = 14;
|
|
26
|
+
const DEFAULT_FONT_FAMILY = "Menlo";
|
|
27
|
+
const DEFAULT_SCROLLBACK = 1000;
|
|
28
|
+
function mergeTheme(partial) {
|
|
29
|
+
if (!partial)
|
|
30
|
+
return { ...DEFAULT_THEME };
|
|
31
|
+
return { ...DEFAULT_THEME, ...partial };
|
|
32
|
+
}
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Component
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
export const NativeTerminal = forwardRef(function NativeTerminal(props, ref) {
|
|
37
|
+
const { cols = DEFAULT_COLS, rows = DEFAULT_ROWS, fontSize = DEFAULT_FONT_SIZE, fontFamily = DEFAULT_FONT_FAMILY, theme: themeProp, scrollback = DEFAULT_SCROLLBACK, onData, onResize, onRenderCommands, style, } = props;
|
|
38
|
+
// Stable refs for callbacks
|
|
39
|
+
const onDataRef = useRef(onData);
|
|
40
|
+
const onResizeRef = useRef(onResize);
|
|
41
|
+
const onRenderCommandsRef = useRef(onRenderCommands);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
onDataRef.current = onData;
|
|
44
|
+
}, [onData]);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
onResizeRef.current = onResize;
|
|
47
|
+
}, [onResize]);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
onRenderCommandsRef.current = onRenderCommands;
|
|
50
|
+
}, [onRenderCommands]);
|
|
51
|
+
// Core state
|
|
52
|
+
const bufferSetRef = useRef(null);
|
|
53
|
+
const parserRef = useRef(null);
|
|
54
|
+
const rendererRef = useRef(null);
|
|
55
|
+
const gestureHandlerRef = useRef(null);
|
|
56
|
+
const keyboardHandlerRef = useRef(null);
|
|
57
|
+
const [_focused, setFocused] = useState(false);
|
|
58
|
+
const [selection, setSelection] = useState(null);
|
|
59
|
+
const encoder = useRef(new TextEncoder());
|
|
60
|
+
const theme = mergeTheme(themeProp);
|
|
61
|
+
const initialized = useRef(false);
|
|
62
|
+
const rafRef = useRef(null);
|
|
63
|
+
// -----------------------------------------------------------------------
|
|
64
|
+
// Initialization
|
|
65
|
+
// -----------------------------------------------------------------------
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (initialized.current)
|
|
68
|
+
return;
|
|
69
|
+
initialized.current = true;
|
|
70
|
+
// Create core terminal
|
|
71
|
+
const bufferSet = new BufferSet(cols, rows, scrollback);
|
|
72
|
+
const parser = new VTParser(bufferSet);
|
|
73
|
+
bufferSetRef.current = bufferSet;
|
|
74
|
+
parserRef.current = parser;
|
|
75
|
+
// Create renderer
|
|
76
|
+
const renderer = new SkiaRenderer({
|
|
77
|
+
fontSize,
|
|
78
|
+
fontFamily,
|
|
79
|
+
theme,
|
|
80
|
+
});
|
|
81
|
+
rendererRef.current = renderer;
|
|
82
|
+
const { width: cellWidth, height: cellHeight } = renderer.getCellSize();
|
|
83
|
+
// Create keyboard handler
|
|
84
|
+
const keyboard = new KeyboardHandler((data) => {
|
|
85
|
+
onDataRef.current?.(data);
|
|
86
|
+
});
|
|
87
|
+
keyboardHandlerRef.current = keyboard;
|
|
88
|
+
// Create gesture handler
|
|
89
|
+
const gesture = new GestureHandler(cellWidth, cellHeight, {
|
|
90
|
+
onScroll: (deltaRows) => {
|
|
91
|
+
// Scrollback navigation would go here
|
|
92
|
+
void deltaRows;
|
|
93
|
+
},
|
|
94
|
+
onTap: (_row, _col) => {
|
|
95
|
+
// Could place cursor or activate links
|
|
96
|
+
},
|
|
97
|
+
onDoubleTap: (_row, _col) => {
|
|
98
|
+
// Word selection
|
|
99
|
+
},
|
|
100
|
+
onLongPress: (_row, _col) => {
|
|
101
|
+
// Selection mode
|
|
102
|
+
},
|
|
103
|
+
onPinch: (_scale) => {
|
|
104
|
+
// Font size adjustment
|
|
105
|
+
},
|
|
106
|
+
onSelectionChange: (sel) => {
|
|
107
|
+
setSelection(sel);
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
gestureHandlerRef.current = gesture;
|
|
111
|
+
// Start render loop
|
|
112
|
+
const renderLoop = () => {
|
|
113
|
+
if (!bufferSetRef.current || !rendererRef.current)
|
|
114
|
+
return;
|
|
115
|
+
const grid = bufferSetRef.current.active.grid;
|
|
116
|
+
let hasDirty = false;
|
|
117
|
+
for (let r = 0; r < grid.rows; r++) {
|
|
118
|
+
if (grid.isDirty(r)) {
|
|
119
|
+
hasDirty = true;
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (hasDirty) {
|
|
124
|
+
const cursor = bufferSetRef.current.active.cursor;
|
|
125
|
+
const commands = rendererRef.current.renderFrame(grid, cursor, selection);
|
|
126
|
+
onRenderCommandsRef.current?.(commands);
|
|
127
|
+
// Clear dirty flags
|
|
128
|
+
for (let r = 0; r < grid.rows; r++) {
|
|
129
|
+
grid.clearDirty(r);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
rafRef.current = requestAnimationFrame(renderLoop);
|
|
133
|
+
};
|
|
134
|
+
rafRef.current = requestAnimationFrame(renderLoop);
|
|
135
|
+
return () => {
|
|
136
|
+
if (rafRef.current !== null) {
|
|
137
|
+
cancelAnimationFrame(rafRef.current);
|
|
138
|
+
rafRef.current = null;
|
|
139
|
+
}
|
|
140
|
+
bufferSetRef.current = null;
|
|
141
|
+
parserRef.current = null;
|
|
142
|
+
rendererRef.current = null;
|
|
143
|
+
gestureHandlerRef.current = null;
|
|
144
|
+
keyboardHandlerRef.current = null;
|
|
145
|
+
initialized.current = false;
|
|
146
|
+
};
|
|
147
|
+
}, [cols, fontFamily, fontSize, rows, scrollback, selection, theme]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
148
|
+
// Update theme
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
rendererRef.current?.setTheme(mergeTheme(themeProp));
|
|
151
|
+
}, [themeProp]);
|
|
152
|
+
// Update font
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
rendererRef.current?.setFont(fontSize, fontFamily);
|
|
155
|
+
if (gestureHandlerRef.current && rendererRef.current) {
|
|
156
|
+
const { width, height } = rendererRef.current.getCellSize();
|
|
157
|
+
gestureHandlerRef.current.updateCellSize(width, height);
|
|
158
|
+
}
|
|
159
|
+
}, [fontSize, fontFamily]);
|
|
160
|
+
// -----------------------------------------------------------------------
|
|
161
|
+
// Imperative handle
|
|
162
|
+
// -----------------------------------------------------------------------
|
|
163
|
+
const focus = useCallback(() => setFocused(true), []);
|
|
164
|
+
const blur = useCallback(() => setFocused(false), []);
|
|
165
|
+
useImperativeHandle(ref, () => ({
|
|
166
|
+
write(data) {
|
|
167
|
+
if (!parserRef.current)
|
|
168
|
+
return;
|
|
169
|
+
const bytes = typeof data === "string" ? encoder.current.encode(data) : data;
|
|
170
|
+
parserRef.current.write(bytes);
|
|
171
|
+
},
|
|
172
|
+
resize(newCols, newRows) {
|
|
173
|
+
if (!Number.isFinite(newCols) || !Number.isFinite(newRows) || newCols < 2 || newRows < 1)
|
|
174
|
+
return;
|
|
175
|
+
const bufferSet = new BufferSet(newCols, newRows, scrollback);
|
|
176
|
+
const parser = new VTParser(bufferSet);
|
|
177
|
+
bufferSetRef.current = bufferSet;
|
|
178
|
+
parserRef.current = parser;
|
|
179
|
+
onResizeRef.current?.({ cols: newCols, rows: newRows });
|
|
180
|
+
},
|
|
181
|
+
focus,
|
|
182
|
+
blur,
|
|
183
|
+
}), [scrollback, focus, blur]);
|
|
184
|
+
// -----------------------------------------------------------------------
|
|
185
|
+
// Render
|
|
186
|
+
// -----------------------------------------------------------------------
|
|
187
|
+
const cellSize = rendererRef.current?.getCellSize() ?? {
|
|
188
|
+
width: Math.ceil(fontSize * 0.6),
|
|
189
|
+
height: Math.ceil(fontSize * 1.2),
|
|
190
|
+
};
|
|
191
|
+
const surfaceWidth = cols * cellSize.width;
|
|
192
|
+
const surfaceHeight = rows * cellSize.height;
|
|
193
|
+
return React.createElement("RCTView", {
|
|
194
|
+
style: {
|
|
195
|
+
width: surfaceWidth,
|
|
196
|
+
height: surfaceHeight,
|
|
197
|
+
backgroundColor: theme.background,
|
|
198
|
+
overflow: "hidden",
|
|
199
|
+
...style,
|
|
200
|
+
},
|
|
201
|
+
accessibilityLabel: "Terminal",
|
|
202
|
+
accessibilityRole: "text",
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
//# sourceMappingURL=NativeTerminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeTerminal.js","sourceRoot":"","sources":["../src/NativeTerminal.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TerminalSurface.d.ts","sourceRoot":"","sources":["../src/TerminalSurface.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,MAAM,WAAW,oBAAoB;IACnC,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,mCAAmC;IACnC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAMD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAsB1D,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TerminalSurface — wraps the native platform view for terminal rendering.
|
|
3
|
+
*
|
|
4
|
+
* In a full implementation this would use requireNativeComponent() or a
|
|
5
|
+
* Fabric component to host a Metal / Vulkan surface. In the JS-fallback
|
|
6
|
+
* mode it renders a plain View that a Skia Canvas can draw into.
|
|
7
|
+
*
|
|
8
|
+
* This module is intentionally thin — the NativeTerminal component handles
|
|
9
|
+
* all logic and passes render commands through.
|
|
10
|
+
*/
|
|
11
|
+
import React from "react";
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Component
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
/**
|
|
16
|
+
* A placeholder surface component. In production this would be replaced by
|
|
17
|
+
* a native Fabric component that hosts the GPU rendering surface.
|
|
18
|
+
*
|
|
19
|
+
* For now it renders a React Native View-compatible element. Since we can't
|
|
20
|
+
* import `react-native` (it's a peer dep), the component returns a basic
|
|
21
|
+
* React element that RN's View would be swapped into by the consumer.
|
|
22
|
+
*/
|
|
23
|
+
export const TerminalSurface = ({ width, height, accessibilityLabel = "Terminal", style, children, }) => {
|
|
24
|
+
return React.createElement("RCTView", {
|
|
25
|
+
style: {
|
|
26
|
+
width,
|
|
27
|
+
height,
|
|
28
|
+
backgroundColor: "#1e1e1e",
|
|
29
|
+
overflow: "hidden",
|
|
30
|
+
...style,
|
|
31
|
+
},
|
|
32
|
+
accessibilityLabel,
|
|
33
|
+
accessibilityRole: "text",
|
|
34
|
+
}, children);
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=TerminalSurface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TerminalSurface.js","sourceRoot":"","sources":["../src/TerminalSurface.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAmB1B,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAmC,CAAC,EAC9D,KAAK,EACL,MAAM,EACN,kBAAkB,GAAG,UAAU,EAC/B,KAAK,EACL,QAAQ,GACT,EAAE,EAAE;IACH,OAAO,KAAK,CAAC,aAAa,CACxB,SAAS,EACT;QACE,KAAK,EAAE;YACL,KAAK;YACL,MAAM;YACN,eAAe,EAAE,SAAS;YAC1B,QAAQ,EAAE,QAAQ;YAClB,GAAG,KAAK;SACT;QACD,kBAAkB;QAClB,iBAAiB,EAAE,MAAM;KAC1B,EACD,QAAQ,CACT,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzE,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAC1F,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { GestureHandler, GestureState } from "./input/GestureHandler.js";
|
|
2
|
+
export { KeyboardHandler } from "./input/KeyboardHandler.js";
|
|
3
|
+
export { NativeTerminal } from "./NativeTerminal.js";
|
|
4
|
+
export { SkiaRenderer } from "./renderer/SkiaRenderer.js";
|
|
5
|
+
export { TerminalSurface } from "./TerminalSurface.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-export the shared GestureHandler from @next_term/core.
|
|
3
|
+
*
|
|
4
|
+
* The gesture handler is platform-agnostic and lives in core so it can
|
|
5
|
+
* be shared between web (DOM touch events) and native (React Native
|
|
6
|
+
* gesture handler).
|
|
7
|
+
*/
|
|
8
|
+
export type { GestureConfig } from "@next_term/core";
|
|
9
|
+
export { GestureHandler, GestureState } from "@next_term/core";
|
|
10
|
+
//# sourceMappingURL=GestureHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GestureHandler.d.ts","sourceRoot":"","sources":["../../src/input/GestureHandler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-export the shared GestureHandler from @next_term/core.
|
|
3
|
+
*
|
|
4
|
+
* The gesture handler is platform-agnostic and lives in core so it can
|
|
5
|
+
* be shared between web (DOM touch events) and native (React Native
|
|
6
|
+
* gesture handler).
|
|
7
|
+
*/
|
|
8
|
+
export { GestureHandler, GestureState } from "@next_term/core";
|
|
9
|
+
//# sourceMappingURL=GestureHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GestureHandler.js","sourceRoot":"","sources":["../../src/input/GestureHandler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyboard input handling for the React Native terminal.
|
|
3
|
+
*
|
|
4
|
+
* Translates key presses and IME text input into VT escape sequences,
|
|
5
|
+
* matching the logic in `@next_term/web`'s InputHandler.
|
|
6
|
+
*
|
|
7
|
+
* This is pure logic with no React Native dependencies — the RN component
|
|
8
|
+
* feeds events from a hidden TextInput into this handler.
|
|
9
|
+
*/
|
|
10
|
+
export interface KeyModifiers {
|
|
11
|
+
ctrl: boolean;
|
|
12
|
+
alt: boolean;
|
|
13
|
+
shift: boolean;
|
|
14
|
+
meta: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare class KeyboardHandler {
|
|
17
|
+
private onData;
|
|
18
|
+
private applicationCursorKeys;
|
|
19
|
+
constructor(onData: (data: Uint8Array) => void);
|
|
20
|
+
/**
|
|
21
|
+
* Process a key event from React Native's TextInput onKeyPress.
|
|
22
|
+
* The `key` string follows the same naming as DOM KeyboardEvent.key
|
|
23
|
+
* (e.g. "Enter", "Backspace", "ArrowUp", "a", "A").
|
|
24
|
+
*/
|
|
25
|
+
handleKeyPress(key: string, modifiers: KeyModifiers): void;
|
|
26
|
+
/**
|
|
27
|
+
* Process IME composition / text input. This handles multi-character
|
|
28
|
+
* input (e.g. CJK input methods, emoji, paste via TextInput).
|
|
29
|
+
*/
|
|
30
|
+
handleTextInput(text: string): void;
|
|
31
|
+
setApplicationCursorKeys(enabled: boolean): void;
|
|
32
|
+
/**
|
|
33
|
+
* Convert a key name + modifiers into the VT sequence string to send
|
|
34
|
+
* to the PTY, or null if the key should not be handled.
|
|
35
|
+
*
|
|
36
|
+
* This mirrors `@next_term/web` InputHandler.keyToSequence exactly.
|
|
37
|
+
*/
|
|
38
|
+
keyToSequence(key: string, modifiers: KeyModifiers): string | null;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=KeyboardHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KeyboardHandler.d.ts","sourceRoot":"","sources":["../../src/input/KeyboardHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAgBD,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,qBAAqB,CAAU;gBAE3B,MAAM,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI;IAS9C;;;;OAIG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,IAAI;IAO1D;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMnC,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAQhD;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI;CA6FnE"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyboard input handling for the React Native terminal.
|
|
3
|
+
*
|
|
4
|
+
* Translates key presses and IME text input into VT escape sequences,
|
|
5
|
+
* matching the logic in `@next_term/web`'s InputHandler.
|
|
6
|
+
*
|
|
7
|
+
* This is pure logic with no React Native dependencies — the RN component
|
|
8
|
+
* feeds events from a hidden TextInput into this handler.
|
|
9
|
+
*/
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Helpers
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
const encoder = new TextEncoder();
|
|
14
|
+
function toBytes(s) {
|
|
15
|
+
return encoder.encode(s);
|
|
16
|
+
}
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// KeyboardHandler
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
export class KeyboardHandler {
|
|
21
|
+
onData;
|
|
22
|
+
applicationCursorKeys;
|
|
23
|
+
constructor(onData) {
|
|
24
|
+
this.onData = onData;
|
|
25
|
+
this.applicationCursorKeys = false;
|
|
26
|
+
}
|
|
27
|
+
// -----------------------------------------------------------------------
|
|
28
|
+
// Public API
|
|
29
|
+
// -----------------------------------------------------------------------
|
|
30
|
+
/**
|
|
31
|
+
* Process a key event from React Native's TextInput onKeyPress.
|
|
32
|
+
* The `key` string follows the same naming as DOM KeyboardEvent.key
|
|
33
|
+
* (e.g. "Enter", "Backspace", "ArrowUp", "a", "A").
|
|
34
|
+
*/
|
|
35
|
+
handleKeyPress(key, modifiers) {
|
|
36
|
+
const seq = this.keyToSequence(key, modifiers);
|
|
37
|
+
if (seq !== null) {
|
|
38
|
+
this.onData(toBytes(seq));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Process IME composition / text input. This handles multi-character
|
|
43
|
+
* input (e.g. CJK input methods, emoji, paste via TextInput).
|
|
44
|
+
*/
|
|
45
|
+
handleTextInput(text) {
|
|
46
|
+
if (text.length > 0) {
|
|
47
|
+
this.onData(encoder.encode(text));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
setApplicationCursorKeys(enabled) {
|
|
51
|
+
this.applicationCursorKeys = enabled;
|
|
52
|
+
}
|
|
53
|
+
// -----------------------------------------------------------------------
|
|
54
|
+
// VT sequence generation
|
|
55
|
+
// -----------------------------------------------------------------------
|
|
56
|
+
/**
|
|
57
|
+
* Convert a key name + modifiers into the VT sequence string to send
|
|
58
|
+
* to the PTY, or null if the key should not be handled.
|
|
59
|
+
*
|
|
60
|
+
* This mirrors `@next_term/web` InputHandler.keyToSequence exactly.
|
|
61
|
+
*/
|
|
62
|
+
keyToSequence(key, modifiers) {
|
|
63
|
+
const { ctrl, alt, meta } = modifiers;
|
|
64
|
+
// Meta key combos are OS-level shortcuts — let them through
|
|
65
|
+
if (meta)
|
|
66
|
+
return null;
|
|
67
|
+
// Ctrl + single letter -> control character
|
|
68
|
+
if (ctrl && !alt && key.length === 1) {
|
|
69
|
+
const code = key.toUpperCase().charCodeAt(0);
|
|
70
|
+
if (code >= 0x40 && code <= 0x5f) {
|
|
71
|
+
return String.fromCharCode(code - 0x40);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Alt + key -> ESC prefix
|
|
75
|
+
if (alt && !ctrl && key.length === 1) {
|
|
76
|
+
return `\x1b${key}`;
|
|
77
|
+
}
|
|
78
|
+
// Special keys
|
|
79
|
+
const appMode = this.applicationCursorKeys;
|
|
80
|
+
switch (key) {
|
|
81
|
+
case "Enter":
|
|
82
|
+
return "\r";
|
|
83
|
+
case "Backspace":
|
|
84
|
+
return ctrl ? "\x08" : "\x7f";
|
|
85
|
+
case "Tab":
|
|
86
|
+
return "\t";
|
|
87
|
+
case "Escape":
|
|
88
|
+
return "\x1b";
|
|
89
|
+
case "Delete":
|
|
90
|
+
return "\x1b[3~";
|
|
91
|
+
case "ArrowUp":
|
|
92
|
+
return appMode ? "\x1bOA" : "\x1b[A";
|
|
93
|
+
case "ArrowDown":
|
|
94
|
+
return appMode ? "\x1bOB" : "\x1b[B";
|
|
95
|
+
case "ArrowRight":
|
|
96
|
+
return appMode ? "\x1bOC" : "\x1b[C";
|
|
97
|
+
case "ArrowLeft":
|
|
98
|
+
return appMode ? "\x1bOD" : "\x1b[D";
|
|
99
|
+
case "Home":
|
|
100
|
+
return "\x1b[H";
|
|
101
|
+
case "End":
|
|
102
|
+
return "\x1b[F";
|
|
103
|
+
case "PageUp":
|
|
104
|
+
return "\x1b[5~";
|
|
105
|
+
case "PageDown":
|
|
106
|
+
return "\x1b[6~";
|
|
107
|
+
case "Insert":
|
|
108
|
+
return "\x1b[2~";
|
|
109
|
+
// Function keys
|
|
110
|
+
case "F1":
|
|
111
|
+
return "\x1bOP";
|
|
112
|
+
case "F2":
|
|
113
|
+
return "\x1bOQ";
|
|
114
|
+
case "F3":
|
|
115
|
+
return "\x1bOR";
|
|
116
|
+
case "F4":
|
|
117
|
+
return "\x1bOS";
|
|
118
|
+
case "F5":
|
|
119
|
+
return "\x1b[15~";
|
|
120
|
+
case "F6":
|
|
121
|
+
return "\x1b[17~";
|
|
122
|
+
case "F7":
|
|
123
|
+
return "\x1b[18~";
|
|
124
|
+
case "F8":
|
|
125
|
+
return "\x1b[19~";
|
|
126
|
+
case "F9":
|
|
127
|
+
return "\x1b[20~";
|
|
128
|
+
case "F10":
|
|
129
|
+
return "\x1b[21~";
|
|
130
|
+
case "F11":
|
|
131
|
+
return "\x1b[23~";
|
|
132
|
+
case "F12":
|
|
133
|
+
return "\x1b[24~";
|
|
134
|
+
}
|
|
135
|
+
// Modifier-only keys
|
|
136
|
+
if (key === "Shift" || key === "Control" || key === "Alt" || key === "Meta") {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
// Printable character
|
|
140
|
+
if (key.length === 1) {
|
|
141
|
+
return key;
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=KeyboardHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KeyboardHandler.js","sourceRoot":"","sources":["../../src/input/KeyboardHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for the native Metal / Vulkan renderer.
|
|
3
|
+
*
|
|
4
|
+
* This defines the contract that a platform-specific native renderer would
|
|
5
|
+
* implement via JSI. The native renderer reads directly from the SharedArrayBuffer
|
|
6
|
+
* cell grid for zero-copy rendering.
|
|
7
|
+
*
|
|
8
|
+
* On iOS: Metal-backed CAMetalLayer
|
|
9
|
+
* On Android: Vulkan or OpenGL ES surface
|
|
10
|
+
*
|
|
11
|
+
* Until the native renderer is built, the SkiaRenderer (JS fallback) is used.
|
|
12
|
+
*/
|
|
13
|
+
import type { SelectionRange, Theme } from "@next_term/core";
|
|
14
|
+
export interface NativeRendererConfig {
|
|
15
|
+
/** Font size in device-independent points. */
|
|
16
|
+
fontSize: number;
|
|
17
|
+
/** Monospace font family name. */
|
|
18
|
+
fontFamily: string;
|
|
19
|
+
/** Terminal color theme. */
|
|
20
|
+
theme: Theme;
|
|
21
|
+
/** Device pixel ratio for high-DPI rendering. */
|
|
22
|
+
devicePixelRatio: number;
|
|
23
|
+
}
|
|
24
|
+
export interface INativeRenderer {
|
|
25
|
+
/**
|
|
26
|
+
* Initialize the native renderer with a SharedArrayBuffer-backed grid.
|
|
27
|
+
* The buffer layout matches @next_term/core's CellGrid packing.
|
|
28
|
+
*/
|
|
29
|
+
attach(buffer: SharedArrayBuffer, cols: number, rows: number): void;
|
|
30
|
+
/** Trigger a frame render. The native side reads dirty rows from the SAB. */
|
|
31
|
+
render(): void;
|
|
32
|
+
/** Update grid dimensions (re-allocates internal structures). */
|
|
33
|
+
resize(cols: number, rows: number, buffer: SharedArrayBuffer): void;
|
|
34
|
+
/** Update the color theme. */
|
|
35
|
+
setTheme(theme: Theme): void;
|
|
36
|
+
/** Update font settings. */
|
|
37
|
+
setFont(fontSize: number, fontFamily: string): void;
|
|
38
|
+
/** Update selection overlay. */
|
|
39
|
+
setSelection(selection: SelectionRange | null): void;
|
|
40
|
+
/** Get measured cell dimensions from the native text engine. */
|
|
41
|
+
getCellSize(): {
|
|
42
|
+
width: number;
|
|
43
|
+
height: number;
|
|
44
|
+
};
|
|
45
|
+
/** Release native resources. */
|
|
46
|
+
dispose(): void;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=NativeRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeRenderer.d.ts","sourceRoot":"","sources":["../../src/renderer/NativeRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,KAAK,EAAE,KAAK,CAAC;IACb,iDAAiD;IACjD,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpE,6EAA6E;IAC7E,MAAM,IAAI,IAAI,CAAC;IAEf,iEAAiE;IACjE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAEpE,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAE7B,4BAA4B;IAC5B,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpD,gCAAgC;IAChC,YAAY,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,GAAG,IAAI,CAAC;IAErD,gEAAgE;IAChE,WAAW,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAEjD,gCAAgC;IAChC,OAAO,IAAI,IAAI,CAAC;CACjB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for the native Metal / Vulkan renderer.
|
|
3
|
+
*
|
|
4
|
+
* This defines the contract that a platform-specific native renderer would
|
|
5
|
+
* implement via JSI. The native renderer reads directly from the SharedArrayBuffer
|
|
6
|
+
* cell grid for zero-copy rendering.
|
|
7
|
+
*
|
|
8
|
+
* On iOS: Metal-backed CAMetalLayer
|
|
9
|
+
* On Android: Vulkan or OpenGL ES surface
|
|
10
|
+
*
|
|
11
|
+
* Until the native renderer is built, the SkiaRenderer (JS fallback) is used.
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=NativeRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeRenderer.js","sourceRoot":"","sources":["../../src/renderer/NativeRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skia-based renderer for React Native (JS fallback).
|
|
3
|
+
*
|
|
4
|
+
* Instead of directly rendering pixels, this class generates a declarative
|
|
5
|
+
* list of `RenderCommand` objects that a @shopify/react-native-skia Canvas
|
|
6
|
+
* component can consume. This keeps all rendering logic testable without
|
|
7
|
+
* native dependencies.
|
|
8
|
+
*
|
|
9
|
+
* The command list is designed to be consumed in a single pass by a Skia
|
|
10
|
+
* Canvas `onDraw` callback or by mapping commands to Skia React components.
|
|
11
|
+
*/
|
|
12
|
+
import type { CursorState, SelectionRange, Theme } from "@next_term/core";
|
|
13
|
+
import { type CellGrid } from "@next_term/core";
|
|
14
|
+
export interface RenderCommand {
|
|
15
|
+
type: "rect" | "text" | "line";
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
width?: number;
|
|
19
|
+
height?: number;
|
|
20
|
+
color: string;
|
|
21
|
+
text?: string;
|
|
22
|
+
fontSize?: number;
|
|
23
|
+
fontFamily?: string;
|
|
24
|
+
bold?: boolean;
|
|
25
|
+
italic?: boolean;
|
|
26
|
+
/** Opacity override (0-1). Used for selection overlay and cursor. */
|
|
27
|
+
opacity?: number;
|
|
28
|
+
}
|
|
29
|
+
export declare class SkiaRenderer {
|
|
30
|
+
private cellWidth;
|
|
31
|
+
private cellHeight;
|
|
32
|
+
private fontSize;
|
|
33
|
+
private fontFamily;
|
|
34
|
+
private theme;
|
|
35
|
+
private palette;
|
|
36
|
+
constructor(options: {
|
|
37
|
+
fontSize: number;
|
|
38
|
+
fontFamily: string;
|
|
39
|
+
theme?: Theme;
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* Generate render commands for the visible grid.
|
|
43
|
+
*
|
|
44
|
+
* This produces a flat list of drawing commands that a Skia Canvas can
|
|
45
|
+
* execute in order. The order is: backgrounds, text, decorations,
|
|
46
|
+
* selection overlay, cursor.
|
|
47
|
+
*/
|
|
48
|
+
renderFrame(grid: CellGrid, cursor: CursorState, selection: SelectionRange | null): RenderCommand[];
|
|
49
|
+
getCellSize(): {
|
|
50
|
+
width: number;
|
|
51
|
+
height: number;
|
|
52
|
+
};
|
|
53
|
+
setTheme(theme: Theme): void;
|
|
54
|
+
setFont(fontSize: number, fontFamily: string): void;
|
|
55
|
+
private resolveColor;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=SkiaRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SkiaRenderer.d.ts","sourceRoot":"","sources":["../../src/renderer/SkiaRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,KAAK,QAAQ,EAAqC,MAAM,iBAAiB,CAAC;AAMnF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA8DD,qBAAa,YAAY;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,OAAO,CAAW;gBAEd,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE;IAe5E;;;;;;OAMG;IACH,WAAW,CACT,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,cAAc,GAAG,IAAI,GAC/B,aAAa,EAAE;IAiLlB,WAAW,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAIhD,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAK5B,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAWnD,OAAO,CAAC,YAAY;CA0BrB"}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skia-based renderer for React Native (JS fallback).
|
|
3
|
+
*
|
|
4
|
+
* Instead of directly rendering pixels, this class generates a declarative
|
|
5
|
+
* list of `RenderCommand` objects that a @shopify/react-native-skia Canvas
|
|
6
|
+
* component can consume. This keeps all rendering logic testable without
|
|
7
|
+
* native dependencies.
|
|
8
|
+
*
|
|
9
|
+
* The command list is designed to be consumed in a single pass by a Skia
|
|
10
|
+
* Canvas `onDraw` callback or by mapping commands to Skia React components.
|
|
11
|
+
*/
|
|
12
|
+
import { DEFAULT_THEME, normalizeSelection } from "@next_term/core";
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// 256-color palette builder (shared with web renderer)
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
function build256Palette(theme) {
|
|
17
|
+
const palette = new Array(256);
|
|
18
|
+
const themeColors = [
|
|
19
|
+
theme.black,
|
|
20
|
+
theme.red,
|
|
21
|
+
theme.green,
|
|
22
|
+
theme.yellow,
|
|
23
|
+
theme.blue,
|
|
24
|
+
theme.magenta,
|
|
25
|
+
theme.cyan,
|
|
26
|
+
theme.white,
|
|
27
|
+
theme.brightBlack,
|
|
28
|
+
theme.brightRed,
|
|
29
|
+
theme.brightGreen,
|
|
30
|
+
theme.brightYellow,
|
|
31
|
+
theme.brightBlue,
|
|
32
|
+
theme.brightMagenta,
|
|
33
|
+
theme.brightCyan,
|
|
34
|
+
theme.brightWhite,
|
|
35
|
+
];
|
|
36
|
+
for (let i = 0; i < 16; i++) {
|
|
37
|
+
palette[i] = themeColors[i];
|
|
38
|
+
}
|
|
39
|
+
// 16-231: 6x6x6 color cube
|
|
40
|
+
const cubeLevels = [0, 0x5f, 0x87, 0xaf, 0xd7, 0xff];
|
|
41
|
+
for (let r = 0; r < 6; r++) {
|
|
42
|
+
for (let g = 0; g < 6; g++) {
|
|
43
|
+
for (let b = 0; b < 6; b++) {
|
|
44
|
+
palette[16 + r * 36 + g * 6 + b] =
|
|
45
|
+
`rgb(${cubeLevels[r]},${cubeLevels[g]},${cubeLevels[b]})`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// 232-255: grayscale ramp
|
|
50
|
+
for (let i = 0; i < 24; i++) {
|
|
51
|
+
const v = 8 + i * 10;
|
|
52
|
+
palette[232 + i] = `rgb(${v},${v},${v})`;
|
|
53
|
+
}
|
|
54
|
+
return palette;
|
|
55
|
+
}
|
|
56
|
+
// Attribute bit positions (matching core's packed attrs byte)
|
|
57
|
+
const ATTR_BOLD = 0x01;
|
|
58
|
+
const ATTR_ITALIC = 0x02;
|
|
59
|
+
const ATTR_UNDERLINE = 0x04;
|
|
60
|
+
const ATTR_STRIKETHROUGH = 0x08;
|
|
61
|
+
const ATTR_INVERSE = 0x40;
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// SkiaRenderer
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
export class SkiaRenderer {
|
|
66
|
+
cellWidth;
|
|
67
|
+
cellHeight;
|
|
68
|
+
fontSize;
|
|
69
|
+
fontFamily;
|
|
70
|
+
theme;
|
|
71
|
+
palette;
|
|
72
|
+
constructor(options) {
|
|
73
|
+
this.fontSize = options.fontSize;
|
|
74
|
+
this.fontFamily = options.fontFamily;
|
|
75
|
+
this.theme = options.theme ?? DEFAULT_THEME;
|
|
76
|
+
this.palette = build256Palette(this.theme);
|
|
77
|
+
// Estimate cell size from font metrics (no canvas measurement in RN)
|
|
78
|
+
this.cellWidth = Math.ceil(this.fontSize * 0.6);
|
|
79
|
+
this.cellHeight = Math.ceil(this.fontSize * 1.2);
|
|
80
|
+
}
|
|
81
|
+
// -----------------------------------------------------------------------
|
|
82
|
+
// Public API
|
|
83
|
+
// -----------------------------------------------------------------------
|
|
84
|
+
/**
|
|
85
|
+
* Generate render commands for the visible grid.
|
|
86
|
+
*
|
|
87
|
+
* This produces a flat list of drawing commands that a Skia Canvas can
|
|
88
|
+
* execute in order. The order is: backgrounds, text, decorations,
|
|
89
|
+
* selection overlay, cursor.
|
|
90
|
+
*/
|
|
91
|
+
renderFrame(grid, cursor, selection) {
|
|
92
|
+
const commands = [];
|
|
93
|
+
const { cols, rows } = grid;
|
|
94
|
+
const { cellWidth, cellHeight, fontSize, fontFamily, theme } = this;
|
|
95
|
+
// -- Row backgrounds & cell content -----------------------------------
|
|
96
|
+
for (let row = 0; row < rows; row++) {
|
|
97
|
+
// Full-row background
|
|
98
|
+
commands.push({
|
|
99
|
+
type: "rect",
|
|
100
|
+
x: 0,
|
|
101
|
+
y: row * cellHeight,
|
|
102
|
+
width: cols * cellWidth,
|
|
103
|
+
height: cellHeight,
|
|
104
|
+
color: theme.background,
|
|
105
|
+
});
|
|
106
|
+
for (let col = 0; col < cols; col++) {
|
|
107
|
+
const x = col * cellWidth;
|
|
108
|
+
const y = row * cellHeight;
|
|
109
|
+
const codepoint = grid.getCodepoint(row, col);
|
|
110
|
+
const fgIdx = grid.getFgIndex(row, col);
|
|
111
|
+
const bgIdx = grid.getBgIndex(row, col);
|
|
112
|
+
const attrs = grid.getAttrs(row, col);
|
|
113
|
+
const fgIsRGB = grid.isFgRGB(row, col);
|
|
114
|
+
const bgIsRGB = grid.isBgRGB(row, col);
|
|
115
|
+
let fg = this.resolveColor(fgIdx, fgIsRGB, grid, col, true);
|
|
116
|
+
let bg = this.resolveColor(bgIdx, bgIsRGB, grid, col, false);
|
|
117
|
+
// Handle inverse attribute
|
|
118
|
+
if (attrs & ATTR_INVERSE) {
|
|
119
|
+
const tmp = fg;
|
|
120
|
+
fg = bg;
|
|
121
|
+
bg = tmp;
|
|
122
|
+
}
|
|
123
|
+
// Cell background (only if non-default)
|
|
124
|
+
if (bg !== theme.background) {
|
|
125
|
+
commands.push({
|
|
126
|
+
type: "rect",
|
|
127
|
+
x,
|
|
128
|
+
y,
|
|
129
|
+
width: cellWidth,
|
|
130
|
+
height: cellHeight,
|
|
131
|
+
color: bg,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
// Character
|
|
135
|
+
const ch = codepoint > 0x20 ? String.fromCodePoint(codepoint) : null;
|
|
136
|
+
if (ch) {
|
|
137
|
+
const bold = !!(attrs & ATTR_BOLD);
|
|
138
|
+
const italic = !!(attrs & ATTR_ITALIC);
|
|
139
|
+
commands.push({
|
|
140
|
+
type: "text",
|
|
141
|
+
x,
|
|
142
|
+
y: y + Math.ceil(fontSize), // baseline offset
|
|
143
|
+
color: fg,
|
|
144
|
+
text: ch,
|
|
145
|
+
fontSize,
|
|
146
|
+
fontFamily,
|
|
147
|
+
bold,
|
|
148
|
+
italic,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
// Underline
|
|
152
|
+
if (attrs & ATTR_UNDERLINE) {
|
|
153
|
+
commands.push({
|
|
154
|
+
type: "line",
|
|
155
|
+
x,
|
|
156
|
+
y: y + cellHeight - 1,
|
|
157
|
+
width: cellWidth,
|
|
158
|
+
height: 1,
|
|
159
|
+
color: fg,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
// Strikethrough
|
|
163
|
+
if (attrs & ATTR_STRIKETHROUGH) {
|
|
164
|
+
commands.push({
|
|
165
|
+
type: "line",
|
|
166
|
+
x,
|
|
167
|
+
y: y + Math.floor(cellHeight / 2),
|
|
168
|
+
width: cellWidth,
|
|
169
|
+
height: 1,
|
|
170
|
+
color: fg,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// -- Selection overlay ------------------------------------------------
|
|
176
|
+
if (selection) {
|
|
177
|
+
const sel = normalizeSelection(selection);
|
|
178
|
+
const sr = Math.max(0, sel.startRow);
|
|
179
|
+
const er = Math.min(rows - 1, sel.endRow);
|
|
180
|
+
if (!(sr === er && sel.startCol === sel.endCol)) {
|
|
181
|
+
for (let row = sr; row <= er; row++) {
|
|
182
|
+
let colStart;
|
|
183
|
+
let colEnd;
|
|
184
|
+
if (sr === er) {
|
|
185
|
+
colStart = sel.startCol;
|
|
186
|
+
colEnd = sel.endCol;
|
|
187
|
+
}
|
|
188
|
+
else if (row === sr) {
|
|
189
|
+
colStart = sel.startCol;
|
|
190
|
+
colEnd = cols - 1;
|
|
191
|
+
}
|
|
192
|
+
else if (row === er) {
|
|
193
|
+
colStart = 0;
|
|
194
|
+
colEnd = sel.endCol;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
colStart = 0;
|
|
198
|
+
colEnd = cols - 1;
|
|
199
|
+
}
|
|
200
|
+
commands.push({
|
|
201
|
+
type: "rect",
|
|
202
|
+
x: colStart * cellWidth,
|
|
203
|
+
y: row * cellHeight,
|
|
204
|
+
width: (colEnd - colStart + 1) * cellWidth,
|
|
205
|
+
height: cellHeight,
|
|
206
|
+
color: theme.selectionBackground,
|
|
207
|
+
opacity: 0.5,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// -- Cursor -----------------------------------------------------------
|
|
213
|
+
if (cursor.visible) {
|
|
214
|
+
const cx = cursor.col * cellWidth;
|
|
215
|
+
const cy = cursor.row * cellHeight;
|
|
216
|
+
switch (cursor.style) {
|
|
217
|
+
case "block":
|
|
218
|
+
commands.push({
|
|
219
|
+
type: "rect",
|
|
220
|
+
x: cx,
|
|
221
|
+
y: cy,
|
|
222
|
+
width: cellWidth,
|
|
223
|
+
height: cellHeight,
|
|
224
|
+
color: theme.cursor,
|
|
225
|
+
opacity: 0.5,
|
|
226
|
+
});
|
|
227
|
+
break;
|
|
228
|
+
case "underline":
|
|
229
|
+
commands.push({
|
|
230
|
+
type: "rect",
|
|
231
|
+
x: cx,
|
|
232
|
+
y: cy + cellHeight - 2,
|
|
233
|
+
width: cellWidth,
|
|
234
|
+
height: 2,
|
|
235
|
+
color: theme.cursor,
|
|
236
|
+
});
|
|
237
|
+
break;
|
|
238
|
+
case "bar":
|
|
239
|
+
commands.push({
|
|
240
|
+
type: "rect",
|
|
241
|
+
x: cx,
|
|
242
|
+
y: cy,
|
|
243
|
+
width: 2,
|
|
244
|
+
height: cellHeight,
|
|
245
|
+
color: theme.cursor,
|
|
246
|
+
});
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return commands;
|
|
251
|
+
}
|
|
252
|
+
getCellSize() {
|
|
253
|
+
return { width: this.cellWidth, height: this.cellHeight };
|
|
254
|
+
}
|
|
255
|
+
setTheme(theme) {
|
|
256
|
+
this.theme = theme;
|
|
257
|
+
this.palette = build256Palette(theme);
|
|
258
|
+
}
|
|
259
|
+
setFont(fontSize, fontFamily) {
|
|
260
|
+
this.fontSize = fontSize;
|
|
261
|
+
this.fontFamily = fontFamily;
|
|
262
|
+
this.cellWidth = Math.ceil(fontSize * 0.6);
|
|
263
|
+
this.cellHeight = Math.ceil(fontSize * 1.2);
|
|
264
|
+
}
|
|
265
|
+
// -----------------------------------------------------------------------
|
|
266
|
+
// Color resolution
|
|
267
|
+
// -----------------------------------------------------------------------
|
|
268
|
+
resolveColor(colorIdx, isRGB, grid, col, isForeground) {
|
|
269
|
+
if (isRGB) {
|
|
270
|
+
const offset = isForeground ? col : 256 + col;
|
|
271
|
+
const rgb = grid.rgbColors[offset];
|
|
272
|
+
const r = (rgb >> 16) & 0xff;
|
|
273
|
+
const g = (rgb >> 8) & 0xff;
|
|
274
|
+
const b = rgb & 0xff;
|
|
275
|
+
return `rgb(${r},${g},${b})`;
|
|
276
|
+
}
|
|
277
|
+
// Default colors
|
|
278
|
+
if (isForeground && colorIdx === 7)
|
|
279
|
+
return this.theme.foreground;
|
|
280
|
+
if (!isForeground && colorIdx === 0)
|
|
281
|
+
return this.theme.background;
|
|
282
|
+
if (colorIdx >= 0 && colorIdx < 256) {
|
|
283
|
+
return this.palette[colorIdx];
|
|
284
|
+
}
|
|
285
|
+
return isForeground ? this.theme.foreground : this.theme.background;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=SkiaRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SkiaRenderer.js","sourceRoot":"","sources":["../../src/renderer/SkiaRenderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TurboModule spec for the native terminal core.
|
|
3
|
+
*
|
|
4
|
+
* This TypeScript interface defines the contract that a native C++ TurboModule
|
|
5
|
+
* would implement via JSI. The native implementation would handle:
|
|
6
|
+
* - VT parsing on a dedicated native thread
|
|
7
|
+
* - Metal (iOS) / Vulkan (Android) rendering
|
|
8
|
+
* - SharedArrayBuffer-backed cell grid for zero-copy JS access
|
|
9
|
+
*
|
|
10
|
+
* Until the native module is built, the JS-side `NativeTerminal` component
|
|
11
|
+
* uses `@next_term/core`'s BufferSet + VTParser as a fallback.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The TurboModule interface. In a full React Native New Architecture setup,
|
|
15
|
+
* this would extend `TurboModule` from `react-native`. We define a standalone
|
|
16
|
+
* interface here so the package can be tested without the RN runtime.
|
|
17
|
+
*/
|
|
18
|
+
export interface NativeTerminalCoreSpec {
|
|
19
|
+
/**
|
|
20
|
+
* Create a terminal instance. Returns an opaque numeric handle used
|
|
21
|
+
* to identify this terminal in all subsequent calls.
|
|
22
|
+
*/
|
|
23
|
+
createTerminal(cols: number, rows: number, scrollback: number): number;
|
|
24
|
+
/** Destroy a terminal instance and free its resources. */
|
|
25
|
+
destroyTerminal(handle: number): void;
|
|
26
|
+
/**
|
|
27
|
+
* Write data to the terminal. The native side performs VT parsing
|
|
28
|
+
* on a background thread and updates the shared cell grid.
|
|
29
|
+
*/
|
|
30
|
+
write(handle: number, data: string): void;
|
|
31
|
+
/** Resize the terminal grid. */
|
|
32
|
+
resize(handle: number, cols: number, rows: number): void;
|
|
33
|
+
/** Get the current cursor position and visibility. */
|
|
34
|
+
getCursor(handle: number): {
|
|
35
|
+
row: number;
|
|
36
|
+
col: number;
|
|
37
|
+
visible: boolean;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Get raw cell data for a row (for JS-side rendering fallback).
|
|
41
|
+
* Returns a Uint32Array-compatible ArrayBuffer with CELL_SIZE words per cell.
|
|
42
|
+
*/
|
|
43
|
+
getRowCells(handle: number, row: number): ArrayBuffer;
|
|
44
|
+
/**
|
|
45
|
+
* Get a bitmask of dirty rows. Each Int32 element is 1 if the
|
|
46
|
+
* corresponding row needs re-rendering, 0 otherwise.
|
|
47
|
+
*/
|
|
48
|
+
getDirtyRows(handle: number): ArrayBuffer;
|
|
49
|
+
/** Clear the dirty flag for a specific row after rendering it. */
|
|
50
|
+
clearDirty(handle: number, row: number): void;
|
|
51
|
+
/**
|
|
52
|
+
* Set the color theme. Keys are Theme property names (e.g. "foreground",
|
|
53
|
+
* "background", "red", etc.) and values are CSS-style color strings.
|
|
54
|
+
*/
|
|
55
|
+
setTheme(handle: number, theme: Record<string, string>): void;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=NativeTerminalCore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeTerminalCore.d.ts","sourceRoot":"","sources":["../../src/turbo-module/NativeTerminalCore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAEvE,0DAA0D;IAC1D,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtC;;;OAGG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1C,gCAAgC;IAChC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzD,sDAAsD;IACtD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAE1E;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;IAEtD;;;OAGG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC;IAE1C,kEAAkE;IAClE,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9C;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;CAC/D"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TurboModule spec for the native terminal core.
|
|
3
|
+
*
|
|
4
|
+
* This TypeScript interface defines the contract that a native C++ TurboModule
|
|
5
|
+
* would implement via JSI. The native implementation would handle:
|
|
6
|
+
* - VT parsing on a dedicated native thread
|
|
7
|
+
* - Metal (iOS) / Vulkan (Android) rendering
|
|
8
|
+
* - SharedArrayBuffer-backed cell grid for zero-copy JS access
|
|
9
|
+
*
|
|
10
|
+
* Until the native module is built, the JS-side `NativeTerminal` component
|
|
11
|
+
* uses `@next_term/core`'s BufferSet + VTParser as a fallback.
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=NativeTerminalCore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeTerminalCore.js","sourceRoot":"","sources":["../../src/turbo-module/NativeTerminalCore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@next_term/native",
|
|
3
|
+
"version": "0.1.0-next.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/rahulpandita/react-term",
|
|
8
|
+
"directory": "packages/native"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc"
|
|
21
|
+
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
24
|
+
"react-native": ">=0.73.0"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@next_term/core": "workspace:*"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"typescript": "^5.5.0",
|
|
31
|
+
"vitest": "^2.0.0",
|
|
32
|
+
"@types/react": "^19.0.0"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"!dist/__tests__"
|
|
37
|
+
],
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
}
|
|
41
|
+
}
|