@opentui/core 0.1.5 → 0.1.7

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/3d.js CHANGED
@@ -33976,6 +33976,18 @@ function parseJustify(value) {
33976
33976
  return Justify.FlexStart;
33977
33977
  }
33978
33978
  }
33979
+ function parsePositionType(value) {
33980
+ switch (value.toLowerCase()) {
33981
+ case "static":
33982
+ return PositionType.Static;
33983
+ case "relative":
33984
+ return PositionType.Relative;
33985
+ case "absolute":
33986
+ return PositionType.Absolute;
33987
+ default:
33988
+ return PositionType.Static;
33989
+ }
33990
+ }
33979
33991
 
33980
33992
  // src/Renderable.ts
33981
33993
  var renderableNumber = 1;
@@ -34286,8 +34298,8 @@ class Renderable extends EventEmitter3 {
34286
34298
  this.layoutNode.setHeight(options.height);
34287
34299
  }
34288
34300
  this._positionType = options.position ?? "relative";
34289
- if (this._positionType === "absolute") {
34290
- node.setPositionType(PositionType.Absolute);
34301
+ if (this._positionType !== "relative") {
34302
+ node.setPositionType(parsePositionType(this._positionType));
34291
34303
  }
34292
34304
  const hasPositionProps = options.top !== undefined || options.right !== undefined || options.bottom !== undefined || options.left !== undefined;
34293
34305
  if (hasPositionProps) {
@@ -34346,6 +34358,14 @@ class Renderable extends EventEmitter3 {
34346
34358
  node.setPadding(Edge2.Left, options.paddingLeft);
34347
34359
  }
34348
34360
  }
34361
+ set position(positionType) {
34362
+ if (this._positionType === positionType)
34363
+ return;
34364
+ this._positionType = positionType;
34365
+ this.layoutNode.yogaNode.setPositionType(parsePositionType(positionType));
34366
+ this.needsUpdate();
34367
+ this._yogaPerformancePositionUpdated = true;
34368
+ }
34349
34369
  setPosition(position) {
34350
34370
  this._position = { ...this._position, ...position };
34351
34371
  this.updateYogaPosition(position);
@@ -34853,7 +34873,7 @@ function getOpenTUILib(libPath) {
34853
34873
  returns: "ptr"
34854
34874
  },
34855
34875
  destroyRenderer: {
34856
- args: ["ptr"],
34876
+ args: ["ptr", "bool", "u32"],
34857
34877
  returns: "void"
34858
34878
  },
34859
34879
  setUseThread: {
@@ -35008,6 +35028,14 @@ function getOpenTUILib(libPath) {
35008
35028
  args: ["ptr", "i64"],
35009
35029
  returns: "void"
35010
35030
  },
35031
+ enableMouse: {
35032
+ args: ["ptr", "bool"],
35033
+ returns: "void"
35034
+ },
35035
+ disableMouse: {
35036
+ args: ["ptr"],
35037
+ returns: "void"
35038
+ },
35011
35039
  createTextBuffer: {
35012
35040
  args: ["u32"],
35013
35041
  returns: "ptr"
@@ -35116,8 +35144,8 @@ class FFIRenderLib {
35116
35144
  createRenderer(width, height) {
35117
35145
  return this.opentui.symbols.createRenderer(width, height);
35118
35146
  }
35119
- destroyRenderer(renderer) {
35120
- this.opentui.symbols.destroyRenderer(renderer);
35147
+ destroyRenderer(renderer, useAlternateScreen, splitHeight) {
35148
+ this.opentui.symbols.destroyRenderer(renderer, useAlternateScreen, splitHeight);
35121
35149
  }
35122
35150
  setUseThread(renderer, useThread) {
35123
35151
  this.opentui.symbols.setUseThread(renderer, useThread);
@@ -35327,6 +35355,12 @@ class FFIRenderLib {
35327
35355
  const ts = timestamp ?? Date.now();
35328
35356
  this.opentui.symbols.dumpStdoutBuffer(renderer, ts);
35329
35357
  }
35358
+ enableMouse(renderer, enableMovement) {
35359
+ this.opentui.symbols.enableMouse(renderer, enableMovement);
35360
+ }
35361
+ disableMouse(renderer) {
35362
+ this.opentui.symbols.disableMouse(renderer);
35363
+ }
35330
35364
  createTextBuffer(capacity) {
35331
35365
  const bufferPtr = this.opentui.symbols.createTextBuffer(capacity);
35332
35366
  if (!bufferPtr) {
@@ -35553,6 +35587,77 @@ var BorderCharArrays = {
35553
35587
  rounded: borderCharsToArray(BorderChars.rounded),
35554
35588
  heavy: borderCharsToArray(BorderChars.heavy)
35555
35589
  };
35590
+ // src/lib/styled-text.ts
35591
+ var textEncoder = new TextEncoder;
35592
+
35593
+ class StyledText {
35594
+ chunks;
35595
+ _plainText = "";
35596
+ constructor(chunks) {
35597
+ this.chunks = chunks;
35598
+ for (let i = 0;i < chunks.length; i++) {
35599
+ this._plainText += chunks[i].plainText;
35600
+ }
35601
+ }
35602
+ toString() {
35603
+ return this._plainText;
35604
+ }
35605
+ _chunksToPlainText() {
35606
+ this._plainText = "";
35607
+ for (const chunk of this.chunks) {
35608
+ this._plainText += chunk.plainText;
35609
+ }
35610
+ }
35611
+ insert(chunk, index) {
35612
+ const originalLength = this.chunks.length;
35613
+ if (index === undefined) {
35614
+ this.chunks.push(chunk);
35615
+ } else {
35616
+ this.chunks.splice(index, 0, chunk);
35617
+ }
35618
+ if (index === undefined || index === originalLength) {
35619
+ this._plainText += chunk.plainText;
35620
+ } else {
35621
+ this._chunksToPlainText();
35622
+ }
35623
+ }
35624
+ remove(chunk) {
35625
+ const originalLength = this.chunks.length;
35626
+ const index = this.chunks.indexOf(chunk);
35627
+ if (index === -1)
35628
+ return;
35629
+ this.chunks.splice(index, 1);
35630
+ if (index === originalLength - 1) {
35631
+ this._plainText = this._plainText.slice(0, this._plainText.length - chunk.plainText.length);
35632
+ } else {
35633
+ this._chunksToPlainText();
35634
+ }
35635
+ }
35636
+ replace(chunk, oldChunk) {
35637
+ const index = this.chunks.indexOf(oldChunk);
35638
+ if (index === -1)
35639
+ return;
35640
+ this.chunks.splice(index, 1, chunk);
35641
+ if (index === this.chunks.length - 1) {
35642
+ this._plainText = this._plainText.slice(0, this._plainText.length - oldChunk.plainText.length) + chunk.plainText;
35643
+ } else {
35644
+ this._chunksToPlainText();
35645
+ }
35646
+ }
35647
+ }
35648
+ function stringToStyledText(content) {
35649
+ const textEncoder2 = new TextEncoder;
35650
+ const chunk = {
35651
+ __isChunk: true,
35652
+ text: textEncoder2.encode(content),
35653
+ plainText: content
35654
+ };
35655
+ return new StyledText([chunk]);
35656
+ }
35657
+ var templateCache = new WeakMap;
35658
+
35659
+ // src/lib/hast-styled-text.ts
35660
+ var textEncoder2 = new TextEncoder;
35556
35661
  // src/buffer.ts
35557
35662
  var fbIdCounter = 0;
35558
35663
  function isRGBAWithAlpha(color) {
@@ -35933,35 +36038,6 @@ class TimelineEngine {
35933
36038
  }
35934
36039
  }
35935
36040
  var engine = new TimelineEngine;
35936
- // src/lib/styled-text.ts
35937
- var textEncoder = new TextEncoder;
35938
-
35939
- class StyledText {
35940
- chunks;
35941
- _length;
35942
- _plainText;
35943
- constructor(chunks, length, plainText) {
35944
- this.chunks = chunks;
35945
- this._length = length;
35946
- this._plainText = plainText;
35947
- }
35948
- toString() {
35949
- return this._plainText;
35950
- }
35951
- get length() {
35952
- return this._length;
35953
- }
35954
- }
35955
- function stringToStyledText(content) {
35956
- const textEncoder2 = new TextEncoder;
35957
- const chunk = {
35958
- __isChunk: true,
35959
- text: textEncoder2.encode(content),
35960
- plainText: content
35961
- };
35962
- return new StyledText([chunk], content.length, content);
35963
- }
35964
- var templateCache = new WeakMap;
35965
36041
  // src/lib/selection.ts
35966
36042
  class Selection {
35967
36043
  _anchor;
@@ -36142,7 +36218,10 @@ var ANSI = {
36142
36218
  enableAnyEventTracking: "\x1B[?1003h",
36143
36219
  disableAnyEventTracking: "\x1B[?1003l",
36144
36220
  enableSGRMouseMode: "\x1B[?1006h",
36145
- disableSGRMouseMode: "\x1B[?1006l"
36221
+ disableSGRMouseMode: "\x1B[?1006l",
36222
+ makeRoomForRenderer: (height) => `
36223
+ `.repeat(height) + `\x1B[${height}A`,
36224
+ clearRendererSpace: (height) => `\x1B[${height}A\x1B[1G\x1B[J`
36146
36225
  };
36147
36226
 
36148
36227
  // src/console.ts
@@ -36925,6 +37004,11 @@ class MouseEvent {
36925
37004
  this._defaultPrevented = true;
36926
37005
  }
36927
37006
  }
37007
+ ["SIGINT", "SIGTERM", "SIGQUIT", "SIGABRT"].forEach((signal) => {
37008
+ process.on(signal, () => {
37009
+ process.exit();
37010
+ });
37011
+ });
36928
37012
  var animationFrameId = 0;
36929
37013
 
36930
37014
  class CliRenderer extends EventEmitter6 {
@@ -36934,7 +37018,6 @@ class CliRenderer extends EventEmitter6 {
36934
37018
  stdout;
36935
37019
  exitOnCtrlC;
36936
37020
  isDestroyed = false;
36937
- isShuttingDown = false;
36938
37021
  nextRenderBuffer;
36939
37022
  currentRenderBuffer;
36940
37023
  _isRunning = false;
@@ -36956,6 +37039,7 @@ class CliRenderer extends EventEmitter6 {
36956
37039
  postProcessFns = [];
36957
37040
  backgroundColor = RGBA.fromHex("#000000");
36958
37041
  waitingForPixelResolution = false;
37042
+ shutdownRequested = null;
36959
37043
  rendering = false;
36960
37044
  renderingNative = false;
36961
37045
  renderTimeout = null;
@@ -37059,8 +37143,6 @@ class CliRenderer extends EventEmitter6 {
37059
37143
  }
37060
37144
  this.stdout.write = this.interceptStdoutWrite.bind(this);
37061
37145
  this.sigwinchHandler = () => {
37062
- if (this.isShuttingDown)
37063
- return;
37064
37146
  const width2 = this.stdout.columns || 80;
37065
37147
  const height2 = this.stdout.rows || 24;
37066
37148
  this.handleResize(width2, height2);
@@ -37068,6 +37150,7 @@ class CliRenderer extends EventEmitter6 {
37068
37150
  process.on("SIGWINCH", this.sigwinchHandler);
37069
37151
  const handleError = (error) => {
37070
37152
  this.stop();
37153
+ this.destroy();
37071
37154
  new Promise((resolve2) => {
37072
37155
  setTimeout(() => {
37073
37156
  resolve2(true);
@@ -37101,8 +37184,7 @@ Error details:
37101
37184
  };
37102
37185
  process.on("uncaughtException", handleError);
37103
37186
  process.on("unhandledRejection", handleError);
37104
- process.on("exit", (code) => {
37105
- this.stop();
37187
+ process.on("exit", () => {
37106
37188
  this.destroy();
37107
37189
  });
37108
37190
  this._console = new TerminalConsole(this, config.consoleOptions);
@@ -37121,6 +37203,13 @@ Error details:
37121
37203
  }
37122
37204
  global.window.requestAnimationFrame = requestAnimationFrame;
37123
37205
  this.queryPixelResolution();
37206
+ if (process.env.OTUI_NO_NATIVE_RENDER === "true") {
37207
+ this.renderNative = () => {
37208
+ if (this._splitHeight > 0) {
37209
+ this.flushStdoutCache(this._splitHeight);
37210
+ }
37211
+ };
37212
+ }
37124
37213
  }
37125
37214
  writeOut(chunk, encoding, callback) {
37126
37215
  return this.realStdoutWrite.call(this.stdout, chunk, encoding, callback);
@@ -37252,30 +37341,17 @@ Error details:
37252
37341
  return true;
37253
37342
  }
37254
37343
  enableMouse() {
37255
- this.writeOut(ANSI.enableSGRMouseMode);
37256
- this.writeOut(ANSI.enableMouseTracking);
37257
- this.writeOut(ANSI.enableButtonEventTracking);
37258
- if (this.enableMouseMovement) {
37259
- this.writeOut(ANSI.enableAnyEventTracking);
37260
- }
37344
+ this.lib.enableMouse(this.rendererPtr, this.enableMouseMovement);
37261
37345
  }
37262
37346
  disableMouse() {
37263
- if (this.enableMouseMovement) {
37264
- this.writeOut(ANSI.disableAnyEventTracking);
37265
- }
37266
- this.writeOut(ANSI.disableButtonEventTracking);
37267
- this.writeOut(ANSI.disableMouseTracking);
37268
- this.writeOut(ANSI.disableSGRMouseMode);
37269
37347
  this.capturedRenderable = undefined;
37270
37348
  this.mouseParser.reset();
37349
+ this.lib.disableMouse(this.rendererPtr);
37271
37350
  }
37272
37351
  set useThread(useThread) {
37273
37352
  this._useThread = useThread;
37274
37353
  this.lib.setUseThread(this.rendererPtr, useThread);
37275
37354
  }
37276
- setTerminalSize(width, height) {
37277
- this.handleResize(width, height);
37278
- }
37279
37355
  setupTerminal() {
37280
37356
  this.writeOut(ANSI.saveCursorState);
37281
37357
  if (this.stdin.setRawMode) {
@@ -37302,7 +37378,7 @@ Error details:
37302
37378
  }
37303
37379
  if (this.exitOnCtrlC && str === "\x03") {
37304
37380
  process.nextTick(() => {
37305
- process.exit(0);
37381
+ process.exit();
37306
37382
  });
37307
37383
  return;
37308
37384
  }
@@ -37313,6 +37389,8 @@ Error details:
37313
37389
  });
37314
37390
  if (this._useAlternateScreen) {
37315
37391
  this.writeOut(ANSI.switchToAlternateScreen);
37392
+ } else {
37393
+ this.writeOut(ANSI.makeRoomForRenderer(this.height - 1));
37316
37394
  }
37317
37395
  this.setCursorPosition(0, 0, false);
37318
37396
  }
@@ -37434,7 +37512,7 @@ Error details:
37434
37512
  }
37435
37513
  }
37436
37514
  handleResize(width, height) {
37437
- if (this.isShuttingDown)
37515
+ if (this.isDestroyed)
37438
37516
  return;
37439
37517
  if (this._splitHeight > 0) {
37440
37518
  this.processResize(width, height);
@@ -37571,44 +37649,31 @@ Error details:
37571
37649
  this._isRunning = false;
37572
37650
  }
37573
37651
  stop() {
37574
- if (this.isShuttingDown)
37652
+ if (this.isRunning && !this.isDestroyed) {
37653
+ this._isRunning = false;
37654
+ if (this.memorySnapshotTimer) {
37655
+ clearInterval(this.memorySnapshotTimer);
37656
+ this.memorySnapshotTimer = null;
37657
+ }
37658
+ if (this.renderTimeout) {
37659
+ clearTimeout(this.renderTimeout);
37660
+ this.renderTimeout = null;
37661
+ }
37662
+ }
37663
+ }
37664
+ destroy() {
37665
+ if (this.isDestroyed)
37575
37666
  return;
37576
- this._isRunning = false;
37577
- this.isShuttingDown = true;
37667
+ this.isDestroyed = true;
37578
37668
  this.waitingForPixelResolution = false;
37669
+ this.capturedRenderable = undefined;
37579
37670
  if (this.sigwinchHandler) {
37580
37671
  process.removeListener("SIGWINCH", this.sigwinchHandler);
37581
37672
  this.sigwinchHandler = null;
37582
37673
  }
37583
37674
  this._console.deactivate();
37675
+ this.lib.destroyRenderer(this.rendererPtr, this._useAlternateScreen, this._splitHeight);
37584
37676
  this.disableStdoutInterception();
37585
- if (this.renderTimeout) {
37586
- clearTimeout(this.renderTimeout);
37587
- this.renderTimeout = null;
37588
- }
37589
- if (this.memorySnapshotTimer) {
37590
- clearInterval(this.memorySnapshotTimer);
37591
- this.memorySnapshotTimer = null;
37592
- }
37593
- if (this._splitHeight > 0) {
37594
- const consoleEndLine = this._terminalHeight - this._splitHeight;
37595
- this.writeOut(ANSI.moveCursor(consoleEndLine, 1));
37596
- }
37597
- this.capturedRenderable = undefined;
37598
- if (this._useMouse) {
37599
- this.disableMouse();
37600
- }
37601
- this.writeOut(ANSI.resetCursorColor);
37602
- this.writeOut(ANSI.showCursor);
37603
- if (this._useAlternateScreen) {
37604
- this.writeOut(ANSI.switchToMainScreen);
37605
- }
37606
- }
37607
- destroy() {
37608
- if (this.isDestroyed)
37609
- return;
37610
- this.lib.destroyRenderer(this.rendererPtr);
37611
- this.isDestroyed = true;
37612
37677
  }
37613
37678
  startRenderLoop() {
37614
37679
  if (!this._isRunning)
@@ -37621,7 +37686,7 @@ Error details:
37621
37686
  this.loop();
37622
37687
  }
37623
37688
  async loop() {
37624
- if (this.rendering)
37689
+ if (this.rendering || this.isDestroyed)
37625
37690
  return;
37626
37691
  this.rendering = true;
37627
37692
  if (this.renderTimeout) {
@@ -37866,8 +37931,6 @@ class TextRenderable extends Renderable {
37866
37931
  set content(value) {
37867
37932
  this._text = typeof value === "string" ? stringToStyledText(value) : value;
37868
37933
  this.updateTextInfo();
37869
- this.setupMeasureFunc();
37870
- this.needsUpdate();
37871
37934
  }
37872
37935
  get fg() {
37873
37936
  return this._defaultFg;
@@ -37929,8 +37992,8 @@ class TextRenderable extends Renderable {
37929
37992
  const changed = this.selectionHelper.reevaluateSelection(this.width, this.height);
37930
37993
  if (changed) {
37931
37994
  this.syncSelectionToTextBuffer();
37932
- this.needsUpdate();
37933
37995
  }
37996
+ this.needsUpdate();
37934
37997
  }
37935
37998
  setupMeasureFunc() {
37936
37999
  if (this._positionType === "relative" && this._width === "auto") {
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 opentui
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  OpenTUI Core is a TypeScript library for building terminal user interfaces (TUIs). It is currently in
4
4
  development and is not ready for production use.
5
5
 
6
+ [Getting Started](docs/getting-started.md)
7
+
6
8
  ## Install
7
9
 
8
10
  ```bash
package/Renderable.d.ts CHANGED
@@ -126,6 +126,7 @@ export declare abstract class Renderable extends EventEmitter {
126
126
  private ensureZIndexSorted;
127
127
  private setupYogaProperties;
128
128
  private setupMarginAndPadding;
129
+ set position(positionType: PositionTypeString);
129
130
  setPosition(position: Position): void;
130
131
  private updateYogaPosition;
131
132
  set flexGrow(grow: number);
package/ansi.d.ts CHANGED
@@ -23,4 +23,6 @@ export declare const ANSI: {
23
23
  disableAnyEventTracking: string;
24
24
  enableSGRMouseMode: string;
25
25
  disableSGRMouseMode: string;
26
+ makeRoomForRenderer: (height: number) => string;
27
+ clearRendererSpace: (height: number) => string;
26
28
  };
package/index.d.ts CHANGED
@@ -12,3 +12,4 @@ export * from "./lib/selection";
12
12
  export * from "./renderer";
13
13
  export * from "./renderables";
14
14
  export * from "./zig";
15
+ export * from "./console";