@aitty/browser 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -0
- package/dist/browser.d.ts +6 -4
- package/dist/browser.js +3 -1
- package/dist/frontend/aitty-sw.js +43 -0
- package/dist/frontend/ansi-sequences.d.ts +7 -2
- package/dist/frontend/ansi-sequences.js +65 -2
- package/dist/frontend/ansi-style-tracker.d.ts +2 -6
- package/dist/frontend/ansi-style-tracker.js +11 -47
- package/dist/frontend/browser-terminal-renderer.d.ts +23 -15
- package/dist/frontend/browser-terminal-renderer.js +266 -102
- package/dist/frontend/cell-width.d.ts +1 -1
- package/dist/frontend/cell-width.js +1 -1
- package/dist/frontend/shell-controls.d.ts +24 -0
- package/dist/frontend/shell-controls.js +221 -0
- package/dist/frontend/terminal-app.d.ts +84 -20
- package/dist/frontend/terminal-app.js +2672 -278
- package/dist/frontend/terminal-config.d.ts +62 -0
- package/dist/frontend/terminal-config.js +126 -0
- package/dist/frontend/terminal-input-policies.d.ts +12 -2
- package/dist/frontend/terminal-input-policies.js +131 -49
- package/dist/frontend/terminal-scroll-anchor.js +25 -0
- package/dist/frontend/terminal-scroll-follow.js +23 -0
- package/dist/frontend/terminal-scrollback-window.js +18 -0
- package/dist/frontend/terminal-theme-protocol.d.ts +1 -1
- package/dist/frontend/terminal-theme-protocol.js +1 -1
- package/dist/frontend/terminal.css +161 -19
- package/dist/frontend/virtual-transcript-window.js +42 -0
- package/package.json +3 -3
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { normalizeThemeName } from "./terminal-config.js";
|
|
2
|
+
//#region packages/browser/src/frontend/shell-controls.ts
|
|
3
|
+
const DEFAULT_SCROLL_RESTORE_PASSES = 8;
|
|
4
|
+
const STICKY_BOTTOM_SCROLL_RESTORE_PASSES = 16;
|
|
5
|
+
function installShellControls(options) {
|
|
6
|
+
const { captureScrollAnchor, doc, focusTerminal, getConfig, onInterrupt, onScrollSurfaceChange, onStickToBottomChange, resetConfig, restoreScrollAnchor, shell, updateConfig, windowObject } = options;
|
|
7
|
+
const fontSizeLabel = shell.querySelector("[data-terminal-font-size]");
|
|
8
|
+
const fontSizeDecreaseControl = shell.querySelector("[data-shell-control=\"font-size-decrease\"]");
|
|
9
|
+
const fontSizeIncreaseControl = shell.querySelector("[data-shell-control=\"font-size-increase\"]");
|
|
10
|
+
const fontSizeResetControl = shell.querySelector("[data-shell-control=\"font-size-reset\"]");
|
|
11
|
+
const viewportFullscreenControl = shell.querySelector("[data-shell-control=\"viewport-fullscreen\"]");
|
|
12
|
+
const systemFullscreenControl = shell.querySelector("[data-shell-control=\"system-fullscreen\"]");
|
|
13
|
+
const terminalContainer = shell.querySelector(".terminal-container");
|
|
14
|
+
const themeToggle = shell.querySelector("#theme-toggle");
|
|
15
|
+
let viewportFullscreen = false;
|
|
16
|
+
let pendingScrollAnchor = null;
|
|
17
|
+
let suppressNextControlClick = false;
|
|
18
|
+
let scrollRestoreFrame = null;
|
|
19
|
+
let scrollRestorePassesRemaining = 0;
|
|
20
|
+
const cancelScrollRestore = () => {
|
|
21
|
+
if (scrollRestoreFrame === null) {
|
|
22
|
+
scrollRestorePassesRemaining = 0;
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
windowObject.cancelAnimationFrame(scrollRestoreFrame);
|
|
26
|
+
scrollRestoreFrame = null;
|
|
27
|
+
scrollRestorePassesRemaining = 0;
|
|
28
|
+
};
|
|
29
|
+
const scheduleScrollAnchorRestore = (scrollAnchor, passes = scrollAnchor.stickToBottom ? STICKY_BOTTOM_SCROLL_RESTORE_PASSES : DEFAULT_SCROLL_RESTORE_PASSES) => {
|
|
30
|
+
scrollRestorePassesRemaining = Math.max(scrollRestorePassesRemaining, passes);
|
|
31
|
+
if (scrollRestoreFrame !== null) return;
|
|
32
|
+
const runRestore = () => {
|
|
33
|
+
scrollRestoreFrame = windowObject.requestAnimationFrame(() => {
|
|
34
|
+
scrollRestoreFrame = null;
|
|
35
|
+
restoreScrollAnchor(scrollAnchor);
|
|
36
|
+
onScrollSurfaceChange?.();
|
|
37
|
+
scrollRestorePassesRemaining = Math.max(0, scrollRestorePassesRemaining - 1);
|
|
38
|
+
if (scrollRestorePassesRemaining > 0) runRestore();
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
runRestore();
|
|
42
|
+
};
|
|
43
|
+
const emitLayoutChange = () => {
|
|
44
|
+
windowObject.dispatchEvent(new windowObject.Event("resize"));
|
|
45
|
+
const scrollAnchor = pendingScrollAnchor;
|
|
46
|
+
pendingScrollAnchor = null;
|
|
47
|
+
onStickToBottomChange?.(scrollAnchor?.stickToBottom === true);
|
|
48
|
+
onScrollSurfaceChange?.();
|
|
49
|
+
if (!scrollAnchor) return;
|
|
50
|
+
windowObject.requestAnimationFrame(() => {
|
|
51
|
+
windowObject.requestAnimationFrame(() => {
|
|
52
|
+
scheduleScrollAnchorRestore(scrollAnchor);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
const captureScrollTransition = () => {
|
|
57
|
+
cancelScrollRestore();
|
|
58
|
+
pendingScrollAnchor = captureScrollAnchor();
|
|
59
|
+
};
|
|
60
|
+
const syncFontSizeControls = () => {
|
|
61
|
+
const { fontSize, fontSizeRange: range } = getConfig().appearance;
|
|
62
|
+
if (fontSizeLabel) fontSizeLabel.textContent = `${fontSize}px`;
|
|
63
|
+
fontSizeDecreaseControl?.toggleAttribute("disabled", fontSize <= range.min);
|
|
64
|
+
fontSizeIncreaseControl?.toggleAttribute("disabled", fontSize >= range.max);
|
|
65
|
+
fontSizeResetControl?.setAttribute("aria-label", `Reset terminal font size (${fontSize}px)`);
|
|
66
|
+
fontSizeResetControl?.setAttribute("title", `Reset terminal font size (${fontSize}px)`);
|
|
67
|
+
};
|
|
68
|
+
const changeFontSize = (direction) => {
|
|
69
|
+
const { fontSize, fontSizeRange: range } = getConfig().appearance;
|
|
70
|
+
updateConfig({ appearance: { fontSize: fontSize + direction * range.step } });
|
|
71
|
+
syncFontSizeControls();
|
|
72
|
+
focusTerminal();
|
|
73
|
+
};
|
|
74
|
+
const resetFontSize = () => {
|
|
75
|
+
updateConfig({ appearance: { fontSize: resetConfig.appearance.fontSize } });
|
|
76
|
+
syncFontSizeControls();
|
|
77
|
+
focusTerminal();
|
|
78
|
+
};
|
|
79
|
+
const syncViewportFullscreenState = () => {
|
|
80
|
+
shell.dataset.viewportFullscreen = viewportFullscreen ? "true" : "false";
|
|
81
|
+
viewportFullscreenControl?.setAttribute("aria-pressed", viewportFullscreen ? "true" : "false");
|
|
82
|
+
viewportFullscreenControl?.setAttribute("aria-label", viewportFullscreen ? "Exit browser fullscreen" : "Enter browser fullscreen");
|
|
83
|
+
viewportFullscreenControl?.setAttribute("title", viewportFullscreen ? "Exit browser fullscreen" : "Enter browser fullscreen");
|
|
84
|
+
emitLayoutChange();
|
|
85
|
+
};
|
|
86
|
+
const syncSystemFullscreenState = () => {
|
|
87
|
+
const fullscreen = doc.fullscreenElement === shell;
|
|
88
|
+
shell.dataset.fullscreen = fullscreen ? "true" : "false";
|
|
89
|
+
systemFullscreenControl?.setAttribute("aria-pressed", fullscreen ? "true" : "false");
|
|
90
|
+
systemFullscreenControl?.setAttribute("aria-label", fullscreen ? "Exit system fullscreen" : "Enter system fullscreen");
|
|
91
|
+
systemFullscreenControl?.setAttribute("title", fullscreen ? "Exit system fullscreen" : "Enter system fullscreen");
|
|
92
|
+
emitLayoutChange();
|
|
93
|
+
};
|
|
94
|
+
const toggleViewportFullscreen = () => {
|
|
95
|
+
captureScrollTransition();
|
|
96
|
+
viewportFullscreen = !viewportFullscreen;
|
|
97
|
+
syncViewportFullscreenState();
|
|
98
|
+
};
|
|
99
|
+
const toggleSystemFullscreen = async () => {
|
|
100
|
+
if (doc.fullscreenElement === shell) {
|
|
101
|
+
captureScrollTransition();
|
|
102
|
+
if (doc.fullscreenElement && typeof doc.exitFullscreen === "function") await doc.exitFullscreen();
|
|
103
|
+
else syncSystemFullscreenState();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (typeof shell.requestFullscreen !== "function") {
|
|
107
|
+
toggleViewportFullscreen();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
captureScrollTransition();
|
|
111
|
+
try {
|
|
112
|
+
await shell.requestFullscreen();
|
|
113
|
+
} catch {
|
|
114
|
+
pendingScrollAnchor = null;
|
|
115
|
+
toggleViewportFullscreen();
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const toggleTheme = () => {
|
|
119
|
+
const nextTheme = (getConfig().appearance.theme ?? normalizeThemeName(shell.dataset.theme)) === "light" ? "dark" : "light";
|
|
120
|
+
shell.dataset.themeOverride = "true";
|
|
121
|
+
updateConfig({ appearance: { theme: nextTheme } });
|
|
122
|
+
focusTerminal();
|
|
123
|
+
};
|
|
124
|
+
const toggleCollapse = () => {
|
|
125
|
+
const isCollapsed = terminalContainer?.dataset.collapsed === "true";
|
|
126
|
+
if (terminalContainer) {
|
|
127
|
+
terminalContainer.dataset.collapsed = isCollapsed ? "false" : "true";
|
|
128
|
+
emitLayoutChange();
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const runAction = (action) => {
|
|
132
|
+
if (action === "close") {
|
|
133
|
+
onInterrupt();
|
|
134
|
+
focusTerminal();
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (action === "viewport-fullscreen") {
|
|
138
|
+
toggleViewportFullscreen();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (action === "system-fullscreen") {
|
|
142
|
+
toggleSystemFullscreen();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (action === "collapse") {
|
|
146
|
+
toggleCollapse();
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (action === "font-size-decrease") {
|
|
150
|
+
changeFontSize(-1);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (action === "font-size-increase") {
|
|
154
|
+
changeFontSize(1);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (action === "font-size-reset") resetFontSize();
|
|
158
|
+
};
|
|
159
|
+
const handleClick = (event) => {
|
|
160
|
+
const target = event.target instanceof Element ? event.target : null;
|
|
161
|
+
const control = target?.closest("[data-shell-control]");
|
|
162
|
+
if (control && shell.contains(control)) {
|
|
163
|
+
event.preventDefault();
|
|
164
|
+
if (suppressNextControlClick) {
|
|
165
|
+
suppressNextControlClick = false;
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
runAction(control.dataset.shellControl);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (themeToggle && (themeToggle === target || themeToggle.contains(target))) {
|
|
172
|
+
event.preventDefault();
|
|
173
|
+
toggleTheme();
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const handlePointerDown = (event) => {
|
|
177
|
+
const control = (event.target instanceof Element ? event.target : null)?.closest("[data-shell-control]");
|
|
178
|
+
if (!control || !shell.contains(control) || control.dataset.shellControl !== "viewport-fullscreen" || !shouldUsePointerDownViewportFullscreenToggle(windowObject)) return;
|
|
179
|
+
event.preventDefault();
|
|
180
|
+
suppressNextControlClick = true;
|
|
181
|
+
toggleViewportFullscreen();
|
|
182
|
+
};
|
|
183
|
+
const handleExternalControl = (event) => {
|
|
184
|
+
runAction("detail" in event ? event.detail : void 0);
|
|
185
|
+
};
|
|
186
|
+
const handleFullscreenChange = () => {
|
|
187
|
+
syncSystemFullscreenState();
|
|
188
|
+
};
|
|
189
|
+
const systemThemeMediaQuery = windowObject.matchMedia("(prefers-color-scheme: dark)");
|
|
190
|
+
const handleSystemThemeChange = (event) => {
|
|
191
|
+
if (!shell.dataset.themeOverride) updateConfig({ appearance: { theme: event.matches ? "dark" : "light" } });
|
|
192
|
+
};
|
|
193
|
+
shell.addEventListener("pointerdown", handlePointerDown, true);
|
|
194
|
+
shell.addEventListener("click", handleClick);
|
|
195
|
+
windowObject.addEventListener("aitty:control", handleExternalControl);
|
|
196
|
+
doc.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
197
|
+
if (typeof systemThemeMediaQuery.addEventListener === "function") systemThemeMediaQuery.addEventListener("change", handleSystemThemeChange);
|
|
198
|
+
else systemThemeMediaQuery.addListener(handleSystemThemeChange);
|
|
199
|
+
if (!shell.dataset.theme) handleSystemThemeChange(systemThemeMediaQuery);
|
|
200
|
+
syncViewportFullscreenState();
|
|
201
|
+
syncSystemFullscreenState();
|
|
202
|
+
syncFontSizeControls();
|
|
203
|
+
return () => {
|
|
204
|
+
cancelScrollRestore();
|
|
205
|
+
shell.removeEventListener("pointerdown", handlePointerDown, true);
|
|
206
|
+
shell.removeEventListener("click", handleClick);
|
|
207
|
+
windowObject.removeEventListener("aitty:control", handleExternalControl);
|
|
208
|
+
doc.removeEventListener("fullscreenchange", handleFullscreenChange);
|
|
209
|
+
if (typeof systemThemeMediaQuery.removeEventListener === "function") systemThemeMediaQuery.removeEventListener("change", handleSystemThemeChange);
|
|
210
|
+
else systemThemeMediaQuery.removeListener(handleSystemThemeChange);
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function shouldUsePointerDownViewportFullscreenToggle(windowObject) {
|
|
214
|
+
const navigatorLike = windowObject.navigator;
|
|
215
|
+
const platform = navigatorLike?.platform ?? "";
|
|
216
|
+
const userAgent = navigatorLike?.userAgent ?? "";
|
|
217
|
+
const maxTouchPoints = navigatorLike?.maxTouchPoints ?? 0;
|
|
218
|
+
return (/iP(?:hone|ad|od)/.test(platform) || /iP(?:hone|ad|od)/.test(userAgent) || platform === "MacIntel" && maxTouchPoints > 1) && windowObject.matchMedia?.("(pointer: coarse)").matches === true;
|
|
219
|
+
}
|
|
220
|
+
//#endregion
|
|
221
|
+
export { installShellControls };
|
|
@@ -1,26 +1,40 @@
|
|
|
1
1
|
import { BrowserTerminalBridge, BrowserTerminalRenderOptions } from "./browser-terminal-renderer.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { AittyRuntimeKind, AittyTerminalConnectionState, AittyTerminalLoadingPresentation, AittyTerminalOutputState, AittyTerminalSessionPresentationState, AittyTerminalStatusSnapshot, AittyTheme } from "@aitty/protocol";
|
|
2
|
+
import { TerminalAppearanceConfig, TerminalBehaviorConfig, TerminalConfig, TerminalConfigListener, TerminalConfigPatch, TerminalFontSizeRange, TerminalResolvedAppearanceConfig, TerminalResolvedBehaviorConfig, TerminalResolvedConfig, TerminalTheme, TerminalThemeTarget } from "./terminal-config.js";
|
|
3
|
+
import { AittyRuntimeKind, AittyTerminalConnectionState, AittyTerminalLoadingPresentation, AittyTerminalOutputState, AittyTerminalSessionPresentationState, AittyTerminalStatusSnapshot } from "@aitty/protocol";
|
|
5
4
|
|
|
6
|
-
//#region src/frontend/terminal-app.d.ts
|
|
5
|
+
//#region packages/browser/src/frontend/terminal-app.d.ts
|
|
7
6
|
type RuntimeKind = AittyRuntimeKind;
|
|
8
|
-
type TerminalTheme = AittyTheme;
|
|
9
7
|
type TerminalConnectionState = AittyTerminalConnectionState;
|
|
10
8
|
type TerminalOutputState = AittyTerminalOutputState;
|
|
11
9
|
type TerminalSessionPresentationState = AittyTerminalSessionPresentationState;
|
|
12
10
|
type BinaryWriteTarget = {
|
|
13
11
|
write(data: Uint8Array): void;
|
|
14
12
|
};
|
|
13
|
+
type TimeoutHandle = ReturnType<typeof setTimeout> | number;
|
|
15
14
|
type FrameScheduler = {
|
|
16
15
|
cancelFrame?: (handle: number) => void;
|
|
16
|
+
now?: () => number;
|
|
17
17
|
requestFrame?: (callback: FrameRequestCallback) => number;
|
|
18
|
+
clearTimeout?: (handle: TimeoutHandle) => void;
|
|
19
|
+
setTimeout?: (callback: () => void, delayMs: number) => TimeoutHandle;
|
|
18
20
|
};
|
|
19
21
|
type BufferedTerminalWriter = {
|
|
20
22
|
destroy(): void;
|
|
21
23
|
discardPending(): void;
|
|
22
24
|
enqueue(chunk: Uint8Array): void;
|
|
23
25
|
};
|
|
26
|
+
type BufferedTerminalWriterOptions = {
|
|
27
|
+
maxBytesPerFrame?: number;
|
|
28
|
+
minFrameIntervalMs?: number;
|
|
29
|
+
resolveMinFrameIntervalMs?: (payload: {
|
|
30
|
+
pendingByteLength: number;
|
|
31
|
+
}) => number;
|
|
32
|
+
onDrain?: () => void;
|
|
33
|
+
onFlush?: (payload: {
|
|
34
|
+
pendingByteLength: number;
|
|
35
|
+
wroteByteLength: number;
|
|
36
|
+
}) => void;
|
|
37
|
+
};
|
|
24
38
|
type TerminalLoadingPresentation = AittyTerminalLoadingPresentation;
|
|
25
39
|
type TerminalStatusSnapshot = AittyTerminalStatusSnapshot;
|
|
26
40
|
type TerminalStatusListener = (status: TerminalStatusSnapshot) => void;
|
|
@@ -76,68 +90,116 @@ type TerminalTransport = {
|
|
|
76
90
|
send(data: string | Uint8Array): void;
|
|
77
91
|
sendControl?(data: string): void;
|
|
78
92
|
};
|
|
93
|
+
type BrowserWTermOptions = {
|
|
94
|
+
autoResize?: boolean;
|
|
95
|
+
cols?: number;
|
|
96
|
+
cursorBlink?: boolean;
|
|
97
|
+
onData?: (data: string) => void;
|
|
98
|
+
onResize?: (cols: number, rows: number) => void;
|
|
99
|
+
onTitle?: (title: string) => void;
|
|
100
|
+
rows?: number;
|
|
101
|
+
wasmUrl?: string;
|
|
102
|
+
};
|
|
79
103
|
type MountTerminalDependencies = {
|
|
80
|
-
|
|
104
|
+
config?: TerminalConfig;
|
|
105
|
+
createTerm?: (element: HTMLElement, options: BrowserWTermOptions) => BrowserWTerm;
|
|
81
106
|
createTransport?: (handlers: TransportHandlers) => TerminalTransport;
|
|
82
107
|
elements?: MountTerminalElements;
|
|
83
108
|
frameScheduler?: FrameScheduler;
|
|
84
|
-
|
|
85
|
-
resolveKey?: TerminalKeyResolver;
|
|
86
|
-
};
|
|
109
|
+
onConfigChange?: TerminalConfigListener;
|
|
87
110
|
onStatusChange?: TerminalStatusListener;
|
|
88
111
|
reconnectDelayMs?: number;
|
|
89
112
|
resolveRuntimeKind?: (doc: Document, shell: HTMLElement) => RuntimeKind | Promise<RuntimeKind>;
|
|
90
113
|
scroll?: TerminalScrollOptions;
|
|
114
|
+
shellControls?: boolean;
|
|
91
115
|
src?: string | URL;
|
|
92
|
-
theme?: TerminalTheme;
|
|
93
|
-
transcriptArchiveOptions?: {
|
|
94
|
-
scrollbackLimit?: number;
|
|
95
|
-
};
|
|
96
116
|
};
|
|
97
117
|
type MountedTerminalApp = {
|
|
98
118
|
destroy(): void;
|
|
119
|
+
getConfig(): TerminalResolvedConfig;
|
|
99
120
|
getStatus(): TerminalStatusSnapshot;
|
|
100
|
-
getTheme(): string | undefined;
|
|
101
|
-
setTheme(theme: TerminalTheme | undefined): void;
|
|
102
121
|
term: BrowserWTerm;
|
|
103
122
|
transport: TerminalTransport;
|
|
123
|
+
updateConfig(config: TerminalConfigPatch): TerminalResolvedConfig;
|
|
104
124
|
};
|
|
105
125
|
type TerminalRendererLike = {
|
|
106
126
|
cols?: number;
|
|
127
|
+
getRenderedScrollbackCount?: () => number;
|
|
107
128
|
render?(bridge: BrowserTerminalBridge, options?: BrowserTerminalRenderOptions): void;
|
|
108
129
|
rows?: number;
|
|
109
130
|
setup?(cols: number, rows: number): void;
|
|
110
131
|
};
|
|
132
|
+
type BrowserWTermWriteOptions = {
|
|
133
|
+
scheduleRender?: boolean;
|
|
134
|
+
};
|
|
111
135
|
type BrowserWTerm = {
|
|
112
136
|
_container?: HTMLElement;
|
|
113
137
|
_measureCharSize?: () => TerminalCellMetrics;
|
|
114
138
|
bridge?: BrowserTerminalBridge | null;
|
|
139
|
+
clearSelection?: () => void;
|
|
115
140
|
cols: number;
|
|
116
141
|
destroy(): void;
|
|
117
142
|
element: HTMLElement;
|
|
118
143
|
focus(): void;
|
|
144
|
+
getSelectionText?: () => string;
|
|
145
|
+
hasSelection?: () => boolean;
|
|
119
146
|
init(): Promise<unknown>;
|
|
120
147
|
input?: {
|
|
121
148
|
destroy?: () => void;
|
|
122
149
|
focus?: () => void;
|
|
150
|
+
setImeAnchor?: (anchor: HTMLElement | null) => void;
|
|
123
151
|
textarea?: HTMLTextAreaElement | null;
|
|
124
152
|
};
|
|
153
|
+
renderNow?: (options?: BrowserTerminalRenderOptions) => void;
|
|
125
154
|
renderer?: TerminalRendererLike;
|
|
126
155
|
resize(cols: number, rows: number): void;
|
|
127
156
|
rows: number;
|
|
128
|
-
write?(data: string | Uint8Array): void;
|
|
157
|
+
write?(data: string | Uint8Array, options?: BrowserWTermWriteOptions): void;
|
|
129
158
|
};
|
|
130
159
|
type TerminalCellMetrics = {
|
|
131
160
|
charWidth: number;
|
|
132
161
|
rowHeight: number;
|
|
133
162
|
};
|
|
163
|
+
type BrowserWindow = Window & typeof globalThis;
|
|
164
|
+
type MobileComposerControl = "arrow-down" | "arrow-left" | "arrow-right" | "arrow-up" | "enter" | "esc" | "tab";
|
|
165
|
+
declare const MOBILE_COMPOSER_PRIMARY_CONTROLS: readonly MobileComposerControl[];
|
|
166
|
+
type BrowserViewport = {
|
|
167
|
+
browserChromeInsetBottom: number;
|
|
168
|
+
height: number;
|
|
169
|
+
keyboardInsetBottom: number;
|
|
170
|
+
offsetTop: number;
|
|
171
|
+
safeHeight: number;
|
|
172
|
+
width: number;
|
|
173
|
+
};
|
|
174
|
+
type MobileFocusProxyPosition = {
|
|
175
|
+
anchor: "mobile-focus-proxy";
|
|
176
|
+
height: number;
|
|
177
|
+
left: number;
|
|
178
|
+
top: number;
|
|
179
|
+
width: number;
|
|
180
|
+
};
|
|
181
|
+
type MobileFocusProxyPointerState = {
|
|
182
|
+
keyboardOpen?: boolean;
|
|
183
|
+
textareaFocused?: boolean;
|
|
184
|
+
};
|
|
134
185
|
/**
|
|
135
186
|
* Batches raw PTY bytes into animation frames without splitting UTF-8 codepoints or
|
|
136
187
|
* incomplete ANSI sequences. This is the only throttling layer in the browser path.
|
|
137
188
|
*/
|
|
138
|
-
declare function createBufferedTerminalWriter(target: BinaryWriteTarget, scheduler?: FrameScheduler, options?:
|
|
139
|
-
|
|
140
|
-
|
|
189
|
+
declare function createBufferedTerminalWriter(target: BinaryWriteTarget, scheduler?: FrameScheduler, options?: BufferedTerminalWriterOptions): BufferedTerminalWriter;
|
|
190
|
+
declare function resolveBrowserViewport(windowObject: BrowserWindow): BrowserViewport;
|
|
191
|
+
declare function resolveMobileFocusProxyPosition(windowObject: BrowserWindow): MobileFocusProxyPosition;
|
|
192
|
+
declare function shouldEnableMobileFocusProxyPointerEvents(windowObject: BrowserWindow, state?: MobileFocusProxyPointerState): boolean;
|
|
193
|
+
declare function isMobileLiveInputTapTarget(terminalRoot: HTMLElement, windowObject: BrowserWindow, clientX: number, clientY: number): boolean;
|
|
194
|
+
declare function resolveMobileKeyboardPromptAlignDelays(): number[];
|
|
195
|
+
declare function resolveTerminalOutputFrameIntervalMs({
|
|
196
|
+
pendingByteLength,
|
|
197
|
+
sustainedPressure
|
|
198
|
+
}: {
|
|
199
|
+
pendingByteLength: number;
|
|
200
|
+
sustainedPressure?: boolean;
|
|
201
|
+
}): number;
|
|
202
|
+
declare function resolveMobileComposerExpandedListHeight(controlCount?: number): number;
|
|
141
203
|
declare function mountTerminalApp(doc?: Document, dependencies?: MountTerminalDependencies): Promise<MountedTerminalApp>;
|
|
142
204
|
interface MountAittyOptions extends MountTerminalDependencies {
|
|
143
205
|
document?: Document;
|
|
@@ -152,5 +214,7 @@ interface MountAittyContainerOptions extends Omit<MountAittyOptions, "elements"
|
|
|
152
214
|
declare function mountAitty(options?: MountAittyOptions): Promise<MountedTerminalApp>;
|
|
153
215
|
declare function mountAitty(container: HTMLElement | string, options?: MountAittyContainerOptions): Promise<MountedTerminalApp>;
|
|
154
216
|
declare function defineAittyTerminalElement(registry?: CustomElementRegistry | undefined): void;
|
|
217
|
+
declare function shouldFollowLiveOutputOnUserInputData(data: string | Uint8Array): boolean;
|
|
218
|
+
declare function resolveMobileComposerControlSequence(control: MobileComposerControl): string;
|
|
155
219
|
//#endregion
|
|
156
|
-
export { BinaryWriteTarget, BufferedTerminalWriter, FrameScheduler, MountAittyContainerOptions, MountAittyOptions, MountTerminalDependencies, MountTerminalElements, MountedTerminalApp, TerminalConnectionState, TerminalLoadingPresentation, TerminalOutputState, TerminalScrollAdapter, TerminalScrollAdapterContext, TerminalScrollAdapterFactory, TerminalScrollMetrics, TerminalScrollOptions, TerminalSessionPresentationState, TerminalStatusListener, TerminalStatusSnapshot, TerminalTheme, TerminalTransport, TransportCloseEvent, TransportHandlers, createBufferedTerminalWriter, defineAittyTerminalElement, mountAitty, mountTerminalApp };
|
|
220
|
+
export { BinaryWriteTarget, BrowserViewport, BrowserWTermOptions, BufferedTerminalWriter, FrameScheduler, MOBILE_COMPOSER_PRIMARY_CONTROLS, MobileFocusProxyPointerState, MobileFocusProxyPosition, MountAittyContainerOptions, MountAittyOptions, MountTerminalDependencies, MountTerminalElements, MountedTerminalApp, type TerminalAppearanceConfig, type TerminalBehaviorConfig, type TerminalConfig, type TerminalConfigListener, type TerminalConfigPatch, TerminalConnectionState, type TerminalFontSizeRange, TerminalLoadingPresentation, TerminalOutputState, type TerminalResolvedAppearanceConfig, type TerminalResolvedBehaviorConfig, type TerminalResolvedConfig, TerminalScrollAdapter, TerminalScrollAdapterContext, TerminalScrollAdapterFactory, TerminalScrollMetrics, TerminalScrollOptions, TerminalSessionPresentationState, TerminalStatusListener, TerminalStatusSnapshot, type TerminalTheme, type TerminalThemeTarget, TerminalTransport, TransportCloseEvent, TransportHandlers, createBufferedTerminalWriter, defineAittyTerminalElement, isMobileLiveInputTapTarget, mountAitty, mountTerminalApp, resolveBrowserViewport, resolveMobileComposerControlSequence, resolveMobileComposerExpandedListHeight, resolveMobileFocusProxyPosition, resolveMobileKeyboardPromptAlignDelays, resolveTerminalOutputFrameIntervalMs, shouldEnableMobileFocusProxyPointerEvents, shouldFollowLiveOutputOnUserInputData };
|