@floegence/floeterm-terminal-web 0.4.31 → 0.5.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 CHANGED
@@ -1,43 +1,70 @@
1
1
  # terminal-web
2
2
 
3
- Headless ghostty-web (xterm.js API-compatible) integration with data flow utilities. Provides `TerminalCore` and
4
- `useTerminalInstance` without UI components.
3
+ Framework-neutral ghostty-web (xterm.js API-compatible) integration with terminal core, session, and data flow utilities.
5
4
 
6
5
  ## Install
6
+
7
7
  ```bash
8
8
  npm i @floegence/floeterm-terminal-web
9
9
  ```
10
10
 
11
- ## Usage (React)
12
- ```tsx
13
- import { useTerminalInstance } from '@floegence/floeterm-terminal-web';
11
+ ## Usage
14
12
 
15
- export function TerminalPane() {
16
- const { containerRef } = useTerminalInstance({
17
- sessionId: 'session-1',
18
- isActive: true,
19
- transport: myTransport,
20
- eventSource: myEventSource
21
- });
13
+ Use the managed controller when you want attach, reconnect-friendly replay, ordered writes, resize, and action helpers handled for you:
22
14
 
23
- return <div ref={containerRef} style={{ height: 400 }} />;
24
- }
15
+ ```ts
16
+ import { createTerminalInstance } from '@floegence/floeterm-terminal-web';
17
+
18
+ const controller = createTerminalInstance({
19
+ sessionId: 'session-1',
20
+ isActive: true,
21
+ transport: myTransport,
22
+ eventSource: myEventSource,
23
+ });
24
+
25
+ const unsubscribe = controller.subscribe((snapshot) => {
26
+ console.log(snapshot.connection.state, snapshot.loadingMessage);
27
+ });
28
+
29
+ await controller.mount(container);
30
+
31
+ // Later:
32
+ controller.actions.copySelection('command');
33
+ unsubscribe();
34
+ controller.dispose();
35
+ ```
36
+
37
+ Use `TerminalCore` directly when the host product owns its own session lifecycle, paging, shell integration, or workbench coordination:
38
+
39
+ ```ts
40
+ import { TerminalCore, getDefaultTerminalConfig } from '@floegence/floeterm-terminal-web';
41
+
42
+ const core = new TerminalCore(
43
+ container,
44
+ getDefaultTerminalConfig('dark', { clipboard: { copyOnSelect: false } }),
45
+ {
46
+ onData: data => transport.sendInput(sessionId, data),
47
+ onResize: size => transport.resize(sessionId, size.cols, size.rows),
48
+ },
49
+ );
50
+
51
+ await core.initialize();
25
52
  ```
26
53
 
27
54
  ## Notes
28
- - You must provide a `TerminalTransport` and `TerminalEventSource`.
29
- - `ghostty-web` needs a one-time `init()` (handled internally by `TerminalCore`).
30
- - `TerminalCore` bridges the hidden textarea used by `ghostty-web`, so soft-keyboard and IME input continue to work on touch devices.
55
+
56
+ - You must provide a `TerminalTransport` and `TerminalEventSource` for the managed controller.
57
+ - `ghostty-web` needs a one-time `init()`; `TerminalCore` handles that internally.
58
+ - `TerminalCore` bridges the hidden textarea used by `ghostty-web`, so soft-keyboard and composition input continue to work on touch devices.
31
59
  - Explicit terminal copy is handled through shared selection-copy APIs, so keyboard shortcuts, native app menus, and product context menus can reuse the same selection logic.
32
- - `TerminalCore` now exposes first-class APIs for runtime appearance updates, shell bell/title events, and custom terminal link providers without reaching into implementation internals.
60
+ - `TerminalCore` exposes runtime appearance updates, shell bell/title events, custom terminal link providers, buffer line reads, and touch-scroll helpers without requiring consumers to reach into private runtime objects.
61
+ - Multiple live `TerminalCore` instances share one render scheduler, so large terminal grids coalesce demand-driven canvas work into browser frames.
33
62
 
34
- ## Responsive resize (multi-pane / multi-view)
35
- When the same remote terminal session can be displayed in multiple views (e.g. a Deck widget and a dedicated Terminal page),
36
- enable the responsive options so the focused terminal re-syncs cols/rows to the remote PTY:
63
+ ## Responsive Resize
37
64
 
38
- ```ts
39
- import { TerminalCore } from '@floegence/floeterm-terminal-web';
65
+ When the same remote terminal session can be displayed in multiple views, enable responsive options so the focused terminal re-syncs cols/rows to the remote PTY:
40
66
 
67
+ ```ts
41
68
  const core = new TerminalCore(container, {
42
69
  responsive: {
43
70
  fitOnFocus: true,
@@ -47,21 +74,18 @@ const core = new TerminalCore(container, {
47
74
  });
48
75
  ```
49
76
 
50
- Passive mirrors of a remote PTY can render with the session owner's current dimensions instead of fitting their own
51
- container:
77
+ Passive mirrors of a remote PTY can render with the session owner's current dimensions:
52
78
 
53
79
  ```ts
54
80
  const core = new TerminalCore(container, {
55
81
  fixedDimensions: { cols: 100, rows: 30 },
56
82
  });
57
83
 
58
- // Later, when this surface becomes the active geometry owner:
59
84
  core.setFixedDimensions(null);
60
85
  core.forceResize();
61
86
  ```
62
87
 
63
- Hosts with overlay scrollbars can remove the default ghostty-web scrollbar reserve so the computed grid fills the
64
- terminal surface:
88
+ Hosts with overlay scrollbars can remove the default ghostty-web scrollbar reserve:
65
89
 
66
90
  ```ts
67
91
  const core = new TerminalCore(container, {
@@ -71,13 +95,11 @@ const core = new TerminalCore(container, {
71
95
  });
72
96
  ```
73
97
 
74
- ## Clipboard behavior
75
- By default, upstream mouse selection keeps the `ghostty-web` behavior and copies immediately on selection.
76
- Consumers that want explicit copy commands only can disable that side effect:
98
+ ## Clipboard
77
99
 
78
- ```ts
79
- import { TerminalCore } from '@floegence/floeterm-terminal-web';
100
+ By default, upstream mouse selection keeps the `ghostty-web` behavior and copies immediately on selection. Consumers that want explicit copy commands only can disable that side effect:
80
101
 
102
+ ```ts
81
103
  const core = new TerminalCore(container, {
82
104
  clipboard: {
83
105
  copyOnSelect: false,
@@ -91,9 +113,10 @@ With `copyOnSelect: false`, `TerminalCore` keeps selection explicit:
91
113
  - `core.copySelection()` writes the current terminal selection to the clipboard.
92
114
  - `Cmd+C` / `Ctrl+C` only claims the shortcut when the terminal currently has a selection. Otherwise the shortcut falls through unchanged.
93
115
 
94
- If you use the React hook, the same helpers are available on `actions.hasSelection()` and `actions.copySelection()`.
116
+ The managed controller exposes the same helpers through `controller.actions`.
117
+
118
+ ## Link Providers And Buffer Reads
95
119
 
96
- ## Link providers and shell events
97
120
  `TerminalCore` forwards shell lifecycle events and lets consumers register custom links over rendered terminal rows:
98
121
 
99
122
  ```ts
@@ -101,26 +124,40 @@ import { TerminalCore, type TerminalLinkProvider } from '@floegence/floeterm-ter
101
124
 
102
125
  const linkProvider: TerminalLinkProvider = {
103
126
  provideLinks(y, callback) {
104
- void y;
127
+ const line = core.readBufferLine(y);
128
+ void line;
105
129
  callback(undefined);
106
130
  },
107
131
  };
108
132
 
109
133
  const core = new TerminalCore(container, {}, {
110
134
  onBell: () => console.log('bell'),
111
- onTitleChange: (title) => console.log('title', title),
135
+ onTitleChange: title => console.log('title', title),
112
136
  });
113
137
 
114
138
  await core.initialize();
115
139
  core.registerLinkProvider(linkProvider);
116
140
  ```
117
141
 
118
- This is the intended extension point for product features such as modifier-click file navigation,
119
- build-log deep links, or shell attention badges driven by bell events.
142
+ This is the intended extension point for product features such as modifier-click file navigation, build-log deep links, or shell attention badges driven by bell events.
120
143
 
121
- ## Visual work suspension
122
- Hosts that animate a surrounding workbench can temporarily suspend expensive terminal visual work while keeping PTY output
123
- and the terminal buffer live:
144
+ ## Touch Scroll Helpers
145
+
146
+ Hosts with custom mobile input surfaces can ask `TerminalCore` for a safe touch-scroll facade instead of reaching into the underlying runtime:
147
+
148
+ ```ts
149
+ const touch = core.getTouchScrollRuntime();
150
+
151
+ if (touch?.isAlternateScreen()) {
152
+ touch.sendAlternateScreenInput('\x1B[A');
153
+ } else {
154
+ touch?.scrollLines(-3);
155
+ }
156
+ ```
157
+
158
+ ## Visual Work Suspension
159
+
160
+ Hosts that animate a surrounding workbench can temporarily suspend expensive terminal visual work while keeping PTY output and the terminal buffer live:
124
161
 
125
162
  ```ts
126
163
  const suspend = core.beginVisualSuspend({ reason: 'workbench_widget_drag' });
@@ -132,12 +169,24 @@ try {
132
169
  }
133
170
  ```
134
171
 
135
- While suspended, `write()` continues to update terminal state. Rendering, fit, full repaint, and overlay refresh requests
136
- are coalesced and reconciled when the final nested suspend handle is disposed.
172
+ While suspended, `write()` continues to update terminal state. Rendering, fit, full repaint, and overlay refresh requests are coalesced and reconciled when the final nested suspend handle is disposed.
173
+
174
+ ## Multi-Terminal Render Scheduling
175
+
176
+ `TerminalCore` keeps ghostty-web rendering demand-driven and routes visible terminal repaints through a shared scheduler. Demo or profiling surfaces can inspect the scheduler without reaching into private instances:
177
+
178
+ ```ts
179
+ import { getTerminalRenderSchedulerStats } from '@floegence/floeterm-terminal-web';
180
+
181
+ const stats = getTerminalRenderSchedulerStats();
182
+ console.log(stats.lastFrameRendered, stats.pending);
183
+ ```
184
+
185
+ Product code should continue to interact with `TerminalCore` or the managed controller.
186
+
187
+ ## Runtime Appearance Updates
137
188
 
138
- ## Runtime appearance updates
139
- Consumers that need to react to user preferences can update appearance without rebuilding the
140
- terminal session:
189
+ Consumers that need to respond to user preferences can update appearance without rebuilding the terminal session:
141
190
 
142
191
  ```ts
143
192
  import { getThemeColors } from '@floegence/floeterm-terminal-web';
@@ -1,12 +1,12 @@
1
- import { TerminalState, type Logger, type TerminalConfig, type TerminalCopySelectionResult, type TerminalCopySelectionSource, type TerminalDimensions, type TerminalEventHandlers, type TerminalAppearance, type TerminalLinkProvider, type TerminalVisualSuspendHandle, type TerminalVisualSuspendOptions } from '../types';
1
+ import { TerminalState, type Logger, type TerminalConfig, type TerminalCopySelectionResult, type TerminalCopySelectionSource, type TerminalDimensions, type TerminalEventHandlers, type TerminalAppearance, type TerminalLinkProvider, type TerminalRuntimeLineSnapshot, type TerminalTouchScrollRuntime, type TerminalVisualSuspendHandle, type TerminalVisualSuspendOptions } from '../types';
2
2
  export declare class TerminalCore {
3
3
  private container;
4
4
  private config;
5
5
  private terminal;
6
6
  private fitAddon;
7
7
  private needsFullRenderOnNextWrite;
8
- private demandRenderRaf;
9
8
  private demandRenderForceAll;
9
+ private readonly renderTask;
10
10
  private viewportHost;
11
11
  private renderHost;
12
12
  private resizeObserver;
@@ -51,6 +51,7 @@ export declare class TerminalCore {
51
51
  private readonly registeredLinkProviders;
52
52
  private readonly appliedLinkProviders;
53
53
  private readonly visualRenderState;
54
+ private static nextRenderTaskId;
54
55
  constructor(container: HTMLElement, config?: TerminalConfig, eventHandlers?: TerminalEventHandlers, logger?: Logger);
55
56
  initialize(): Promise<void>;
56
57
  private createTerminalInstance;
@@ -109,6 +110,13 @@ export declare class TerminalCore {
109
110
  cols: number;
110
111
  bufferLength: number;
111
112
  } | null;
113
+ readBufferLine(row: number, options?: {
114
+ trimRight?: boolean;
115
+ }): string;
116
+ readBufferLines(startRow: number, endRowInclusive: number, options?: {
117
+ trimRight?: boolean;
118
+ }): TerminalRuntimeLineSnapshot[];
119
+ getTouchScrollRuntime(): TerminalTouchScrollRuntime | null;
112
120
  findNext(term: string, options?: {
113
121
  caseSensitive?: boolean;
114
122
  wholeWord?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"TerminalCore.d.ts","sourceRoot":"","sources":["../../src/core/TerminalCore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TerminalCore.d.ts","sourceRoot":"","sources":["../../src/core/TerminalCore.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { filterXtermAutoResponses } from '../utils/xtermAutoResponseFilter';
2
2
  import { createConsoleLogger, noopLogger } from '../utils/logger';
3
3
  import { TerminalState, } from '../types';
4
4
  import { resolveTerminalInputElement, TerminalInputBridge } from './TerminalInputBridge';
5
+ import { terminalRenderScheduler } from './TerminalRenderScheduler';
5
6
  const TERMINAL_SEARCH_MAX_RESULTS = 5000;
6
7
  const PRESENTATION_SCALE_EPSILON = 0.0001;
7
8
  const GHOSTTY_DEFAULT_SCROLLBAR_RESERVE_PX = 15;
@@ -280,7 +281,6 @@ export class TerminalCore {
280
281
  this.terminal = null;
281
282
  this.fitAddon = null;
282
283
  this.needsFullRenderOnNextWrite = false;
283
- this.demandRenderRaf = null;
284
284
  this.demandRenderForceAll = false;
285
285
  this.viewportHost = null;
286
286
  this.renderHost = null;
@@ -338,6 +338,14 @@ export class TerminalCore {
338
338
  this.logicalFontSize = TerminalCore.normalizeFontSize(config?.fontSize);
339
339
  this.presentationScale = TerminalCore.normalizePresentationScale(config?.presentationScale);
340
340
  this.fixedDimensions = normalizeTerminalDimensions(config?.fixedDimensions);
341
+ this.renderTask = {
342
+ id: TerminalCore.nextRenderTaskId,
343
+ run: forceAll => {
344
+ this.demandRenderForceAll = false;
345
+ this.renderDemandFrame(forceAll);
346
+ },
347
+ };
348
+ TerminalCore.nextRenderTaskId += 1;
341
349
  }
342
350
  // initialize creates the ghostty-web terminal instance and binds addons.
343
351
  async initialize() {
@@ -1246,6 +1254,82 @@ export class TerminalCore {
1246
1254
  bufferLength: this.terminal.buffer.active.length
1247
1255
  };
1248
1256
  }
1257
+ readBufferLine(row, options = {}) {
1258
+ if (!this.terminal) {
1259
+ return '';
1260
+ }
1261
+ const normalizedRow = Math.floor(Number(row));
1262
+ if (!Number.isFinite(normalizedRow) || normalizedRow < 0) {
1263
+ return '';
1264
+ }
1265
+ try {
1266
+ const line = this.terminal.buffer?.active?.getLine?.(normalizedRow);
1267
+ const text = line?.translateToString?.(options.trimRight ?? false);
1268
+ return typeof text === 'string' ? text : '';
1269
+ }
1270
+ catch {
1271
+ return '';
1272
+ }
1273
+ }
1274
+ readBufferLines(startRow, endRowInclusive, options = {}) {
1275
+ const start = Math.floor(Number(startRow));
1276
+ const end = Math.floor(Number(endRowInclusive));
1277
+ if (!Number.isFinite(start) || !Number.isFinite(end) || end < start) {
1278
+ return [];
1279
+ }
1280
+ const lines = [];
1281
+ for (let row = Math.max(0, start); row <= end; row += 1) {
1282
+ const text = this.readBufferLine(row, options);
1283
+ if (text.length > 0) {
1284
+ lines.push({ row, text });
1285
+ }
1286
+ }
1287
+ return lines;
1288
+ }
1289
+ getTouchScrollRuntime() {
1290
+ const terminal = this.terminal;
1291
+ if (!terminal) {
1292
+ return null;
1293
+ }
1294
+ return {
1295
+ scrollLines: amount => {
1296
+ const normalizedAmount = Math.trunc(Number(amount));
1297
+ if (!Number.isFinite(normalizedAmount) || normalizedAmount === 0) {
1298
+ return false;
1299
+ }
1300
+ if (typeof terminal.scrollLines !== 'function') {
1301
+ return false;
1302
+ }
1303
+ terminal.scrollLines(normalizedAmount);
1304
+ this.requestDemandRender(false);
1305
+ return true;
1306
+ },
1307
+ getScrollbackLength: () => {
1308
+ if (typeof terminal.getScrollbackLength !== 'function') {
1309
+ return 0;
1310
+ }
1311
+ const length = Number(terminal.getScrollbackLength());
1312
+ return Number.isFinite(length) && length > 0 ? length : 0;
1313
+ },
1314
+ isAlternateScreen: () => {
1315
+ if (typeof terminal.isAlternateScreen !== 'function') {
1316
+ return false;
1317
+ }
1318
+ return Boolean(terminal.isAlternateScreen());
1319
+ },
1320
+ sendAlternateScreenInput: data => {
1321
+ const text = String(data ?? '');
1322
+ if (!text) {
1323
+ return;
1324
+ }
1325
+ if (typeof terminal.input === 'function') {
1326
+ terminal.input(text, true);
1327
+ return;
1328
+ }
1329
+ this.eventHandlers.onData?.(text);
1330
+ },
1331
+ };
1332
+ }
1249
1333
  findNext(term, options) {
1250
1334
  return this.findInternal(term, options, 1);
1251
1335
  }
@@ -2119,21 +2203,10 @@ export class TerminalCore {
2119
2203
  return;
2120
2204
  }
2121
2205
  this.demandRenderForceAll = this.demandRenderForceAll || forceAll;
2122
- if (this.demandRenderRaf !== null) {
2123
- return;
2124
- }
2125
- this.demandRenderRaf = requestAnimationFrame(() => {
2126
- this.demandRenderRaf = null;
2127
- const shouldForce = this.demandRenderForceAll;
2128
- this.demandRenderForceAll = false;
2129
- this.renderDemandFrame(shouldForce);
2130
- });
2206
+ terminalRenderScheduler.schedule(this.renderTask, this.demandRenderForceAll);
2131
2207
  }
2132
2208
  cancelDemandRender() {
2133
- if (this.demandRenderRaf !== null) {
2134
- cancelAnimationFrame(this.demandRenderRaf);
2135
- this.demandRenderRaf = null;
2136
- }
2209
+ terminalRenderScheduler.cancel(this.renderTask);
2137
2210
  this.demandRenderForceAll = false;
2138
2211
  this.stopGhosttyRenderLoop();
2139
2212
  }
@@ -2169,4 +2242,5 @@ export class TerminalCore {
2169
2242
  }
2170
2243
  }
2171
2244
  }
2245
+ TerminalCore.nextRenderTaskId = 1;
2172
2246
  //# sourceMappingURL=TerminalCore.js.map