@opentui/core 0.2.16 → 0.3.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/index.js CHANGED
@@ -26,7 +26,6 @@ import {
26
26
  InputRenderableEvents,
27
27
  LineNumberRenderable,
28
28
  MarkdownRenderable,
29
- NativeSpanFeed,
30
29
  PROTANOPIA_COMP_MATRIX,
31
30
  PROTANOPIA_SIM_MATRIX,
32
31
  RainbowTextEffect,
@@ -72,7 +71,7 @@ import {
72
71
  resolveCoreSlot,
73
72
  setupAudio,
74
73
  vstyles
75
- } from "./index-hzcw4q21.js";
74
+ } from "./index-sq86yyfz.js";
76
75
  import {
77
76
  ASCIIFontSelectionHelper,
78
77
  ATTRIBUTE_BASE_BITS,
@@ -104,6 +103,7 @@ import {
104
103
  MouseButton,
105
104
  MouseEvent,
106
105
  MouseParser,
106
+ NativeSpanFeed,
107
107
  OptimizedBuffer,
108
108
  PasteEvent,
109
109
  RGBA,
@@ -246,7 +246,7 @@ import {
246
246
  white,
247
247
  wrapWithDelegates,
248
248
  yellow
249
- } from "./index-qfwqv8y3.js";
249
+ } from "./index-081xws23.js";
250
250
  export {
251
251
  yellow,
252
252
  wrapWithDelegates,
@@ -494,5 +494,5 @@ export {
494
494
  ACHROMATOPSIA_MATRIX
495
495
  };
496
496
 
497
- //# debugId=3B163E1BF0509BD764756E2164756E21
497
+ //# debugId=893EFD9F8A7D3C4264756E2164756E21
498
498
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "3B163E1BF0509BD764756E2164756E21",
7
+ "debugId": "893EFD9F8A7D3C4264756E2164756E21",
8
8
  "names": []
9
9
  }
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "type": "module",
7
- "version": "0.2.16",
7
+ "version": "0.3.0",
8
8
  "description": "OpenTUI is a TypeScript library on a native Zig core for building terminal user interfaces (TUIs)",
9
9
  "license": "MIT",
10
10
  "repository": {
@@ -69,11 +69,11 @@
69
69
  "web-tree-sitter": "0.25.10"
70
70
  },
71
71
  "optionalDependencies": {
72
- "@opentui/core-darwin-x64": "0.2.16",
73
- "@opentui/core-darwin-arm64": "0.2.16",
74
- "@opentui/core-linux-x64": "0.2.16",
75
- "@opentui/core-linux-arm64": "0.2.16",
76
- "@opentui/core-win32-x64": "0.2.16",
77
- "@opentui/core-win32-arm64": "0.2.16"
72
+ "@opentui/core-darwin-x64": "0.3.0",
73
+ "@opentui/core-darwin-arm64": "0.3.0",
74
+ "@opentui/core-linux-x64": "0.3.0",
75
+ "@opentui/core-linux-arm64": "0.3.0",
76
+ "@opentui/core-win32-x64": "0.3.0",
77
+ "@opentui/core-win32-arm64": "0.3.0"
78
78
  }
79
79
  }
package/renderer.d.ts CHANGED
@@ -3,7 +3,7 @@ import { DebugOverlayCorner, type CursorStyleOptions, type MousePointerStyle, ty
3
3
  import { RGBA, type ColorInput } from "./lib/RGBA.js";
4
4
  import type { Pointer } from "./platform/ffi.js";
5
5
  import { OptimizedBuffer } from "./buffer.js";
6
- import { type NativeRenderStats, type RenderLib } from "./zig.js";
6
+ import { type NativeBufferedOutput, type NativeRenderStats } from "./zig.js";
7
7
  import { TerminalConsole, type ConsoleOptions } from "./console.js";
8
8
  import { type MouseEventType, type RawMouseEvent, type ScrollInfo } from "./lib/parse.mouse.js";
9
9
  import { Selection } from "./lib/selection.js";
@@ -16,8 +16,10 @@ import { type Clock } from "./lib/clock.js";
16
16
  export interface CliRendererConfig {
17
17
  stdin?: NodeJS.ReadStream;
18
18
  stdout?: NodeJS.WriteStream;
19
+ width?: number;
20
+ height?: number;
19
21
  remote?: boolean;
20
- testing?: boolean;
22
+ bufferedOutput?: NativeBufferedOutput;
21
23
  exitOnCtrlC?: boolean;
22
24
  exitSignals?: NodeJS.Signals[];
23
25
  clearOnShutdown?: boolean;
@@ -165,6 +167,11 @@ export declare enum MouseButton {
165
167
  WHEEL_UP = 4,
166
168
  WHEEL_DOWN = 5
167
169
  }
170
+ /**
171
+ * Create a CLI renderer and run its async terminal setup. The constructor
172
+ * owns all stream and backend decisions; this factory only layers on the
173
+ * `--delay-start` flag and the `await setupTerminal()` convenience.
174
+ */
168
175
  export declare function createCliRenderer(config?: CliRendererConfig): Promise<CliRenderer>;
169
176
  export declare enum CliRenderEvents {
170
177
  RESIZE = "resize",
@@ -203,6 +210,7 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
203
210
  private _destroyPending;
204
211
  private _destroyFinalized;
205
212
  private _destroyCleanupPrepared;
213
+ private _streamLeaseAcquired;
206
214
  nextRenderBuffer: OptimizedBuffer;
207
215
  currentRenderBuffer: OptimizedBuffer;
208
216
  private _isRunning;
@@ -317,8 +325,37 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
317
325
  private dumpOutputCache;
318
326
  private exitHandler;
319
327
  private warningHandler;
328
+ private readonly _usesProcessStdout;
329
+ private _feed;
330
+ private _detachFeed;
331
+ private _detachFeedError;
332
+ private feedIdleRenderScheduled;
320
333
  get controlState(): RendererControlState;
321
- constructor(lib: RenderLib, rendererPtr: Pointer, stdin: NodeJS.ReadStream, stdout: NodeJS.WriteStream, width: number, height: number, config?: CliRendererConfig);
334
+ /**
335
+ * Construct a renderer over the given streams.
336
+ *
337
+ * If `stdout` is not `process.stdout`, a `NativeSpanFeed` is allocated
338
+ * internally and rendered bytes are piped through it to `stdout` unless
339
+ * `bufferedOutput: "memory"` is set. Prefer `createCliRenderer` for the async
340
+ * `setupTerminal` convenience.
341
+ *
342
+ * Construction side effects (observable before the constructor returns):
343
+ * - Acquires exclusive ownership of the given stdin/stdout streams
344
+ * - Allocates a `NativeSpanFeed` (for non-process stdout unless bufferedOutput is "memory")
345
+ * - Calls `lib.createRenderer` → native Zig allocation
346
+ * - Registers in the process-wide `rendererTracker`
347
+ * - Adds `process.on(...)` listeners for SIGWINCH (process.stdout only),
348
+ * "warning", "uncaughtException", "unhandledRejection", "beforeExit",
349
+ * plus the configured `exitSignals`
350
+ * - Replaces `global.requestAnimationFrame` with the renderer's impl
351
+ * - When `setupTerminal()` is called, it will put `stdin` in raw mode and
352
+ * call `stdin.resume()`
353
+ *
354
+ * Some late constructor side effects are not rolled back if construction
355
+ * throws partway; production callers should use `createCliRenderer`, which
356
+ * wraps `setupTerminal()` in a try/catch that calls `destroy()` on failure.
357
+ */
358
+ constructor(stdin: NodeJS.ReadStream, stdout: NodeJS.WriteStream, width: number, height: number, config?: CliRendererConfig);
322
359
  private addExitListeners;
323
360
  private removeExitListeners;
324
361
  get isDestroyed(): boolean;
@@ -339,6 +376,7 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
339
376
  get widthMethod(): WidthMethod;
340
377
  get frameId(): number;
341
378
  private writeOut;
379
+ private scheduleRenderAfterFeedIdle;
342
380
  requestRender(): void;
343
381
  private activateFrame;
344
382
  get consoleMode(): ConsoleMode;
@@ -452,6 +490,15 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
452
490
  private handleResize;
453
491
  private queryPixelResolution;
454
492
  private processResize;
493
+ /**
494
+ * Programmatically resize the renderer to new dimensions.
495
+ *
496
+ * Use this for externally-driven resize events — for example, an SSH
497
+ * `window-change` signal or a test harness simulating a terminal resize.
498
+ * When the renderer is attached to `process.stdout`, `SIGWINCH` is handled
499
+ * automatically and callers do not need this method.
500
+ */
501
+ resize(width: number, height: number): void;
455
502
  setBackgroundColor(color: ColorInput): void;
456
503
  toggleDebugOverlay(): void;
457
504
  configureDebugOverlay(options: {
@@ -470,7 +517,7 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
470
517
  isOsc52Supported(): boolean;
471
518
  dumpHitGrid(): void;
472
519
  dumpBuffers(timestamp?: number): void;
473
- dumpStdoutBuffer(timestamp?: number): void;
520
+ dumpOutputBuffer(timestamp?: number): void;
474
521
  static setCursorPosition(renderer: CliRenderer, x: number, y: number, visible?: boolean): void;
475
522
  static setCursorStyle(renderer: CliRenderer, options: CursorStyleOptions): void;
476
523
  static setCursorColor(renderer: CliRenderer, color: RGBA): void;
@@ -1,13 +1,13 @@
1
1
  // @bun
2
2
  import {
3
3
  ensureRuntimePluginSupport
4
- } from "./index-t1vzaxv4.js";
4
+ } from "./index-dhbwkghw.js";
5
5
  import {
6
6
  createRuntimePlugin,
7
7
  runtimeModuleIdForSpecifier
8
- } from "./index-qe67qr6s.js";
9
- import"./index-hzcw4q21.js";
10
- import"./index-qfwqv8y3.js";
8
+ } from "./index-qwem5zxy.js";
9
+ import"./index-sq86yyfz.js";
10
+ import"./index-081xws23.js";
11
11
  export {
12
12
  runtimeModuleIdForSpecifier,
13
13
  ensureRuntimePluginSupport,
@@ -1,13 +1,13 @@
1
1
  // @bun
2
2
  import {
3
3
  ensureRuntimePluginSupport
4
- } from "./index-t1vzaxv4.js";
4
+ } from "./index-dhbwkghw.js";
5
5
  import {
6
6
  createRuntimePlugin,
7
7
  runtimeModuleIdForSpecifier
8
- } from "./index-qe67qr6s.js";
9
- import"./index-hzcw4q21.js";
10
- import"./index-qfwqv8y3.js";
8
+ } from "./index-qwem5zxy.js";
9
+ import"./index-sq86yyfz.js";
10
+ import"./index-081xws23.js";
11
11
  // src/runtime-plugin-support.ts
12
12
  ensureRuntimePluginSupport();
13
13
  export {
package/runtime-plugin.js CHANGED
@@ -3,9 +3,9 @@ import {
3
3
  createRuntimePlugin,
4
4
  isCoreRuntimeModuleSpecifier,
5
5
  runtimeModuleIdForSpecifier
6
- } from "./index-qe67qr6s.js";
7
- import"./index-hzcw4q21.js";
8
- import"./index-qfwqv8y3.js";
6
+ } from "./index-qwem5zxy.js";
7
+ import"./index-sq86yyfz.js";
8
+ import"./index-081xws23.js";
9
9
  export {
10
10
  runtimeModuleIdForSpecifier,
11
11
  isCoreRuntimeModuleSpecifier,
@@ -1,5 +1,5 @@
1
1
  import { CliRenderer, type CliRendererConfig } from "../renderer.js";
2
- import { type NativeRenderStats } from "../zig.js";
2
+ import type { NativeRenderStats } from "../zig.js";
3
3
  import { createMockKeys } from "./mock-keys.js";
4
4
  import { createMockMouse } from "./mock-mouse.js";
5
5
  import type { CapturedFrame } from "../types.js";
@@ -9,8 +9,7 @@ export interface TestRendererOptions extends CliRendererConfig {
9
9
  kittyKeyboard?: boolean;
10
10
  otherModifiersMode?: boolean;
11
11
  }
12
- export interface TestRenderer extends CliRenderer {
13
- }
12
+ export type TestRenderer = CliRenderer;
14
13
  export type MockInput = ReturnType<typeof createMockKeys>;
15
14
  export type MockMouse = ReturnType<typeof createMockMouse>;
16
15
  export interface TestFlushOptions {
@@ -0,0 +1,12 @@
1
+ import { Writable } from "stream";
2
+ export declare class TestWriteStream extends Writable {
3
+ readonly isTTY = true;
4
+ readonly columns: number;
5
+ readonly rows: number;
6
+ constructor(columns?: number, rows?: number);
7
+ _write(_chunk: any, _encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
8
+ getColorDepth(): number;
9
+ }
10
+ export type TestStdout = TestWriteStream & NodeJS.WriteStream;
11
+ export declare function createTestStdin(): NodeJS.ReadStream;
12
+ export declare function createTestStdout(columns?: number, rows?: number): NodeJS.WriteStream;
package/testing.js CHANGED
@@ -2,13 +2,8 @@
2
2
  import {
3
3
  ANSI,
4
4
  CliRenderer,
5
- TreeSitterClient,
6
- calculateRenderGeometry,
7
- resolveRenderLib
8
- } from "./index-qfwqv8y3.js";
9
-
10
- // src/testing/test-renderer.ts
11
- import { Readable, Writable } from "stream";
5
+ TreeSitterClient
6
+ } from "./index-081xws23.js";
12
7
 
13
8
  // src/testing/mock-keys.ts
14
9
  import { Buffer as Buffer2 } from "buffer";
@@ -455,6 +450,32 @@ function createMockMouse(renderer) {
455
450
  };
456
451
  }
457
452
 
453
+ // src/testing/test-streams.ts
454
+ import { Readable, Writable } from "stream";
455
+
456
+ class TestWriteStream extends Writable {
457
+ isTTY = true;
458
+ columns;
459
+ rows;
460
+ constructor(columns = 80, rows = 24) {
461
+ super();
462
+ this.columns = columns;
463
+ this.rows = rows;
464
+ }
465
+ _write(_chunk, _encoding, callback) {
466
+ callback();
467
+ }
468
+ getColorDepth() {
469
+ return 24;
470
+ }
471
+ }
472
+ function createTestStdin() {
473
+ return new Readable({ read() {} });
474
+ }
475
+ function createTestStdout(columns = 80, rows = 24) {
476
+ return new TestWriteStream(columns, rows);
477
+ }
478
+
458
479
  // src/testing/test-renderer.ts
459
480
  var decoder = new TextDecoder;
460
481
  var DEFAULT_MAX_PASSES = 20;
@@ -557,23 +578,6 @@ function waitForNextFrameOrIdle(renderer) {
557
578
  }
558
579
  });
559
580
  }
560
-
561
- class TestWriteStream extends Writable {
562
- isTTY = true;
563
- columns;
564
- rows;
565
- constructor(columns, rows) {
566
- super();
567
- this.columns = columns;
568
- this.rows = rows;
569
- }
570
- _write(_chunk, _encoding, callback) {
571
- callback();
572
- }
573
- getColorDepth() {
574
- return 24;
575
- }
576
- }
577
581
  async function createTestRenderer(options) {
578
582
  const useKittyKeyboard = options.kittyKeyboard ? { events: true } : options.useKittyKeyboard;
579
583
  const renderer = await setupTestRenderer({
@@ -591,6 +595,10 @@ async function createTestRenderer(options) {
591
595
  });
592
596
  const mockMouse = createMockMouse(renderer);
593
597
  const renderOnce = async () => {
598
+ const feed = renderer._feed;
599
+ if (feed?.isBackpressured()) {
600
+ await feed.idle();
601
+ }
594
602
  await renderer.loop();
595
603
  };
596
604
  const captureCharFrame = () => {
@@ -699,31 +707,14 @@ async function createTestRenderer(options) {
699
707
  };
700
708
  }
701
709
  async function setupTestRenderer(config) {
702
- const stdin = config.stdin || new Readable({ read() {} });
710
+ const stdin = config.stdin || createTestStdin();
703
711
  const width = config.width || config.stdout?.columns || process.stdout.columns || 80;
704
712
  const height = config.height || config.stdout?.rows || process.stdout.rows || 24;
705
- const stdout = config.stdout || new TestWriteStream(width, height);
706
- const screenMode = config.screenMode ?? "alternate-screen";
707
- const footerHeight = config.footerHeight ?? 12;
708
- const geometry = calculateRenderGeometry(screenMode, width, height, footerHeight);
709
- const ziglib = resolveRenderLib();
710
- const rendererPtr = ziglib.createRenderer(geometry.renderWidth, geometry.renderHeight, {
711
- testing: true,
712
- remote: config.remote ?? false
713
+ const stdout = config.stdout || createTestStdout(width, height);
714
+ return new CliRenderer(stdin, stdout, width, height, {
715
+ ...config,
716
+ bufferedOutput: config.bufferedOutput ?? "memory"
713
717
  });
714
- if (!rendererPtr) {
715
- throw new Error("Failed to create test renderer");
716
- }
717
- if (config.useThread === undefined) {
718
- config.useThread = true;
719
- }
720
- if (process.platform === "linux") {
721
- config.useThread = false;
722
- }
723
- ziglib.setUseThread(rendererPtr, config.useThread);
724
- const renderer = new CliRenderer(ziglib, rendererPtr, stdin, stdout, width, height, config);
725
- process.off("SIGWINCH", renderer["sigwinchHandler"]);
726
- return renderer;
727
718
  }
728
719
  // src/testing/mock-tree-sitter-client.ts
729
720
  class MockTreeSitterClient extends TreeSitterClient {
@@ -795,7 +786,8 @@ function createTerminalCapabilities(overrides = {}) {
795
786
  osc52: false,
796
787
  notifications: false,
797
788
  explicit_cursor_positioning: false,
798
- in_tmux: false,
789
+ remote: false,
790
+ multiplexer: "none",
799
791
  ...overrides,
800
792
  terminal: {
801
793
  name: "",
@@ -999,5 +991,5 @@ export {
999
991
  KeyCodes
1000
992
  };
1001
993
 
1002
- //# debugId=40EAAC392783D1D064756E2164756E21
994
+ //# debugId=0BAC903EE185632E64756E2164756E21
1003
995
  //# sourceMappingURL=testing.js.map