@opentui/core 0.1.53 → 0.1.55

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
@@ -5,7 +5,7 @@ import {
5
5
  __export,
6
6
  __require,
7
7
  __toESM
8
- } from "./index-vhxgbbed.js";
8
+ } from "./index-0razn4m6.js";
9
9
 
10
10
  // ../../node_modules/omggif/omggif.js
11
11
  var require_omggif = __commonJS((exports) => {
package/Renderable.d.ts CHANGED
@@ -111,7 +111,7 @@ export declare abstract class BaseRenderable extends EventEmitter {
111
111
  }
112
112
  export declare abstract class Renderable extends BaseRenderable {
113
113
  static renderablesByNumber: Map<number, Renderable>;
114
- private _isDestroyed;
114
+ protected _isDestroyed: boolean;
115
115
  protected _ctx: RenderContext;
116
116
  protected _translateX: number;
117
117
  protected _translateY: number;
@@ -148,6 +148,7 @@ export declare abstract class Renderable extends BaseRenderable {
148
148
  parent: Renderable | null;
149
149
  private childrenPrimarySortDirty;
150
150
  private childrenSortedByPrimaryAxis;
151
+ private _shouldUpdateBefore;
151
152
  onLifecyclePass: (() => void) | null;
152
153
  renderBefore?: (this: Renderable, buffer: OptimizedBuffer, deltaTime: number) => void;
153
154
  renderAfter?: (this: Renderable, buffer: OptimizedBuffer, deltaTime: number) => void;
@@ -1889,15 +1889,45 @@ var functionalKeyMap = {
1889
1889
  R: "f3",
1890
1890
  S: "f4"
1891
1891
  };
1892
- function parseKittyFunctionalKey(sequence) {
1893
- const functionalRe = /^\x1b\[1;(\d+):(\d+)([A-Z])$/;
1894
- const match = functionalRe.exec(sequence);
1892
+ var tildeKeyMap = {
1893
+ "1": "home",
1894
+ "2": "insert",
1895
+ "3": "delete",
1896
+ "4": "end",
1897
+ "5": "pageup",
1898
+ "6": "pagedown",
1899
+ "7": "home",
1900
+ "8": "end",
1901
+ "11": "f1",
1902
+ "12": "f2",
1903
+ "13": "f3",
1904
+ "14": "f4",
1905
+ "15": "f5",
1906
+ "17": "f6",
1907
+ "18": "f7",
1908
+ "19": "f8",
1909
+ "20": "f9",
1910
+ "21": "f10",
1911
+ "23": "f11",
1912
+ "24": "f12"
1913
+ };
1914
+ function parseKittySpecialKey(sequence) {
1915
+ const specialKeyRe = /^\x1b\[(\d+);(\d+):(\d+)([A-Z~])$/;
1916
+ const match = specialKeyRe.exec(sequence);
1895
1917
  if (!match)
1896
1918
  return null;
1897
- const modifierStr = match[1];
1898
- const eventTypeStr = match[2];
1899
- const keyChar = match[3];
1900
- const keyName = functionalKeyMap[keyChar];
1919
+ const keyNumOrOne = match[1];
1920
+ const modifierStr = match[2];
1921
+ const eventTypeStr = match[3];
1922
+ const terminator = match[4];
1923
+ let keyName;
1924
+ if (terminator === "~") {
1925
+ keyName = tildeKeyMap[keyNumOrOne];
1926
+ } else {
1927
+ if (keyNumOrOne !== "1")
1928
+ return null;
1929
+ keyName = functionalKeyMap[terminator];
1930
+ }
1901
1931
  if (!keyName)
1902
1932
  return null;
1903
1933
  const key = {
@@ -1941,9 +1971,9 @@ function parseKittyFunctionalKey(sequence) {
1941
1971
  return key;
1942
1972
  }
1943
1973
  function parseKittyKeyboard(sequence) {
1944
- const functionalResult = parseKittyFunctionalKey(sequence);
1945
- if (functionalResult)
1946
- return functionalResult;
1974
+ const specialResult = parseKittySpecialKey(sequence);
1975
+ if (specialResult)
1976
+ return specialResult;
1947
1977
  const kittyRe = /^\x1b\[([^\x1b]+)u$/;
1948
1978
  const match = kittyRe.exec(sequence);
1949
1979
  if (!match)
@@ -2212,9 +2242,11 @@ var parseKeypress = (s = "", options = {}) => {
2212
2242
  const modifier = parseInt(modifyOtherKeysMatch[1], 10) - 1;
2213
2243
  const charCode = parseInt(modifyOtherKeysMatch[2], 10);
2214
2244
  key.ctrl = !!(modifier & 4);
2215
- key.meta = !!(modifier & 10);
2245
+ key.meta = !!(modifier & 2);
2216
2246
  key.shift = !!(modifier & 1);
2217
2247
  key.option = !!(modifier & 2);
2248
+ key.super = !!(modifier & 8);
2249
+ key.hyper = !!(modifier & 16);
2218
2250
  if (charCode === 13) {
2219
2251
  key.name = "return";
2220
2252
  } else if (charCode === 27) {
@@ -2291,9 +2323,11 @@ var parseKeypress = (s = "", options = {}) => {
2291
2323
  const code = [parts[1], parts[2], parts[4], parts[6]].filter(Boolean).join("");
2292
2324
  const modifier = parseInt(parts[3] || parts[5] || "1", 10) - 1;
2293
2325
  key.ctrl = !!(modifier & 4);
2294
- key.meta = !!(modifier & 10);
2326
+ key.meta = !!(modifier & 2);
2295
2327
  key.shift = !!(modifier & 1);
2296
2328
  key.option = !!(modifier & 2);
2329
+ key.super = !!(modifier & 8);
2330
+ key.hyper = !!(modifier & 16);
2297
2331
  key.code = code;
2298
2332
  const keyNameResult = keyName[code];
2299
2333
  if (keyNameResult) {
@@ -8877,15 +8911,15 @@ class TerminalPalette {
8877
8911
  writeFn;
8878
8912
  activeListeners = [];
8879
8913
  activeTimers = [];
8880
- inTmux;
8881
- constructor(stdin, stdout, writeFn, isTmux) {
8914
+ inLegacyTmux;
8915
+ constructor(stdin, stdout, writeFn, isLegacyTmux) {
8882
8916
  this.stdin = stdin;
8883
8917
  this.stdout = stdout;
8884
8918
  this.writeFn = writeFn || ((data) => stdout.write(data));
8885
- this.inTmux = isTmux ?? false;
8919
+ this.inLegacyTmux = isLegacyTmux ?? false;
8886
8920
  }
8887
8921
  writeOsc(osc) {
8888
- const data = this.inTmux ? wrapForTmux(osc) : osc;
8922
+ const data = this.inLegacyTmux ? wrapForTmux(osc) : osc;
8889
8923
  return this.writeFn(data);
8890
8924
  }
8891
8925
  cleanup() {
@@ -9122,8 +9156,8 @@ class TerminalPalette {
9122
9156
  };
9123
9157
  }
9124
9158
  }
9125
- function createTerminalPalette(stdin, stdout, writeFn, isTmux) {
9126
- return new TerminalPalette(stdin, stdout, writeFn, isTmux);
9159
+ function createTerminalPalette(stdin, stdout, writeFn, isLegacyTmux) {
9160
+ return new TerminalPalette(stdin, stdout, writeFn, isLegacyTmux);
9127
9161
  }
9128
9162
  // src/zig.ts
9129
9163
  import { dlopen, toArrayBuffer as toArrayBuffer4, JSCallback, ptr as ptr3 } from "bun:ffi";
@@ -11507,7 +11541,7 @@ class FFIRenderLib {
11507
11541
  lineWraps: struct.wraps
11508
11542
  };
11509
11543
  }
11510
- textBufferViewGetLineCount(view) {
11544
+ textBufferViewGetVirtualLineCount(view) {
11511
11545
  return this.opentui.symbols.textBufferViewGetVirtualLineCount(view);
11512
11546
  }
11513
11547
  textBufferViewGetLineInfoDirect(view, outPtr) {
@@ -12421,6 +12455,7 @@ class Renderable extends BaseRenderable {
12421
12455
  parent = null;
12422
12456
  childrenPrimarySortDirty = true;
12423
12457
  childrenSortedByPrimaryAxis = [];
12458
+ _shouldUpdateBefore = new Set;
12424
12459
  onLifecyclePass = null;
12425
12460
  renderBefore;
12426
12461
  renderAfter;
@@ -12506,19 +12541,27 @@ class Renderable extends BaseRenderable {
12506
12541
  return false;
12507
12542
  }
12508
12543
  focus() {
12509
- if (this._focused || !this._focusable)
12544
+ if (this._isDestroyed || this._focused || !this._focusable)
12510
12545
  return;
12511
12546
  this._ctx.focusRenderable(this);
12512
12547
  this._focused = true;
12513
12548
  this.requestRender();
12514
12549
  this.keypressHandler = (key) => {
12550
+ if (this._isDestroyed)
12551
+ return;
12515
12552
  this._keyListeners["down"]?.(key);
12553
+ if (this._isDestroyed)
12554
+ return;
12516
12555
  if (!key.defaultPrevented && this.handleKeyPress) {
12517
12556
  this.handleKeyPress(key);
12518
12557
  }
12519
12558
  };
12520
12559
  this.pasteHandler = (event) => {
12560
+ if (this._isDestroyed)
12561
+ return;
12521
12562
  this._pasteListener?.call(this, event);
12563
+ if (this._isDestroyed)
12564
+ return;
12522
12565
  if (!event.defaultPrevented && this.handlePaste) {
12523
12566
  this.handlePaste(event);
12524
12567
  }
@@ -13116,6 +13159,7 @@ class Renderable extends BaseRenderable {
13116
13159
  this._childrenInLayoutOrder.push(renderable);
13117
13160
  this.yogaNode.insertChild(childLayoutNode, insertedIndex);
13118
13161
  this.childrenPrimarySortDirty = true;
13162
+ this._shouldUpdateBefore.add(renderable);
13119
13163
  this.requestRender();
13120
13164
  return insertedIndex;
13121
13165
  }
@@ -13168,6 +13212,7 @@ class Renderable extends BaseRenderable {
13168
13212
  const insertedIndex = Math.max(0, Math.min(anchorIndex, this._childrenInLayoutOrder.length));
13169
13213
  this._childrenInLayoutOrder.splice(insertedIndex, 0, renderable);
13170
13214
  this.yogaNode.insertChild(renderable.getLayoutNode(), insertedIndex);
13215
+ this._shouldUpdateBefore.add(renderable);
13171
13216
  this.requestRender();
13172
13217
  return insertedIndex;
13173
13218
  }
@@ -13214,7 +13259,19 @@ class Renderable extends BaseRenderable {
13214
13259
  if (!this.visible)
13215
13260
  return;
13216
13261
  this.onUpdate(deltaTime);
13262
+ if (this._isDestroyed)
13263
+ return;
13217
13264
  this.updateFromLayout();
13265
+ if (this._shouldUpdateBefore.size > 0) {
13266
+ for (const child of this._shouldUpdateBefore) {
13267
+ if (!child.isDestroyed) {
13268
+ child.updateFromLayout();
13269
+ }
13270
+ }
13271
+ this._shouldUpdateBefore.clear();
13272
+ }
13273
+ if (this._isDestroyed)
13274
+ return;
13218
13275
  renderList.push({ action: "render", renderable: this });
13219
13276
  this.ensureZIndexSorted();
13220
13277
  const shouldPushScissor = this._overflow !== "visible" && this.width > 0 && this.height > 0;
@@ -13442,7 +13499,9 @@ class RootRenderable extends Renderable {
13442
13499
  const command = this.renderList[i];
13443
13500
  switch (command.action) {
13444
13501
  case "render":
13445
- command.renderable.render(buffer, deltaTime);
13502
+ if (!command.renderable.isDestroyed) {
13503
+ command.renderable.render(buffer, deltaTime);
13504
+ }
13446
13505
  break;
13447
13506
  case "pushScissorRect":
13448
13507
  buffer.pushScissorRect(command.x, command.y, command.width, command.height);
@@ -14601,6 +14660,7 @@ class CliRenderer extends EventEmitter9 {
14601
14660
  currentRenderBuffer;
14602
14661
  _isRunning = false;
14603
14662
  targetFps = 30;
14663
+ maxFps = 60;
14604
14664
  automaticMemorySnapshot = false;
14605
14665
  memorySnapshotInterval;
14606
14666
  memorySnapshotTimer = null;
@@ -14626,7 +14686,8 @@ class CliRenderer extends EventEmitter9 {
14626
14686
  frameCount = 0;
14627
14687
  lastFpsTime = 0;
14628
14688
  currentFps = 0;
14629
- targetFrameTime = 0;
14689
+ targetFrameTime = 1000 / this.targetFps;
14690
+ minTargetFrameTime = 1000 / this.maxFps;
14630
14691
  immediateRerenderRequested = false;
14631
14692
  updateScheduled = false;
14632
14693
  liveRequestCounter = 0;
@@ -14688,6 +14749,7 @@ class CliRenderer extends EventEmitter9 {
14688
14749
  _onDestroy;
14689
14750
  inputHandlers = [];
14690
14751
  prependedInputHandlers = [];
14752
+ idleResolvers = [];
14691
14753
  handleError = ((error) => {
14692
14754
  console.error(error);
14693
14755
  if (this._openConsoleOnError) {
@@ -14752,6 +14814,9 @@ Captured output:
14752
14814
  this.exitOnCtrlC = config.exitOnCtrlC === undefined ? true : config.exitOnCtrlC;
14753
14815
  this.resizeDebounceDelay = config.debounceDelay || 100;
14754
14816
  this.targetFps = config.targetFps || 30;
14817
+ this.maxFps = config.maxFps || 60;
14818
+ this.targetFrameTime = 1000 / this.targetFps;
14819
+ this.minTargetFrameTime = 1000 / this.maxFps;
14755
14820
  this.memorySnapshotInterval = config.memorySnapshotInterval ?? 0;
14756
14821
  this.gatherStats = config.gatherStats || false;
14757
14822
  this.maxStatSamples = config.maxStatSamples || 300;
@@ -14847,14 +14912,33 @@ Captured output:
14847
14912
  return this.realStdoutWrite.call(this.stdout, chunk, encoding, callback);
14848
14913
  }
14849
14914
  requestRender() {
14850
- if (!this.rendering && !this.updateScheduled && !this._isRunning && this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
14915
+ if (this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
14916
+ return;
14917
+ }
14918
+ if (this._isRunning) {
14919
+ return;
14920
+ }
14921
+ if (this.rendering) {
14922
+ this.immediateRerenderRequested = true;
14923
+ return;
14924
+ }
14925
+ if (!this.updateScheduled && !this.renderTimeout) {
14851
14926
  this.updateScheduled = true;
14852
- process.nextTick(() => {
14853
- this.loop();
14854
- this.updateScheduled = false;
14855
- });
14927
+ const now = Date.now();
14928
+ const elapsed = now - this.lastTime;
14929
+ const delay = Math.max(this.minTargetFrameTime - elapsed, 0);
14930
+ if (delay === 0) {
14931
+ process.nextTick(() => this.activateFrame());
14932
+ return;
14933
+ }
14934
+ setTimeout(() => this.activateFrame(), delay);
14856
14935
  }
14857
14936
  }
14937
+ async activateFrame() {
14938
+ await this.loop();
14939
+ this.updateScheduled = false;
14940
+ this.resolveIdleIfNeeded();
14941
+ }
14858
14942
  get useConsole() {
14859
14943
  return this._useConsole;
14860
14944
  }
@@ -14869,6 +14953,26 @@ Captured output:
14869
14953
  get isRunning() {
14870
14954
  return this._isRunning;
14871
14955
  }
14956
+ isIdleNow() {
14957
+ return !this._isRunning && !this.rendering && !this.renderTimeout && !this.updateScheduled && !this.immediateRerenderRequested;
14958
+ }
14959
+ resolveIdleIfNeeded() {
14960
+ if (!this.isIdleNow())
14961
+ return;
14962
+ const resolvers = this.idleResolvers.splice(0);
14963
+ for (const resolve4 of resolvers) {
14964
+ resolve4();
14965
+ }
14966
+ }
14967
+ idle() {
14968
+ if (this._isDestroyed)
14969
+ return Promise.resolve();
14970
+ if (this.isIdleNow())
14971
+ return Promise.resolve();
14972
+ return new Promise((resolve4) => {
14973
+ this.idleResolvers.push(resolve4);
14974
+ });
14975
+ }
14872
14976
  get resolution() {
14873
14977
  return this._resolution;
14874
14978
  }
@@ -15048,6 +15152,7 @@ Captured output:
15048
15152
  if (isCapabilityResponse(sequence)) {
15049
15153
  this.lib.processCapabilityResponse(this.rendererPtr, sequence);
15050
15154
  this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
15155
+ this.emit("capabilities", this._capabilities);
15051
15156
  return true;
15052
15157
  }
15053
15158
  return false;
@@ -15470,6 +15575,9 @@ Captured output:
15470
15575
  clearTimeout(this.renderTimeout);
15471
15576
  this.renderTimeout = null;
15472
15577
  }
15578
+ if (!this.rendering) {
15579
+ this.resolveIdleIfNeeded();
15580
+ }
15473
15581
  }
15474
15582
  }
15475
15583
  destroy() {
@@ -15522,6 +15630,7 @@ Captured output:
15522
15630
  console.error("Error in onDestroy callback:", e instanceof Error ? e.stack : String(e));
15523
15631
  }
15524
15632
  }
15633
+ this.resolveIdleIfNeeded();
15525
15634
  }
15526
15635
  startRenderLoop() {
15527
15636
  if (!this._isRunning)
@@ -15530,12 +15639,12 @@ Captured output:
15530
15639
  this.frameCount = 0;
15531
15640
  this.lastFpsTime = this.lastTime;
15532
15641
  this.currentFps = 0;
15533
- this.targetFrameTime = 1000 / this.targetFps;
15534
15642
  this.loop();
15535
15643
  }
15536
15644
  async loop() {
15537
15645
  if (this.rendering || this._isDestroyed)
15538
15646
  return;
15647
+ this.renderTimeout = null;
15539
15648
  this.rendering = true;
15540
15649
  if (this.renderTimeout) {
15541
15650
  clearTimeout(this.renderTimeout);
@@ -15585,16 +15694,21 @@ Captured output:
15585
15694
  if (this.gatherStats) {
15586
15695
  this.collectStatSample(overallFrameTime);
15587
15696
  }
15588
- if (this._isRunning) {
15589
- const delay = Math.max(1, this.targetFrameTime - Math.floor(overallFrameTime));
15590
- this.renderTimeout = setTimeout(() => this.loop(), delay);
15697
+ if (this._isRunning || this.immediateRerenderRequested) {
15698
+ const targetFrameTime = this.immediateRerenderRequested ? this.minTargetFrameTime : this.targetFrameTime;
15699
+ const delay = Math.max(1, targetFrameTime - Math.floor(overallFrameTime));
15700
+ this.immediateRerenderRequested = false;
15701
+ this.renderTimeout = setTimeout(() => {
15702
+ this.renderTimeout = null;
15703
+ this.loop();
15704
+ }, delay);
15705
+ } else {
15706
+ clearTimeout(this.renderTimeout);
15707
+ this.renderTimeout = null;
15591
15708
  }
15592
15709
  }
15593
15710
  this.rendering = false;
15594
- if (this.immediateRerenderRequested) {
15595
- this.immediateRerenderRequested = false;
15596
- this.loop();
15597
- }
15711
+ this.resolveIdleIfNeeded();
15598
15712
  }
15599
15713
  intermediateRender() {
15600
15714
  this.immediateRerenderRequested = true;
@@ -15772,8 +15886,8 @@ Captured output:
15772
15886
  return this._paletteDetectionPromise;
15773
15887
  }
15774
15888
  if (!this._paletteDetector) {
15775
- const isTmux = this.capabilities?.terminal?.name?.toLowerCase()?.includes("tmux");
15776
- this._paletteDetector = createTerminalPalette(this.stdin, this.stdout, this.writeOut.bind(this), isTmux);
15889
+ const isLegacyTmux = this.capabilities?.terminal?.name?.toLowerCase()?.includes("tmux") && this.capabilities?.terminal?.version?.localeCompare("3.6") < 0;
15890
+ this._paletteDetector = createTerminalPalette(this.stdin, this.stdout, this.writeOut.bind(this), isLegacyTmux);
15777
15891
  }
15778
15892
  this._paletteDetectionPromise = this._paletteDetector.detect(options).then((result) => {
15779
15893
  this._cachedPalette = result;
@@ -15786,5 +15900,5 @@ Captured output:
15786
15900
 
15787
15901
  export { __toESM, __commonJS, __export, __require, Edge, Gutter, MeasureMode, exports_src, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, nonAlphanumericKeys, parseKeypress, KeyEvent, PasteEvent, KeyHandler, InternalKeyHandler, RGBA, hexToRgb, rgbToHex, hsvToRgb, parseColor, fonts, measureText, getCharacterPositions, coordinateToCharacterIndex, renderFontToFrameBuffer, TextAttributes, DebugOverlayCorner, createTextAttributes, visualizeRenderableTree, isStyledText, StyledText, stringToStyledText, black, red, green, yellow, blue, magenta, cyan, white, brightBlack, brightRed, brightGreen, brightYellow, brightBlue, brightMagenta, brightCyan, brightWhite, bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite, bold, italic, underline, strikethrough, dim, reverse, blink, fg, bg, t, hastToStyledText, LinearScrollAccel, MacOSScrollAccel, StdinBuffer, parseAlign, parseBoxSizing, parseDimension, parseDirection, parseDisplay, parseEdge, parseFlexDirection, parseGutter, parseJustify, parseLogLevel, parseMeasureMode, parseOverflow, parsePositionType, parseUnit, parseWrap, MouseParser, Selection, convertGlobalToLocalSelection, ASCIIFontSelectionHelper, envRegistry, registerEnvVar, clearEnvCache, generateEnvMarkdown, generateEnvColored, env, treeSitterToTextChunks, treeSitterToStyledText, addDefaultParsers, TreeSitterClient, DataPathsManager, getDataPaths, extToFiletype, pathToFiletype, main, getTreeSitterClient, ExtmarksController, createExtmarksController, TerminalPalette, createTerminalPalette, TextBuffer, LogLevel2 as LogLevel, setRenderLibPath, resolveRenderLib, OptimizedBuffer, h, isVNode, maybeMakeRenderable, wrapWithDelegates, instantiate, delegate, isValidPercentage, LayoutEvents, RenderableEvents, isRenderable, BaseRenderable, Renderable, RootRenderable, ANSI, capture, ConsolePosition, TerminalConsole, getObjectsInViewport, MouseEvent, MouseButton, createCliRenderer, CliRenderEvents, RendererControlState, CliRenderer };
15788
15902
 
15789
- //# debugId=1108F3F0A4484C0264756E2164756E21
15790
- //# sourceMappingURL=index-vhxgbbed.js.map
15903
+ //# debugId=E61ED12D8C1C497964756E2164756E21
15904
+ //# sourceMappingURL=index-0razn4m6.js.map