@opentui/core 0.1.23 → 0.1.24

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.
@@ -1,11 +1,15 @@
1
1
  import { EventEmitter } from "events";
2
2
  import { type ParsedKey } from "./parse.keypress";
3
+ export type { ParsedKey };
3
4
  type KeyHandlerEventMap = {
4
5
  keypress: [ParsedKey];
6
+ keyrepeat: [ParsedKey];
7
+ keyrelease: [ParsedKey];
5
8
  };
6
9
  export declare class KeyHandler extends EventEmitter<KeyHandlerEventMap> {
7
- constructor();
10
+ private stdin;
11
+ private useKittyKeyboard;
12
+ constructor(stdin?: NodeJS.ReadStream, useKittyKeyboard?: boolean);
8
13
  destroy(): void;
9
14
  }
10
- export declare function getKeyHandler(): KeyHandler;
11
- export {};
15
+ export declare function getKeyHandler(useKittyKeyboard?: boolean): KeyHandler;
package/lib/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export * from "./border";
2
- export * from "./TrackedNode";
3
2
  export * from "./KeyHandler";
4
3
  export * from "./ascii.font";
5
4
  export * from "./hast-styled-text";
@@ -0,0 +1,2 @@
1
+ import type { ParsedKey } from "./parse.keypress";
2
+ export declare function parseKittyKeyboard(sequence: string): ParsedKey | null;
@@ -1,5 +1,6 @@
1
1
  import { Buffer } from "node:buffer";
2
2
  export declare const nonAlphanumericKeys: string[];
3
+ export type KeyEventType = "press" | "repeat" | "release";
3
4
  export type ParsedKey = {
4
5
  name: string;
5
6
  ctrl: boolean;
@@ -9,6 +10,15 @@ export type ParsedKey = {
9
10
  sequence: string;
10
11
  number: boolean;
11
12
  raw: string;
13
+ eventType: KeyEventType;
12
14
  code?: string;
15
+ super?: boolean;
16
+ hyper?: boolean;
17
+ capsLock?: boolean;
18
+ numLock?: boolean;
19
+ baseCode?: number;
13
20
  };
14
- export declare const parseKeypress: (s?: Buffer | string) => ParsedKey;
21
+ export type ParseKeypressOptions = {
22
+ useKittyKeyboard?: boolean;
23
+ };
24
+ export declare const parseKeypress: (s?: Buffer | string, options?: ParseKeypressOptions) => ParsedKey;
@@ -0,0 +1,12 @@
1
+ import type { RenderableOptions, Renderable } from "../Renderable";
2
+ import type { PositionTypeString, OverflowString } from "./yoga.options";
3
+ export declare function validateOptions(id: string, options: RenderableOptions<Renderable>): void;
4
+ export declare function isValidPercentage(value: any): value is `${number}%`;
5
+ export declare function isMarginType(value: any): value is number | "auto" | `${number}%`;
6
+ export declare function isPaddingType(value: any): value is number | `${number}%`;
7
+ export declare function isPositionType(value: any): value is number | "auto" | `${number}%`;
8
+ export declare function isPositionTypeType(value: any): value is PositionTypeString;
9
+ export declare function isOverflowType(value: any): value is OverflowString;
10
+ export declare function isDimensionType(value: any): value is number | "auto" | `${number}%`;
11
+ export declare function isFlexBasisType(value: any): value is number | "auto" | undefined;
12
+ export declare function isSizeType(value: any): value is number | `${number}%` | undefined;
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.1.23",
7
+ "version": "0.1.24",
8
8
  "description": "OpenTUI is a TypeScript library for building terminal user interfaces (TUIs)",
9
9
  "license": "MIT",
10
10
  "repository": {
@@ -22,27 +22,29 @@
22
22
  "import": "./3d.js",
23
23
  "require": "./3d.js",
24
24
  "types": "./3d.d.ts"
25
+ },
26
+ "./testing": {
27
+ "import": "./testing.js",
28
+ "require": "./testing.js",
29
+ "types": "./testing.d.ts"
25
30
  }
26
31
  },
27
- "dependencies": {
28
- "jimp": "1.6.0",
29
- "yoga-layout": "3.2.1"
30
- },
31
32
  "devDependencies": {
32
33
  "@types/bun": "latest",
33
34
  "@types/three": "0.177.0",
34
- "commander": "^13.1.0"
35
+ "commander": "^13.1.0",
36
+ "typescript": "^5"
35
37
  },
36
38
  "optionalDependencies": {
37
39
  "@dimforge/rapier2d-simd-compat": "^0.17.3",
38
40
  "bun-webgpu": "0.1.3",
39
41
  "planck": "^1.4.2",
40
42
  "three": "0.177.0",
41
- "@opentui/core-darwin-x64": "0.1.23",
42
- "@opentui/core-darwin-arm64": "0.1.23",
43
- "@opentui/core-linux-x64": "0.1.23",
44
- "@opentui/core-linux-arm64": "0.1.23",
45
- "@opentui/core-win32-x64": "0.1.23",
46
- "@opentui/core-win32-arm64": "0.1.23"
43
+ "@opentui/core-darwin-x64": "0.1.24",
44
+ "@opentui/core-darwin-arm64": "0.1.24",
45
+ "@opentui/core-linux-x64": "0.1.24",
46
+ "@opentui/core-linux-arm64": "0.1.24",
47
+ "@opentui/core-win32-x64": "0.1.24",
48
+ "@opentui/core-win32-arm64": "0.1.24"
47
49
  }
48
50
  }
@@ -20,6 +20,8 @@ export interface ScrollBoxOptions extends BoxOptions<ScrollBoxRenderable> {
20
20
  horizontalScrollbarOptions?: Omit<ScrollBarOptions, "orientation">;
21
21
  stickyScroll?: boolean;
22
22
  stickyStart?: "bottom" | "top" | "left" | "right";
23
+ scrollX?: boolean;
24
+ scrollY?: boolean;
23
25
  }
24
26
  export declare class ScrollBoxRenderable extends BoxRenderable {
25
27
  static idCounter: number;
@@ -61,7 +63,7 @@ export declare class ScrollBoxRenderable extends BoxRenderable {
61
63
  get scrollHeight(): number;
62
64
  private updateStickyState;
63
65
  private applyStickyStart;
64
- constructor(ctx: RenderContext, { wrapperOptions, viewportOptions, contentOptions, rootOptions, scrollbarOptions, verticalScrollbarOptions, horizontalScrollbarOptions, stickyScroll, stickyStart, ...options }: ScrollBoxOptions);
66
+ constructor(ctx: RenderContext, { wrapperOptions, viewportOptions, contentOptions, rootOptions, scrollbarOptions, verticalScrollbarOptions, horizontalScrollbarOptions, stickyScroll, stickyStart, scrollX, scrollY, ...options }: ScrollBoxOptions);
65
67
  protected onUpdate(deltaTime: number): void;
66
68
  scrollBy(delta: number | {
67
69
  x: number;
@@ -1,31 +1,44 @@
1
1
  import { type ColorInput, OptimizedBuffer, Renderable, type RenderableOptions, type RenderContext, RGBA } from "../index";
2
2
  export interface SliderOptions extends RenderableOptions<SliderRenderable> {
3
3
  orientation: "vertical" | "horizontal";
4
- thumbSize?: number;
5
- thumbPosition?: number;
4
+ value?: number;
5
+ min?: number;
6
+ max?: number;
7
+ viewPortSize?: number;
6
8
  backgroundColor?: ColorInput;
7
9
  foregroundColor?: ColorInput;
8
- onChange?: (position: number) => void;
10
+ onChange?: (value: number) => void;
9
11
  }
10
12
  export declare class SliderRenderable extends Renderable {
11
13
  readonly orientation: "vertical" | "horizontal";
12
- private _thumbSize;
13
- private _thumbPosition;
14
+ private _value;
15
+ private _min;
16
+ private _max;
17
+ private _viewPortSize;
14
18
  private _backgroundColor;
15
19
  private _foregroundColor;
16
20
  private _onChange?;
17
21
  constructor(ctx: RenderContext, options: SliderOptions);
18
- get thumbSize(): number;
19
- set thumbSize(value: number);
20
- get thumbPosition(): number;
21
- set thumbPosition(value: number);
22
+ get value(): number;
23
+ set value(newValue: number);
24
+ get min(): number;
25
+ set min(newMin: number);
26
+ get max(): number;
27
+ set max(newMax: number);
28
+ set viewPortSize(size: number);
29
+ get viewPortSize(): number;
22
30
  get backgroundColor(): RGBA;
23
31
  set backgroundColor(value: ColorInput);
24
32
  get foregroundColor(): RGBA;
25
33
  set foregroundColor(value: ColorInput);
34
+ private calculateDragOffsetVirtual;
26
35
  private setupMouseHandling;
27
- private updatePositionFromMouse;
28
- private getThumbPosition;
36
+ private updateValueFromMouseDirect;
37
+ private updateValueFromMouseWithOffset;
29
38
  private getThumbRect;
30
39
  protected renderSelf(buffer: OptimizedBuffer): void;
40
+ private renderHorizontal;
41
+ private renderVertical;
42
+ private getVirtualThumbSize;
43
+ private getVirtualThumbStart;
31
44
  }
@@ -5,7 +5,7 @@ import { type TextChunk } from "../text-buffer";
5
5
  import { RGBA } from "../lib/RGBA";
6
6
  import { type RenderContext } from "../types";
7
7
  import type { OptimizedBuffer } from "../buffer";
8
- import { TextNodeRenderable } from "./TextNode";
8
+ import { RootTextNodeRenderable, TextNodeRenderable } from "./TextNode";
9
9
  export interface TextOptions extends RenderableOptions<TextRenderable> {
10
10
  content?: StyledText | string;
11
11
  fg?: string | RGBA;
@@ -14,6 +14,8 @@ export interface TextOptions extends RenderableOptions<TextRenderable> {
14
14
  selectionFg?: string | RGBA;
15
15
  selectable?: boolean;
16
16
  attributes?: number;
17
+ wrap?: boolean;
18
+ wrapMode?: "char" | "word";
17
19
  }
18
20
  export declare class TextRenderable extends Renderable {
19
21
  selectable: boolean;
@@ -23,10 +25,12 @@ export declare class TextRenderable extends Renderable {
23
25
  private _defaultAttributes;
24
26
  private _selectionBg;
25
27
  private _selectionFg;
28
+ private _wrap;
29
+ private _wrapMode;
26
30
  private lastLocalSelection;
27
31
  private textBuffer;
28
32
  private _lineInfo;
29
- private rootTextNode;
33
+ protected rootTextNode: RootTextNodeRenderable;
30
34
  protected _defaultOptions: {
31
35
  content: string;
32
36
  fg: RGBA;
@@ -35,6 +39,8 @@ export declare class TextRenderable extends Renderable {
35
39
  selectionFg: undefined;
36
40
  selectable: true;
37
41
  attributes: number;
42
+ wrap: true;
43
+ wrapMode: "char" | "word";
38
44
  };
39
45
  constructor(ctx: RenderContext, options: TextOptions);
40
46
  private updateTextBuffer;
@@ -43,6 +49,7 @@ export declare class TextRenderable extends Renderable {
43
49
  get plainText(): string;
44
50
  get textLength(): number;
45
51
  get chunks(): TextChunk[];
52
+ get textNode(): RootTextNodeRenderable;
46
53
  set content(value: StyledText | string);
47
54
  get fg(): RGBA;
48
55
  set fg(value: RGBA | string | undefined);
@@ -54,6 +61,10 @@ export declare class TextRenderable extends Renderable {
54
61
  set bg(value: RGBA | string | undefined);
55
62
  get attributes(): number;
56
63
  set attributes(value: number);
64
+ get wrap(): boolean;
65
+ set wrap(value: boolean);
66
+ get wrapMode(): "char" | "word";
67
+ set wrapMode(value: "char" | "word");
57
68
  protected onResize(width: number, height: number): void;
58
69
  private updateLocalSelection;
59
70
  private updateTextInfo;
@@ -65,6 +76,7 @@ export declare class TextRenderable extends Renderable {
65
76
  add(obj: TextNodeRenderable | StyledText | string, index?: number): number;
66
77
  remove(id: string): void;
67
78
  insertBefore(obj: BaseRenderable | any, anchor?: TextNodeRenderable): number;
79
+ getTextChildren(): BaseRenderable[];
68
80
  clear(): void;
69
81
  shouldStartSelection(x: number, y: number): boolean;
70
82
  onSelectionChanged(selection: Selection | null): boolean;
@@ -74,7 +86,7 @@ export declare class TextRenderable extends Renderable {
74
86
  start: number;
75
87
  end: number;
76
88
  } | null;
77
- protected onUpdate(deltaTime: number): void;
89
+ onLifecyclePass: () => void;
78
90
  render(buffer: OptimizedBuffer, deltaTime: number): void;
79
91
  protected renderSelf(buffer: OptimizedBuffer): void;
80
92
  destroy(): void;
@@ -1,3 +1,4 @@
1
+ import type { TextRenderable } from ".";
1
2
  import { BaseRenderable, type BaseRenderableOptions } from "../Renderable";
2
3
  import { RGBA } from "../lib/RGBA";
3
4
  import { StyledText } from "../lib/styled-text";
@@ -12,9 +13,9 @@ declare const BrandedTextNodeRenderable: unique symbol;
12
13
  export declare function isTextNodeRenderable(obj: any): obj is TextNodeRenderable;
13
14
  export declare class TextNodeRenderable extends BaseRenderable {
14
15
  [BrandedTextNodeRenderable]: boolean;
15
- fg?: RGBA;
16
- bg?: RGBA;
17
- attributes: number;
16
+ private _fg?;
17
+ private _bg?;
18
+ private _attributes;
18
19
  private _children;
19
20
  parent: TextNodeRenderable | null;
20
21
  constructor(options: TextNodeOptions);
@@ -22,6 +23,7 @@ export declare class TextNodeRenderable extends BaseRenderable {
22
23
  set children(children: (string | TextNodeRenderable)[]);
23
24
  requestRender(): void;
24
25
  add(obj: TextNodeRenderable | StyledText | string, index?: number): number;
26
+ replace(obj: TextNodeRenderable | string, index: number): void;
25
27
  insertBefore(child: string | TextNodeRenderable | StyledText, anchorNode: TextNodeRenderable | string | unknown): this;
26
28
  remove(child: string | TextNodeRenderable): this;
27
29
  clear(): void;
@@ -49,10 +51,17 @@ export declare class TextNodeRenderable extends BaseRenderable {
49
51
  getChildren(): BaseRenderable[];
50
52
  getChildrenCount(): number;
51
53
  getRenderable(id: string): BaseRenderable | undefined;
54
+ get fg(): RGBA | undefined;
55
+ set fg(fg: RGBA | string | undefined);
56
+ set bg(bg: RGBA | string | undefined);
57
+ get bg(): RGBA | undefined;
58
+ set attributes(attributes: number);
59
+ get attributes(): number;
52
60
  }
53
61
  export declare class RootTextNodeRenderable extends TextNodeRenderable {
54
62
  private readonly ctx;
55
- constructor(ctx: RenderContext, options: TextNodeOptions);
63
+ textParent: TextRenderable;
64
+ constructor(ctx: RenderContext, options: TextNodeOptions, textParent: TextRenderable);
56
65
  requestRender(): void;
57
66
  }
58
67
  export {};
package/renderer.d.ts CHANGED
@@ -8,6 +8,7 @@ import { TerminalConsole, type ConsoleOptions } from "./console";
8
8
  import { type MouseEventType, type RawMouseEvent, type ScrollInfo } from "./lib/parse.mouse";
9
9
  import { Selection } from "./lib/selection";
10
10
  import { EventEmitter } from "events";
11
+ import { KeyHandler } from "./lib/KeyHandler";
11
12
  export interface CliRendererConfig {
12
13
  stdin?: NodeJS.ReadStream;
13
14
  stdout?: NodeJS.WriteStream;
@@ -25,6 +26,7 @@ export interface CliRendererConfig {
25
26
  useAlternateScreen?: boolean;
26
27
  useConsole?: boolean;
27
28
  experimental_splitHeight?: number;
29
+ useKittyKeyboard?: boolean;
28
30
  }
29
31
  export type PixelResolution = {
30
32
  width: number;
@@ -78,6 +80,7 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
78
80
  currentRenderBuffer: OptimizedBuffer;
79
81
  private _isRunning;
80
82
  private targetFps;
83
+ private automaticMemorySnapshot;
81
84
  private memorySnapshotInterval;
82
85
  private memorySnapshotTimer;
83
86
  private lastMemorySnapshot;
@@ -111,6 +114,7 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
111
114
  };
112
115
  private _console;
113
116
  private _resolution;
117
+ private _keyHandler;
114
118
  private animationRequest;
115
119
  private resizeTimeoutId;
116
120
  private resizeDebounceDelay;
@@ -135,7 +139,14 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
135
139
  private _capabilities;
136
140
  private _latestPointer;
137
141
  private _currentFocusedRenderable;
142
+ private lifecyclePasses;
143
+ private handleError;
144
+ private exitHandler;
145
+ private warningHandler;
138
146
  constructor(lib: RenderLib, rendererPtr: Pointer, stdin: NodeJS.ReadStream, stdout: NodeJS.WriteStream, width: number, height: number, config?: CliRendererConfig);
147
+ registerLifecyclePass(renderable: Renderable): void;
148
+ unregisterLifecyclePass(renderable: Renderable): void;
149
+ getLifecyclePasses(): Set<Renderable>;
139
150
  get currentFocusedRenderable(): Renderable | null;
140
151
  focusRenderable(renderable: Renderable): void;
141
152
  addToHitGrid(x: number, y: number, width: number, height: number, id: number): void;
@@ -147,6 +158,7 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
147
158
  get isRunning(): boolean;
148
159
  get resolution(): PixelResolution | null;
149
160
  get console(): TerminalConsole;
161
+ get keyInput(): KeyHandler;
150
162
  get terminalWidth(): number;
151
163
  get terminalHeight(): number;
152
164
  get useThread(): boolean;
@@ -158,7 +170,7 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
158
170
  get capabilities(): any | null;
159
171
  set experimental_splitHeight(splitHeight: number);
160
172
  private interceptStdoutWrite;
161
- private disableStdoutInterception;
173
+ disableStdoutInterception(): void;
162
174
  private flushStdoutCache;
163
175
  private enableMouse;
164
176
  private disableMouse;
@@ -166,9 +178,12 @@ export declare class CliRenderer extends EventEmitter implements RenderContext {
166
178
  disableKittyKeyboard(): void;
167
179
  set useThread(useThread: boolean);
168
180
  setupTerminal(): Promise<void>;
181
+ private stdinListener;
182
+ private setupInput;
169
183
  private handleMouseData;
170
184
  private takeMemorySnapshot;
171
185
  private startMemorySnapshotTimer;
186
+ private stopMemorySnapshotTimer;
172
187
  setMemorySnapshotInterval(interval: number): void;
173
188
  private handleResize;
174
189
  private queryPixelResolution;
@@ -0,0 +1,38 @@
1
+ import type { CliRenderer } from "../renderer";
2
+ export declare const MouseButtons: {
3
+ readonly LEFT: 0;
4
+ readonly MIDDLE: 1;
5
+ readonly RIGHT: 2;
6
+ readonly WHEEL_UP: 64;
7
+ readonly WHEEL_DOWN: 65;
8
+ readonly WHEEL_LEFT: 66;
9
+ readonly WHEEL_RIGHT: 67;
10
+ };
11
+ export type MouseButton = (typeof MouseButtons)[keyof typeof MouseButtons];
12
+ export interface MousePosition {
13
+ x: number;
14
+ y: number;
15
+ }
16
+ export interface MouseModifiers {
17
+ shift?: boolean;
18
+ alt?: boolean;
19
+ ctrl?: boolean;
20
+ }
21
+ export type MouseEventType = "down" | "up" | "move" | "drag" | "scroll";
22
+ export interface MouseEventOptions {
23
+ button?: MouseButton;
24
+ modifiers?: MouseModifiers;
25
+ delayMs?: number;
26
+ }
27
+ export declare function createMockMouse(renderer: CliRenderer): {
28
+ moveTo: (x: number, y: number, options?: MouseEventOptions) => Promise<void>;
29
+ click: (x: number, y: number, button?: MouseButton, options?: MouseEventOptions) => Promise<void>;
30
+ doubleClick: (x: number, y: number, button?: MouseButton, options?: MouseEventOptions) => Promise<void>;
31
+ pressDown: (x: number, y: number, button?: MouseButton, options?: MouseEventOptions) => Promise<void>;
32
+ release: (x: number, y: number, button?: MouseButton, options?: MouseEventOptions) => Promise<void>;
33
+ drag: (startX: number, startY: number, endX: number, endY: number, button?: MouseButton, options?: MouseEventOptions) => Promise<void>;
34
+ scroll: (x: number, y: number, direction: "up" | "down" | "left" | "right", options?: MouseEventOptions) => Promise<void>;
35
+ getCurrentPosition: () => MousePosition;
36
+ getPressedButtons: () => MouseButton[];
37
+ emitMouseEvent: (type: MouseEventType, x: number, y: number, button?: MouseButton, options?: Omit<MouseEventOptions, "button">) => Promise<void>;
38
+ };
@@ -1,6 +1,18 @@
1
1
  import { CliRenderer, type CliRendererConfig } from "../renderer";
2
2
  import { createMockKeys } from "./mock-keys";
3
- export declare function createTestRenderer(options: CliRendererConfig): Promise<{
4
- renderer: CliRenderer;
5
- mockInput: ReturnType<typeof createMockKeys>;
3
+ import { createMockMouse } from "./mock-mouse";
4
+ export interface TestRendererOptions extends CliRendererConfig {
5
+ width?: number;
6
+ height?: number;
7
+ }
8
+ export interface TestRenderer extends CliRenderer {
9
+ }
10
+ export type MockInput = ReturnType<typeof createMockKeys>;
11
+ export type MockMouse = ReturnType<typeof createMockMouse>;
12
+ export declare function createTestRenderer(options: TestRendererOptions): Promise<{
13
+ renderer: TestRenderer;
14
+ mockInput: MockInput;
15
+ mockMouse: MockMouse;
16
+ renderOnce: () => Promise<void>;
17
+ captureCharFrame: () => string;
6
18
  }>;
package/testing.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./testing/test-renderer";
2
+ export * from "./testing/mock-keys";
3
+ export * from "./testing/mock-mouse";