@jrichman/ink 6.4.10 → 6.4.12

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.
Files changed (108) hide show
  1. package/build/components/App.d.ts +6 -0
  2. package/build/components/App.js +5 -0
  3. package/build/components/App.js.map +1 -1
  4. package/build/components/AppContext.d.ts +36 -1
  5. package/build/components/AppContext.js +7 -2
  6. package/build/components/AppContext.js.map +1 -1
  7. package/build/components/Box.d.ts +26 -2
  8. package/build/components/Box.js +3 -2
  9. package/build/components/Box.js.map +1 -1
  10. package/build/components/StaticRender.d.ts +8 -0
  11. package/build/components/StaticRender.js +11 -0
  12. package/build/components/StaticRender.js.map +1 -0
  13. package/build/debug-log.d.ts +2 -0
  14. package/build/debug-log.js +44 -0
  15. package/build/debug-log.js.map +1 -0
  16. package/build/dom.d.ts +37 -3
  17. package/build/dom.js +19 -3
  18. package/build/dom.js.map +1 -1
  19. package/build/index.d.ts +4 -1
  20. package/build/index.js +3 -1
  21. package/build/index.js.map +1 -1
  22. package/build/ink.d.ts +38 -2
  23. package/build/ink.js +223 -97
  24. package/build/ink.js.map +1 -1
  25. package/build/measure-element.d.ts +20 -1
  26. package/build/measure-element.js +201 -51
  27. package/build/measure-element.js.map +1 -1
  28. package/build/output.d.ts +195 -10
  29. package/build/output.js +494 -160
  30. package/build/output.js.map +1 -1
  31. package/build/reconciler.js +19 -3
  32. package/build/reconciler.js.map +1 -1
  33. package/build/render-background.js +1 -1
  34. package/build/render-background.js.map +1 -1
  35. package/build/render-cached.d.ts +17 -0
  36. package/build/render-cached.js +62 -0
  37. package/build/render-cached.js.map +1 -0
  38. package/build/render-container.d.ts +24 -0
  39. package/build/render-container.js +169 -0
  40. package/build/render-container.js.map +1 -0
  41. package/build/render-node-to-output.d.ts +15 -7
  42. package/build/render-node-to-output.js +123 -485
  43. package/build/render-node-to-output.js.map +1 -1
  44. package/build/render-screen-reader.d.ts +5 -0
  45. package/build/render-screen-reader.js +54 -0
  46. package/build/render-screen-reader.js.map +1 -0
  47. package/build/render-scrollbar.d.ts +22 -0
  48. package/build/render-scrollbar.js +77 -0
  49. package/build/render-scrollbar.js.map +1 -0
  50. package/build/render-sticky.d.ts +56 -0
  51. package/build/render-sticky.js +314 -0
  52. package/build/render-sticky.js.map +1 -0
  53. package/build/render-text-node.d.ts +24 -0
  54. package/build/render-text-node.js +133 -0
  55. package/build/render-text-node.js.map +1 -0
  56. package/build/render.d.ts +39 -0
  57. package/build/render.js +5 -0
  58. package/build/render.js.map +1 -1
  59. package/build/renderer.d.ts +10 -2
  60. package/build/renderer.js +103 -7
  61. package/build/renderer.js.map +1 -1
  62. package/build/replay.d.ts +60 -0
  63. package/build/replay.js +138 -0
  64. package/build/replay.js.map +1 -0
  65. package/build/scroll.js +20 -1
  66. package/build/scroll.js.map +1 -1
  67. package/build/selection.d.ts +9 -0
  68. package/build/selection.js +47 -0
  69. package/build/selection.js.map +1 -1
  70. package/build/serialization.d.ts +28 -0
  71. package/build/serialization.js +267 -0
  72. package/build/serialization.js.map +1 -0
  73. package/build/styles.d.ts +18 -0
  74. package/build/styles.js.map +1 -1
  75. package/build/terminal-buffer.d.ts +53 -0
  76. package/build/terminal-buffer.js +441 -0
  77. package/build/terminal-buffer.js.map +1 -0
  78. package/build/worker/animation-controller.d.ts +72 -0
  79. package/build/worker/animation-controller.js +128 -0
  80. package/build/worker/animation-controller.js.map +1 -0
  81. package/build/worker/ansi-utils.d.ts +16 -0
  82. package/build/worker/ansi-utils.js +40 -0
  83. package/build/worker/ansi-utils.js.map +1 -0
  84. package/build/worker/canvas.d.ts +47 -0
  85. package/build/worker/canvas.js +94 -0
  86. package/build/worker/canvas.js.map +1 -0
  87. package/build/worker/compositor.d.ts +33 -0
  88. package/build/worker/compositor.js +314 -0
  89. package/build/worker/compositor.js.map +1 -0
  90. package/build/worker/platform.d.ts +15 -0
  91. package/build/worker/platform.js +19 -0
  92. package/build/worker/platform.js.map +1 -0
  93. package/build/worker/render-worker.d.ts +112 -0
  94. package/build/worker/render-worker.js +936 -0
  95. package/build/worker/render-worker.js.map +1 -0
  96. package/build/worker/scene-manager.d.ts +26 -0
  97. package/build/worker/scene-manager.js +99 -0
  98. package/build/worker/scene-manager.js.map +1 -0
  99. package/build/worker/scroll-optimizer.d.ts +32 -0
  100. package/build/worker/scroll-optimizer.js +110 -0
  101. package/build/worker/scroll-optimizer.js.map +1 -0
  102. package/build/worker/terminal-writer.d.ts +116 -0
  103. package/build/worker/terminal-writer.js +722 -0
  104. package/build/worker/terminal-writer.js.map +1 -0
  105. package/build/worker/worker-entry.d.ts +6 -0
  106. package/build/worker/worker-entry.js +130 -0
  107. package/build/worker/worker-entry.js.map +1 -0
  108. package/package.json +3 -1
@@ -0,0 +1,441 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import process from 'node:process';
7
+ import { fork } from 'node:child_process';
8
+ import { Serializer } from './serialization.js';
9
+ import { TerminalBufferWorker } from './worker/render-worker.js';
10
+ import { linesEqual } from './worker/terminal-writer.js';
11
+ import { flattenRegion, regionLayoutProperties, copyRegionProperty, } from './output.js';
12
+ const debugEdits = false;
13
+ export default class TerminalBuffer {
14
+ lines = [];
15
+ serializer = new Serializer();
16
+ worker;
17
+ workerInstance;
18
+ resizeListener;
19
+ stdout;
20
+ // Track previous state of all regions by ID
21
+ lastRegions = new Map();
22
+ lastCursorPosition;
23
+ lastOptions;
24
+ optionsChanged = false;
25
+ columns;
26
+ rows;
27
+ constructor(columns, rows, options) {
28
+ this.lastOptions = {
29
+ isAlternateBufferEnabled: options?.isAlternateBufferEnabled,
30
+ stickyHeadersInBackbuffer: options?.stickyHeadersInBackbuffer,
31
+ animatedScroll: options?.animatedScroll,
32
+ animationInterval: options?.animationInterval,
33
+ backbufferUpdateDelay: options?.backbufferUpdateDelay,
34
+ maxScrollbackLength: options?.maxScrollbackLength,
35
+ forceScrollToBottomOnBackbufferRefresh: options?.forceScrollToBottomOnBackbufferRefresh,
36
+ };
37
+ this.columns = columns;
38
+ this.rows = rows;
39
+ this.stdout = options?.stdout ?? process.stdout;
40
+ if (options?.renderInProcess) {
41
+ this.workerInstance = new TerminalBufferWorker(columns, rows, {
42
+ debugRainbowEnabled: options?.debugRainbowEnabled,
43
+ stdout: this.stdout,
44
+ isAlternateBufferEnabled: options?.isAlternateBufferEnabled,
45
+ stickyHeadersInBackbuffer: options?.stickyHeadersInBackbuffer,
46
+ animatedScroll: options?.animatedScroll,
47
+ animationInterval: options?.animationInterval,
48
+ backbufferUpdateDelay: options?.backbufferUpdateDelay,
49
+ maxScrollbackLength: options?.maxScrollbackLength,
50
+ forceScrollToBottomOnBackbufferRefresh: options?.forceScrollToBottomOnBackbufferRefresh,
51
+ });
52
+ void this.workerInstance.render();
53
+ }
54
+ else {
55
+ const workerUrl = new URL('worker/worker-entry.js', import.meta.url);
56
+ this.worker = fork(workerUrl, {
57
+ env: {
58
+ ...process.env,
59
+ // eslint-disable-next-line @typescript-eslint/naming-convention
60
+ INK_WORKER: 'true',
61
+ },
62
+ });
63
+ this.worker.on('error', error => {
64
+ console.error('Render worker error:', error);
65
+ });
66
+ this.sendToWorker({
67
+ type: 'init',
68
+ columns,
69
+ rows,
70
+ debugRainbowEnabled: options?.debugRainbowEnabled,
71
+ isAlternateBufferEnabled: options?.isAlternateBufferEnabled,
72
+ stickyHeadersInBackbuffer: options?.stickyHeadersInBackbuffer,
73
+ animatedScroll: options?.animatedScroll,
74
+ animationInterval: options?.animationInterval,
75
+ backbufferUpdateDelay: options?.backbufferUpdateDelay,
76
+ maxScrollbackLength: options?.maxScrollbackLength,
77
+ forceScrollToBottomOnBackbufferRefresh: options?.forceScrollToBottomOnBackbufferRefresh,
78
+ }, 'Failed to send init message to worker:');
79
+ }
80
+ this.resizeListener = () => {
81
+ if (this.stdout.columns && this.stdout.rows) {
82
+ this.resize(this.stdout.columns, this.stdout.rows);
83
+ }
84
+ };
85
+ this.stdout.on('resize', this.resizeListener);
86
+ }
87
+ resize(columns, rows) {
88
+ if (this.columns === columns && this.rows === rows) {
89
+ return;
90
+ }
91
+ this.columns = columns;
92
+ this.rows = rows;
93
+ if (this.workerInstance) {
94
+ this.workerInstance.resize(columns, rows);
95
+ }
96
+ else {
97
+ this.sendToWorker({
98
+ type: 'resize',
99
+ columns,
100
+ rows,
101
+ }, 'Failed to send resize message to worker:');
102
+ }
103
+ }
104
+ updateOptions(options) {
105
+ const keys = [
106
+ 'isAlternateBufferEnabled',
107
+ 'stickyHeadersInBackbuffer',
108
+ 'animatedScroll',
109
+ 'animationInterval',
110
+ 'backbufferUpdateDelay',
111
+ 'maxScrollbackLength',
112
+ 'forceScrollToBottomOnBackbufferRefresh',
113
+ ];
114
+ for (const key of keys) {
115
+ if (options[key] !== this.lastOptions?.[key]) {
116
+ this.optionsChanged = true;
117
+ break;
118
+ }
119
+ }
120
+ this.lastOptions = { ...options };
121
+ if (this.workerInstance) {
122
+ this.workerInstance.updateOptions(options);
123
+ }
124
+ else {
125
+ this.sendToWorker({
126
+ type: 'updateOptions',
127
+ options,
128
+ }, 'Failed to send updateOptions message to worker:');
129
+ }
130
+ }
131
+ startRecording(filename) {
132
+ if (this.workerInstance) {
133
+ this.workerInstance.startRecording(filename);
134
+ }
135
+ else {
136
+ this.sendToWorker({
137
+ type: 'startRecording',
138
+ filename,
139
+ }, 'Failed to send startRecording message to worker:');
140
+ }
141
+ }
142
+ stopRecording() {
143
+ if (this.workerInstance) {
144
+ this.workerInstance.stopRecording();
145
+ }
146
+ else {
147
+ this.sendToWorker({
148
+ type: 'stopRecording',
149
+ }, 'Failed to send stopRecording message to worker:');
150
+ }
151
+ }
152
+ dumpCurrentFrame(filename) {
153
+ if (this.workerInstance) {
154
+ this.workerInstance.dumpCurrentFrame(filename);
155
+ }
156
+ else {
157
+ this.sendToWorker({
158
+ type: 'dumpCurrentFrame',
159
+ filename,
160
+ }, 'Failed to send dumpCurrentFrame message to worker:');
161
+ }
162
+ }
163
+ update(_start, _end, root, cursorPosition) {
164
+ this.lines = flattenRegion(root, {
165
+ skipScrollbars: true,
166
+ skipStickyHeaders: true,
167
+ });
168
+ const currentRegionsMap = new Map();
169
+ const nodeIdToElement = new Map();
170
+ const updates = [];
171
+ // Traverse tree to collect all current regions and build structure
172
+ const buildTree = (r) => {
173
+ currentRegionsMap.set(r.id, r);
174
+ // Populate nodeIdToElement map
175
+ if (r.nodeId !== undefined && r.node !== undefined) {
176
+ nodeIdToElement.set(r.nodeId, r.node);
177
+ }
178
+ // Diff this region
179
+ const update = this.diffRegion(r, nodeIdToElement);
180
+ if (update) {
181
+ updates.push(update);
182
+ }
183
+ return {
184
+ id: r.id,
185
+ children: r.children.map(child => buildTree(child)),
186
+ };
187
+ };
188
+ const tree = buildTree(root);
189
+ // Update local state to current frame
190
+ this.lastRegions = currentRegionsMap;
191
+ const cursorChanged = cursorPosition !== this.lastCursorPosition &&
192
+ (!cursorPosition ||
193
+ !this.lastCursorPosition ||
194
+ cursorPosition.row !== this.lastCursorPosition.row ||
195
+ cursorPosition.col !== this.lastCursorPosition.col);
196
+ this.lastCursorPosition = cursorPosition;
197
+ if (updates.length > 0 || cursorChanged || this.optionsChanged) {
198
+ this.optionsChanged = false;
199
+ this.sendEdits(tree, updates, cursorPosition);
200
+ return true;
201
+ }
202
+ return false;
203
+ }
204
+ async render() {
205
+ if (this.workerInstance) {
206
+ await this.workerInstance.render();
207
+ }
208
+ else if (this.worker?.connected) {
209
+ try {
210
+ this.worker.send({
211
+ type: 'render',
212
+ });
213
+ }
214
+ catch (error) {
215
+ console.error('Failed to send render message to worker:', error);
216
+ }
217
+ }
218
+ }
219
+ async fullRender() {
220
+ if (this.workerInstance) {
221
+ await this.workerInstance.fullRender();
222
+ }
223
+ else if (this.worker?.connected) {
224
+ try {
225
+ this.worker.send({
226
+ type: 'fullRender',
227
+ });
228
+ }
229
+ catch (error) {
230
+ console.error('Failed to send fullRender message to worker:', error);
231
+ }
232
+ }
233
+ }
234
+ done() {
235
+ if (this.workerInstance) {
236
+ this.workerInstance.done();
237
+ }
238
+ else if (this.worker?.connected) {
239
+ try {
240
+ this.worker.send({
241
+ type: 'done',
242
+ });
243
+ }
244
+ catch {
245
+ // Silently fail on exit errors as the worker might already be gone
246
+ }
247
+ }
248
+ }
249
+ async getLinesUpdated() {
250
+ if (this.workerInstance) {
251
+ return this.workerInstance.getLinesUpdated();
252
+ }
253
+ if (!this.worker?.connected) {
254
+ return 0;
255
+ }
256
+ return new Promise(resolve => {
257
+ const handler = (message) => {
258
+ if (message.type === 'linesUpdated') {
259
+ this.worker?.off('message', handler);
260
+ resolve(message.count);
261
+ }
262
+ };
263
+ this.worker?.on('message', handler);
264
+ try {
265
+ this.worker?.send({ type: 'getLinesUpdated' });
266
+ }
267
+ catch (error) {
268
+ this.worker?.off('message', handler);
269
+ console.error('Failed to send getLinesUpdated message to worker:', error);
270
+ resolve(0);
271
+ }
272
+ });
273
+ }
274
+ resetLinesUpdated() {
275
+ if (this.workerInstance) {
276
+ this.workerInstance.resetLinesUpdated();
277
+ }
278
+ else if (this.worker?.connected) {
279
+ try {
280
+ this.worker.send({ type: 'resetLinesUpdated' });
281
+ }
282
+ catch (error) {
283
+ console.error('Failed to send resetLinesUpdated message to worker:', error);
284
+ }
285
+ }
286
+ }
287
+ destroy() {
288
+ if (this.worker) {
289
+ this.worker.kill();
290
+ }
291
+ if (this.resizeListener) {
292
+ this.stdout.off('resize', this.resizeListener);
293
+ }
294
+ }
295
+ sendToWorker(message, errorMessage) {
296
+ if (this.worker?.connected) {
297
+ try {
298
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
299
+ this.worker.send(message);
300
+ }
301
+ catch (error) {
302
+ console.error(errorMessage, error);
303
+ }
304
+ }
305
+ }
306
+ diffRegion(current, nodeIdToElement) {
307
+ const last = this.lastRegions.get(current.id);
308
+ const update = { id: current.id };
309
+ let hasChanges = false;
310
+ if (!last) {
311
+ // New region, send everything
312
+ hasChanges = true;
313
+ for (const key of regionLayoutProperties) {
314
+ copyRegionProperty(update, current, key);
315
+ }
316
+ update.stickyHeaders = current.stickyHeaders;
317
+ // Send all lines
318
+ const serialized = this.serializer.serialize(current.lines);
319
+ update.lines = {
320
+ updates: [
321
+ {
322
+ start: 0,
323
+ end: current.lines.length,
324
+ data: serialized,
325
+ },
326
+ ],
327
+ totalLength: current.lines.length,
328
+ };
329
+ return update;
330
+ }
331
+ // Check properties
332
+ for (const key of regionLayoutProperties) {
333
+ if (current[key] !== last[key]) {
334
+ copyRegionProperty(update, current, key);
335
+ hasChanges = true;
336
+ }
337
+ }
338
+ // Deep compare sticky headers? For now assuming reference change or simple length change is enough,
339
+ // or we can rely on the fact they are rebuilt every frame.
340
+ // Let's just resend if length differs or assume they might change.
341
+ // To be safe and simple: always send sticky headers if they exist or existed.
342
+ if (current.stickyHeaders !== last.stickyHeaders ||
343
+ current.stickyHeaders.length > 0 ||
344
+ last.stickyHeaders.length > 0) {
345
+ update.stickyHeaders = current.stickyHeaders;
346
+ hasChanges = true;
347
+ }
348
+ // Diff lines
349
+ const lineUpdates = this.diffLines(last.lines, current.lines);
350
+ if (lineUpdates.length > 0 || last.lines.length !== current.lines.length) {
351
+ hasChanges = true;
352
+ update.lines = {
353
+ updates: lineUpdates,
354
+ totalLength: current.lines.length,
355
+ };
356
+ if (current.stableScrollback && current.nodeId !== undefined) {
357
+ const element = nodeIdToElement.get(current.nodeId);
358
+ if (element) {
359
+ const scrollTop = current.scrollTop ?? 0;
360
+ for (const chunk of lineUpdates) {
361
+ if (chunk.start < scrollTop) {
362
+ element.internalIsScrollbackDirty = true;
363
+ break;
364
+ }
365
+ }
366
+ // Also check if lines were removed from the end of the content but still within the scrollback
367
+ if (!element.internalIsScrollbackDirty &&
368
+ current.lines.length < last.lines.length &&
369
+ current.lines.length < scrollTop) {
370
+ element.internalIsScrollbackDirty = true;
371
+ }
372
+ }
373
+ }
374
+ }
375
+ return hasChanges ? update : undefined;
376
+ }
377
+ diffLines(oldLines, newLines) {
378
+ const updates = [];
379
+ const limit = Math.max(oldLines.length, newLines.length);
380
+ let chunkStart = -1;
381
+ let chunkLines = [];
382
+ let chunkSource = [];
383
+ for (let i = 0; i < limit; i++) {
384
+ const newLine = newLines[i];
385
+ const oldLine = oldLines[i];
386
+ const areEqual = linesEqual(oldLine, newLine);
387
+ if (areEqual) {
388
+ if (chunkStart !== -1) {
389
+ updates.push({
390
+ start: chunkStart,
391
+ end: chunkStart + chunkLines.length,
392
+ data: this.serializer.serialize(chunkLines),
393
+ source: debugEdits
394
+ ? this.serializer.serialize(chunkSource)
395
+ : undefined,
396
+ });
397
+ chunkStart = -1;
398
+ chunkLines = [];
399
+ chunkSource = [];
400
+ }
401
+ }
402
+ else {
403
+ if (chunkStart === -1) {
404
+ chunkStart = i;
405
+ }
406
+ chunkLines.push(newLine ?? []);
407
+ if (debugEdits) {
408
+ chunkSource.push(oldLine ?? []);
409
+ }
410
+ }
411
+ }
412
+ if (chunkStart !== -1) {
413
+ updates.push({
414
+ start: chunkStart,
415
+ end: chunkStart + chunkLines.length,
416
+ data: this.serializer.serialize(chunkLines),
417
+ source: debugEdits ? this.serializer.serialize(chunkSource) : undefined,
418
+ });
419
+ }
420
+ return updates;
421
+ }
422
+ sendEdits(tree, updates, cursorPosition) {
423
+ if (this.workerInstance) {
424
+ this.workerInstance.update(tree, updates, cursorPosition);
425
+ }
426
+ else if (this.worker?.connected) {
427
+ try {
428
+ this.worker.send({
429
+ type: 'edits',
430
+ tree,
431
+ updates,
432
+ cursorPosition,
433
+ });
434
+ }
435
+ catch (error) {
436
+ console.error('Failed to send edits to worker:', error);
437
+ }
438
+ }
439
+ }
440
+ }
441
+ //# sourceMappingURL=terminal-buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-buffer.js","sourceRoot":"","sources":["../src/terminal-buffer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { type Region } from '../output.js';
7
+ export type AnimationOptions = {
8
+ interval: number;
9
+ onTick: () => void;
10
+ };
11
+ /**
12
+ * Manages scroll animations.
13
+ * Interpolates between current scroll position and target scroll position.
14
+ */
15
+ export declare class AnimationController {
16
+ private readonly options;
17
+ private readonly targetScrollTops;
18
+ private intervalId?;
19
+ private idleResolvers;
20
+ constructor(options: AnimationOptions);
21
+ /**
22
+ * Updates the animation interval.
23
+ */
24
+ updateInterval(interval: number): void;
25
+ /**
26
+ * Returns the internal target scroll tops map.
27
+ */
28
+ get allTargetScrollTops(): ReadonlyMap<string | number, number>;
29
+ /**
30
+ * Returns true if the animation loop is running.
31
+ */
32
+ get isRunning(): boolean;
33
+ /**
34
+ * Returns a promise that resolves when the animation loop stops.
35
+ */
36
+ waitForIdle(): Promise<void>;
37
+ /**
38
+ * Sets the target scroll position for a region.
39
+ */
40
+ setTargetScrollTop(regionId: string | number, scrollTop: number): void;
41
+ /**
42
+ * Returns the target scroll top for a region.
43
+ */
44
+ getTargetScrollTop(regionId: string | number): number | undefined;
45
+ /**
46
+ * Removes the target scroll position for a region.
47
+ */
48
+ deleteTargetScrollTop(regionId: string | number): void;
49
+ /**
50
+ * Starts the animation loop if not already running.
51
+ */
52
+ start(): void;
53
+ /**
54
+ * Stops the animation loop.
55
+ */
56
+ stop(): void;
57
+ /**
58
+ * Interrupts animations and jumps all regions to their targets.
59
+ */
60
+ jumpToTargets(regions: Map<string | number, Region>): void;
61
+ /**
62
+ * Updates regions based on their targets. Returns true if any region scrolled.
63
+ */
64
+ updateRegions(regions: Map<string | number, Region>): {
65
+ hasScrolled: boolean;
66
+ canScrollMore: boolean;
67
+ };
68
+ /**
69
+ * Processes one frame of animation.
70
+ */
71
+ private tick;
72
+ }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Manages scroll animations.
8
+ * Interpolates between current scroll position and target scroll position.
9
+ */
10
+ export class AnimationController {
11
+ options;
12
+ targetScrollTops = new Map();
13
+ intervalId;
14
+ idleResolvers = [];
15
+ constructor(options) {
16
+ this.options = options;
17
+ }
18
+ /**
19
+ * Updates the animation interval.
20
+ */
21
+ updateInterval(interval) {
22
+ this.options.interval = interval;
23
+ }
24
+ /**
25
+ * Returns the internal target scroll tops map.
26
+ */
27
+ get allTargetScrollTops() {
28
+ return this.targetScrollTops;
29
+ }
30
+ /**
31
+ * Returns true if the animation loop is running.
32
+ */
33
+ get isRunning() {
34
+ return this.intervalId !== undefined;
35
+ }
36
+ /**
37
+ * Returns a promise that resolves when the animation loop stops.
38
+ */
39
+ async waitForIdle() {
40
+ if (!this.isRunning) {
41
+ return;
42
+ }
43
+ return new Promise(resolve => {
44
+ this.idleResolvers.push(resolve);
45
+ });
46
+ }
47
+ /**
48
+ * Sets the target scroll position for a region.
49
+ */
50
+ setTargetScrollTop(regionId, scrollTop) {
51
+ this.targetScrollTops.set(regionId, scrollTop);
52
+ }
53
+ /**
54
+ * Returns the target scroll top for a region.
55
+ */
56
+ getTargetScrollTop(regionId) {
57
+ return this.targetScrollTops.get(regionId);
58
+ }
59
+ /**
60
+ * Removes the target scroll position for a region.
61
+ */
62
+ deleteTargetScrollTop(regionId) {
63
+ this.targetScrollTops.delete(regionId);
64
+ }
65
+ /**
66
+ * Starts the animation loop if not already running.
67
+ */
68
+ start() {
69
+ if (this.intervalId) {
70
+ return;
71
+ }
72
+ this.intervalId = setInterval(() => {
73
+ this.tick();
74
+ }, this.options.interval);
75
+ }
76
+ /**
77
+ * Stops the animation loop.
78
+ */
79
+ stop() {
80
+ if (this.intervalId) {
81
+ clearInterval(this.intervalId);
82
+ this.intervalId = undefined;
83
+ }
84
+ for (const resolve of this.idleResolvers) {
85
+ resolve();
86
+ }
87
+ this.idleResolvers = [];
88
+ }
89
+ /**
90
+ * Interrupts animations and jumps all regions to their targets.
91
+ */
92
+ jumpToTargets(regions) {
93
+ for (const [id, target] of this.targetScrollTops) {
94
+ const region = regions.get(id);
95
+ if (region) {
96
+ region.scrollTop = target;
97
+ }
98
+ }
99
+ this.stop();
100
+ }
101
+ /**
102
+ * Updates regions based on their targets. Returns true if any region scrolled.
103
+ */
104
+ updateRegions(regions) {
105
+ let hasScrolled = false;
106
+ let canScrollMore = false;
107
+ for (const region of regions.values()) {
108
+ const target = this.targetScrollTops.get(region.id);
109
+ if (target === undefined) {
110
+ continue;
111
+ }
112
+ const current = region.scrollTop ?? 0;
113
+ if (current !== target) {
114
+ region.scrollTop = current < target ? current + 1 : current - 1;
115
+ hasScrolled = true;
116
+ canScrollMore = true;
117
+ }
118
+ }
119
+ return { hasScrolled, canScrollMore };
120
+ }
121
+ /**
122
+ * Processes one frame of animation.
123
+ */
124
+ tick() {
125
+ this.options.onTick();
126
+ }
127
+ }
128
+ //# sourceMappingURL=animation-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animation-controller.js","sourceRoot":"","sources":["../../src/worker/animation-controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export declare const enterSynchronizedOutput = "\u001B[?2026h";
7
+ export declare const exitSynchronizedOutput = "\u001B[?2026l";
8
+ export declare const resetScrollRegion = "\u001B[r";
9
+ export declare const ris = "\u001Bc";
10
+ export declare const clearScrollbackStandard = "\u001B[3J";
11
+ export declare const homeEraseDown = "\u001B[H\u001B[J";
12
+ export declare const getMoveCursorDownCode: (skippedLines: number) => string;
13
+ export declare const getMoveCursorUpCode: (skippedLines: number) => string;
14
+ export declare const getDeleteLinesCode: (count: number) => string;
15
+ export declare const getInsertLinesCode: (count: number) => string;
16
+ export declare const getSetScrollRegionCode: (top: number, bottom: number) => string;