@opentui/core 0.1.96 → 0.1.98

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.
@@ -5788,6 +5788,18 @@ var isShiftKey = (code) => {
5788
5788
  var isCtrlKey = (code) => {
5789
5789
  return ["Oa", "Ob", "Oc", "Od", "Oe", "[2^", "[3^", "[5^", "[6^", "[7^", "[8^"].includes(code);
5790
5790
  };
5791
+ var getCtrlKeyName = (charCode) => {
5792
+ if (charCode === 0) {
5793
+ return "space";
5794
+ }
5795
+ if (charCode >= 1 && charCode <= 26) {
5796
+ return String.fromCharCode(charCode + 97 - 1);
5797
+ }
5798
+ if (charCode >= 28 && charCode <= 31) {
5799
+ return String.fromCharCode(charCode + 64);
5800
+ }
5801
+ return;
5802
+ };
5791
5803
  var modifyOtherKeysRe = /^\x1b\[27;(\d+);(\d+)~$/;
5792
5804
  var parseKeypress = (s = "", options = {}) => {
5793
5805
  let parts;
@@ -5852,6 +5864,8 @@ var parseKeypress = (s = "", options = {}) => {
5852
5864
  source: "raw"
5853
5865
  };
5854
5866
  key.sequence = key.sequence || s || key.name;
5867
+ const ctrlKeyName = s.length === 1 ? getCtrlKeyName(s.charCodeAt(0)) : undefined;
5868
+ const metaCtrlKeyName = s.length === 2 && s[0] === "\x1B" ? getCtrlKeyName(s.charCodeAt(1)) : undefined;
5855
5869
  if (options.useKittyKeyboard) {
5856
5870
  const kittyResult = parseKittyKeyboard(s);
5857
5871
  if (kittyResult) {
@@ -5907,11 +5921,8 @@ var parseKeypress = (s = "", options = {}) => {
5907
5921
  } else if (s === " " || s === "\x1B ") {
5908
5922
  key.name = "space";
5909
5923
  key.meta = s.length === 2;
5910
- } else if (s === "\x00") {
5911
- key.name = "space";
5912
- key.ctrl = true;
5913
- } else if (s.length === 1 && s <= "\x1A") {
5914
- key.name = String.fromCharCode(s.charCodeAt(0) + 97 - 1);
5924
+ } else if (ctrlKeyName) {
5925
+ key.name = ctrlKeyName;
5915
5926
  key.ctrl = true;
5916
5927
  } else if (s.length === 1 && s >= "0" && s <= "9") {
5917
5928
  key.name = s;
@@ -5937,10 +5948,10 @@ var parseKeypress = (s = "", options = {}) => {
5937
5948
  } else {
5938
5949
  key.name = char;
5939
5950
  }
5940
- } else if (s.length === 2 && s[0] === "\x1B" && s[1] <= "\x1A") {
5951
+ } else if (metaCtrlKeyName) {
5941
5952
  key.meta = true;
5942
5953
  key.ctrl = true;
5943
- key.name = String.fromCharCode(s.charCodeAt(1) + 97 - 1);
5954
+ key.name = metaCtrlKeyName;
5944
5955
  } else if (parts = fnKeyRe.exec(s)) {
5945
5956
  const segs = [...s];
5946
5957
  if (segs[0] === "\x1B" && segs[1] === "\x1B") {
@@ -8457,19 +8468,7 @@ class ProcessQueue {
8457
8468
  }
8458
8469
 
8459
8470
  // src/lib/tree-sitter/default-parsers.ts
8460
- import { resolve, dirname } from "path";
8461
8471
  import { fileURLToPath } from "url";
8462
- import javascript_highlights from "./assets/javascript/highlights.scm" with { type: "file" };
8463
- import javascript_language from "./assets/javascript/tree-sitter-javascript.wasm" with { type: "file" };
8464
- import typescript_highlights from "./assets/typescript/highlights.scm" with { type: "file" };
8465
- import typescript_language from "./assets/typescript/tree-sitter-typescript.wasm" with { type: "file" };
8466
- import markdown_highlights from "./assets/markdown/highlights.scm" with { type: "file" };
8467
- import markdown_language from "./assets/markdown/tree-sitter-markdown.wasm" with { type: "file" };
8468
- import markdown_injections from "./assets/markdown/injections.scm" with { type: "file" };
8469
- import markdown_inline_highlights from "./assets/markdown_inline/highlights.scm" with { type: "file" };
8470
- import markdown_inline_language from "./assets/markdown_inline/tree-sitter-markdown_inline.wasm" with { type: "file" };
8471
- import zig_highlights from "./assets/zig/highlights.scm" with { type: "file" };
8472
- import zig_language from "./assets/zig/tree-sitter-zig.wasm" with { type: "file" };
8473
8472
  var _cachedParsers;
8474
8473
  function getParsers() {
8475
8474
  if (!_cachedParsers) {
@@ -8478,25 +8477,25 @@ function getParsers() {
8478
8477
  filetype: "javascript",
8479
8478
  aliases: ["javascriptreact"],
8480
8479
  queries: {
8481
- highlights: [resolve(dirname(fileURLToPath(import.meta.url)), javascript_highlights)]
8480
+ highlights: [fileURLToPath(new URL("./assets/javascript/highlights.scm", import.meta.url))]
8482
8481
  },
8483
- wasm: resolve(dirname(fileURLToPath(import.meta.url)), javascript_language)
8482
+ wasm: fileURLToPath(new URL("./assets/javascript/tree-sitter-javascript.wasm", import.meta.url))
8484
8483
  },
8485
8484
  {
8486
8485
  filetype: "typescript",
8487
8486
  aliases: ["typescriptreact"],
8488
8487
  queries: {
8489
- highlights: [resolve(dirname(fileURLToPath(import.meta.url)), typescript_highlights)]
8488
+ highlights: [fileURLToPath(new URL("./assets/typescript/highlights.scm", import.meta.url))]
8490
8489
  },
8491
- wasm: resolve(dirname(fileURLToPath(import.meta.url)), typescript_language)
8490
+ wasm: fileURLToPath(new URL("./assets/typescript/tree-sitter-typescript.wasm", import.meta.url))
8492
8491
  },
8493
8492
  {
8494
8493
  filetype: "markdown",
8495
8494
  queries: {
8496
- highlights: [resolve(dirname(fileURLToPath(import.meta.url)), markdown_highlights)],
8497
- injections: [resolve(dirname(fileURLToPath(import.meta.url)), markdown_injections)]
8495
+ highlights: [fileURLToPath(new URL("./assets/markdown/highlights.scm", import.meta.url))],
8496
+ injections: [fileURLToPath(new URL("./assets/markdown/injections.scm", import.meta.url))]
8498
8497
  },
8499
- wasm: resolve(dirname(fileURLToPath(import.meta.url)), markdown_language),
8498
+ wasm: fileURLToPath(new URL("./assets/markdown/tree-sitter-markdown.wasm", import.meta.url)),
8500
8499
  injectionMapping: {
8501
8500
  nodeTypes: {
8502
8501
  inline: "markdown_inline",
@@ -8519,16 +8518,16 @@ function getParsers() {
8519
8518
  {
8520
8519
  filetype: "markdown_inline",
8521
8520
  queries: {
8522
- highlights: [resolve(dirname(fileURLToPath(import.meta.url)), markdown_inline_highlights)]
8521
+ highlights: [fileURLToPath(new URL("./assets/markdown_inline/highlights.scm", import.meta.url))]
8523
8522
  },
8524
- wasm: resolve(dirname(fileURLToPath(import.meta.url)), markdown_inline_language)
8523
+ wasm: fileURLToPath(new URL("./assets/markdown_inline/tree-sitter-markdown_inline.wasm", import.meta.url))
8525
8524
  },
8526
8525
  {
8527
8526
  filetype: "zig",
8528
8527
  queries: {
8529
- highlights: [resolve(dirname(fileURLToPath(import.meta.url)), zig_highlights)]
8528
+ highlights: [fileURLToPath(new URL("./assets/zig/highlights.scm", import.meta.url))]
8530
8529
  },
8531
- wasm: resolve(dirname(fileURLToPath(import.meta.url)), zig_language)
8530
+ wasm: fileURLToPath(new URL("./assets/zig/tree-sitter-zig.wasm", import.meta.url))
8532
8531
  }
8533
8532
  ];
8534
8533
  }
@@ -8536,7 +8535,7 @@ function getParsers() {
8536
8535
  }
8537
8536
 
8538
8537
  // src/lib/tree-sitter/client.ts
8539
- import { resolve as resolve2, isAbsolute, parse } from "path";
8538
+ import { resolve, isAbsolute, parse } from "path";
8540
8539
  import { existsSync } from "fs";
8541
8540
 
8542
8541
  // src/lib/bunfs.ts
@@ -8609,7 +8608,7 @@ class TreeSitterClient extends EventEmitter2 {
8609
8608
  worker_path = this.options.workerPath;
8610
8609
  } else {
8611
8610
  worker_path = new URL("./parser.worker.js", import.meta.url).href;
8612
- if (!existsSync(resolve2(import.meta.dirname, "parser.worker.js"))) {
8611
+ if (!existsSync(resolve(import.meta.dirname, "parser.worker.js"))) {
8613
8612
  worker_path = new URL("./parser.worker.ts", import.meta.url).href;
8614
8613
  }
8615
8614
  }
@@ -8644,7 +8643,7 @@ class TreeSitterClient extends EventEmitter2 {
8644
8643
  if (this.initializePromise) {
8645
8644
  return this.initializePromise;
8646
8645
  }
8647
- this.initializePromise = new Promise((resolve3, reject) => {
8646
+ this.initializePromise = new Promise((resolve2, reject) => {
8648
8647
  const timeoutMs = this.options.initTimeout ?? 1e4;
8649
8648
  const timeoutId = setTimeout(() => {
8650
8649
  const error = new Error("Worker initialization timed out");
@@ -8652,7 +8651,7 @@ class TreeSitterClient extends EventEmitter2 {
8652
8651
  this.initializeResolvers = undefined;
8653
8652
  reject(error);
8654
8653
  }, timeoutMs);
8655
- this.initializeResolvers = { resolve: resolve3, reject, timeoutId };
8654
+ this.initializeResolvers = { resolve: resolve2, reject, timeoutId };
8656
8655
  this.worker?.postMessage({
8657
8656
  type: "INIT",
8658
8657
  dataPath: this.options.dataPath
@@ -8675,7 +8674,7 @@ class TreeSitterClient extends EventEmitter2 {
8675
8674
  return normalizeBunfsPath(parse(path).base);
8676
8675
  }
8677
8676
  if (!isAbsolute(path)) {
8678
- return resolve2(path);
8677
+ return resolve(path);
8679
8678
  }
8680
8679
  return path;
8681
8680
  }
@@ -8693,8 +8692,8 @@ class TreeSitterClient extends EventEmitter2 {
8693
8692
  }
8694
8693
  async getPerformance() {
8695
8694
  const messageId = `performance_${this.messageIdCounter++}`;
8696
- return new Promise((resolve3) => {
8697
- this.messageCallbacks.set(messageId, resolve3);
8695
+ return new Promise((resolve2) => {
8696
+ this.messageCallbacks.set(messageId, resolve2);
8698
8697
  this.worker?.postMessage({ type: "GET_PERFORMANCE", messageId });
8699
8698
  });
8700
8699
  }
@@ -8707,8 +8706,8 @@ class TreeSitterClient extends EventEmitter2 {
8707
8706
  }
8708
8707
  }
8709
8708
  const messageId = `oneshot_${this.messageIdCounter++}`;
8710
- return new Promise((resolve3) => {
8711
- this.messageCallbacks.set(messageId, resolve3);
8709
+ return new Promise((resolve2) => {
8710
+ this.messageCallbacks.set(messageId, resolve2);
8712
8711
  this.worker?.postMessage({
8713
8712
  type: "ONESHOT_HIGHLIGHT",
8714
8713
  content,
@@ -8812,20 +8811,13 @@ class TreeSitterClient extends EventEmitter2 {
8812
8811
  const { logType, data } = event.data;
8813
8812
  const message = data.join(" ");
8814
8813
  this.emit("worker:log", logType, message);
8815
- if (logType === "log") {
8816
- console.log("TSWorker:", ...data);
8817
- } else if (logType === "error") {
8818
- console.error("TSWorker:", ...data);
8819
- } else if (logType === "warn") {
8820
- console.warn("TSWorker:", ...data);
8821
- }
8822
8814
  return;
8823
8815
  }
8824
8816
  }
8825
8817
  async preloadParser(filetype) {
8826
8818
  const messageId = `has_parser_${this.messageIdCounter++}`;
8827
- const response = await new Promise((resolve3) => {
8828
- this.messageCallbacks.set(messageId, resolve3);
8819
+ const response = await new Promise((resolve2) => {
8820
+ this.messageCallbacks.set(messageId, resolve2);
8829
8821
  this.worker?.postMessage({
8830
8822
  type: "PRELOAD_PARSER",
8831
8823
  filetype,
@@ -8852,8 +8844,8 @@ class TreeSitterClient extends EventEmitter2 {
8852
8844
  }
8853
8845
  this.buffers.set(id, { id, content, filetype, version, hasParser: false });
8854
8846
  const messageId = `init_${this.messageIdCounter++}`;
8855
- const response = await new Promise((resolve3) => {
8856
- this.messageCallbacks.set(messageId, resolve3);
8847
+ const response = await new Promise((resolve2) => {
8848
+ this.messageCallbacks.set(messageId, resolve2);
8857
8849
  this.worker?.postMessage({
8858
8850
  type: "INITIALIZE_PARSER",
8859
8851
  bufferId: id,
@@ -8909,9 +8901,9 @@ class TreeSitterClient extends EventEmitter2 {
8909
8901
  this.editQueues.delete(bufferId);
8910
8902
  }
8911
8903
  if (this.worker) {
8912
- await new Promise((resolve3) => {
8904
+ await new Promise((resolve2) => {
8913
8905
  const messageId = `dispose_${bufferId}`;
8914
- this.messageCallbacks.set(messageId, resolve3);
8906
+ this.messageCallbacks.set(messageId, resolve2);
8915
8907
  try {
8916
8908
  this.worker.postMessage({
8917
8909
  type: "DISPOSE_BUFFER",
@@ -8919,13 +8911,13 @@ class TreeSitterClient extends EventEmitter2 {
8919
8911
  });
8920
8912
  } catch (error) {
8921
8913
  console.error("Error disposing buffer", error);
8922
- resolve3(false);
8914
+ resolve2(false);
8923
8915
  }
8924
8916
  setTimeout(() => {
8925
8917
  if (this.messageCallbacks.has(messageId)) {
8926
8918
  this.messageCallbacks.delete(messageId);
8927
8919
  console.warn({ bufferId }, "Timed out waiting for buffer to be disposed");
8928
- resolve3(false);
8920
+ resolve2(false);
8929
8921
  }
8930
8922
  }, 3000);
8931
8923
  });
@@ -8982,12 +8974,12 @@ class TreeSitterClient extends EventEmitter2 {
8982
8974
  this.options.dataPath = dataPath;
8983
8975
  if (this.initialized && this.worker) {
8984
8976
  const messageId = `update_datapath_${this.messageIdCounter++}`;
8985
- return new Promise((resolve3, reject) => {
8977
+ return new Promise((resolve2, reject) => {
8986
8978
  this.messageCallbacks.set(messageId, (response) => {
8987
8979
  if (response.error) {
8988
8980
  reject(new Error(response.error));
8989
8981
  } else {
8990
- resolve3();
8982
+ resolve2();
8991
8983
  }
8992
8984
  });
8993
8985
  this.worker.postMessage({
@@ -9003,12 +8995,12 @@ class TreeSitterClient extends EventEmitter2 {
9003
8995
  throw new Error("Cannot clear cache: client is not initialized");
9004
8996
  }
9005
8997
  const messageId = `clear_cache_${this.messageIdCounter++}`;
9006
- return new Promise((resolve3, reject) => {
8998
+ return new Promise((resolve2, reject) => {
9007
8999
  this.messageCallbacks.set(messageId, (response) => {
9008
9000
  if (response.error) {
9009
9001
  reject(new Error(response.error));
9010
9002
  } else {
9011
- resolve3();
9003
+ resolve2();
9012
9004
  }
9013
9005
  });
9014
9006
  this.worker.postMessage({
@@ -9534,26 +9526,13 @@ ${content}`);
9534
9526
  return "./" + path4.relative(path4.dirname(outputPath), queryPath);
9535
9527
  }
9536
9528
  async function generateDefaultParsersFile(parsers, outputPath) {
9537
- const imports = parsers.map((parser) => {
9538
- const safeFiletype = parser.filetype.replace(/[^a-zA-Z0-9]/g, "_");
9539
- const lines = [
9540
- `import ${safeFiletype}_highlights from "${parser.highlightsPath}" with { type: "file" }`,
9541
- `import ${safeFiletype}_language from "${parser.languagePath}" with { type: "file" }`
9542
- ];
9543
- if (parser.injectionsPath) {
9544
- lines.push(`import ${safeFiletype}_injections from "${parser.injectionsPath}" with { type: "file" }`);
9545
- }
9546
- return lines.join(`
9547
- `);
9548
- }).join(`
9549
- `);
9550
9529
  const parserDefinitions = parsers.map((parser) => {
9551
9530
  const safeFiletype = parser.filetype.replace(/[^a-zA-Z0-9]/g, "_");
9552
9531
  const queriesLines = [
9553
- ` highlights: [resolve(dirname(fileURLToPath(import.meta.url)), ${safeFiletype}_highlights)],`
9532
+ ` highlights: [fileURLToPath(new URL("${parser.highlightsPath}", import.meta.url))],`
9554
9533
  ];
9555
9534
  if (parser.injectionsPath) {
9556
- queriesLines.push(` injections: [resolve(dirname(fileURLToPath(import.meta.url)), ${safeFiletype}_injections)],`);
9535
+ queriesLines.push(` injections: [fileURLToPath(new URL("${parser.injectionsPath}", import.meta.url))],`);
9557
9536
  }
9558
9537
  const injectionMappingLine = parser.injectionMapping ? ` injectionMapping: ${JSON.stringify(parser.injectionMapping, null, 10)},` : "";
9559
9538
  const aliasesLine = parser.aliases?.length ? ` aliases: ${JSON.stringify(parser.aliases)},` : "";
@@ -9564,7 +9543,7 @@ ${aliasesLine ? aliasesLine + `
9564
9543
  ${queriesLines.join(`
9565
9544
  `)}
9566
9545
  },
9567
- wasm: resolve(dirname(fileURLToPath(import.meta.url)), ${safeFiletype}_language),${injectionMappingLine ? `
9546
+ wasm: fileURLToPath(new URL("${parser.languagePath}", import.meta.url)),${injectionMappingLine ? `
9568
9547
  ` + injectionMappingLine : ""}
9569
9548
  }`;
9570
9549
  }).join(`,
@@ -9574,11 +9553,8 @@ ${queriesLines.join(`
9574
9553
  // Last generated: ${new Date().toISOString()}
9575
9554
 
9576
9555
  import type { FiletypeParserOptions } from "./types"
9577
- import { resolve, dirname } from "path"
9578
9556
  import { fileURLToPath } from "url"
9579
9557
 
9580
- ${imports}
9581
-
9582
9558
  // Cached parsers to avoid re-resolving paths on every call
9583
9559
  let _cachedParsers: FiletypeParserOptions[] | undefined
9584
9560
 
@@ -10470,7 +10446,7 @@ class TerminalPalette {
10470
10446
  const out = this.stdout;
10471
10447
  if (!out.isTTY || !this.stdin.isTTY)
10472
10448
  return false;
10473
- return new Promise((resolve4) => {
10449
+ return new Promise((resolve3) => {
10474
10450
  const session = this.createQuerySession();
10475
10451
  let buffer = "";
10476
10452
  let settled = false;
@@ -10479,7 +10455,7 @@ class TerminalPalette {
10479
10455
  return;
10480
10456
  settled = true;
10481
10457
  session.cleanup();
10482
- resolve4(supported);
10458
+ resolve3(supported);
10483
10459
  };
10484
10460
  const onData = (chunk) => {
10485
10461
  buffer += chunk.toString();
@@ -10502,7 +10478,7 @@ class TerminalPalette {
10502
10478
  if (!out.isTTY || !this.stdin.isTTY) {
10503
10479
  return results;
10504
10480
  }
10505
- return new Promise((resolve4) => {
10481
+ return new Promise((resolve3) => {
10506
10482
  const session = this.createQuerySession();
10507
10483
  let buffer = "";
10508
10484
  let idleTimer = null;
@@ -10512,7 +10488,7 @@ class TerminalPalette {
10512
10488
  return;
10513
10489
  settled = true;
10514
10490
  session.cleanup();
10515
- resolve4(results);
10491
+ resolve3(results);
10516
10492
  };
10517
10493
  const onData = (chunk) => {
10518
10494
  buffer += chunk.toString();
@@ -10553,7 +10529,7 @@ class TerminalPalette {
10553
10529
  if (!out.isTTY || !this.stdin.isTTY) {
10554
10530
  return results;
10555
10531
  }
10556
- return new Promise((resolve4) => {
10532
+ return new Promise((resolve3) => {
10557
10533
  const session = this.createQuerySession();
10558
10534
  let buffer = "";
10559
10535
  let idleTimer = null;
@@ -10563,7 +10539,7 @@ class TerminalPalette {
10563
10539
  return;
10564
10540
  settled = true;
10565
10541
  session.cleanup();
10566
- resolve4(results);
10542
+ resolve3(results);
10567
10543
  };
10568
10544
  const onData = (chunk) => {
10569
10545
  buffer += chunk.toString();
@@ -10700,7 +10676,7 @@ import { EventEmitter as EventEmitter4 } from "events";
10700
10676
 
10701
10677
  // src/buffer.ts
10702
10678
  import { toArrayBuffer, ptr } from "bun:ffi";
10703
- function packDrawOptions(border2, shouldFill, titleAlignment) {
10679
+ function packDrawOptions(border2, shouldFill, titleAlignment, bottomTitleAlignment) {
10704
10680
  let packed = 0;
10705
10681
  if (border2 === true) {
10706
10682
  packed |= 15;
@@ -10723,7 +10699,9 @@ function packDrawOptions(border2, shouldFill, titleAlignment) {
10723
10699
  right: 2
10724
10700
  };
10725
10701
  const alignment = alignmentMap[titleAlignment];
10702
+ const bottomAlignment = alignmentMap[bottomTitleAlignment];
10726
10703
  packed |= alignment << 5;
10704
+ packed |= bottomAlignment << 7;
10727
10705
  return packed;
10728
10706
  }
10729
10707
 
@@ -10955,8 +10933,8 @@ class OptimizedBuffer {
10955
10933
  this.guard();
10956
10934
  const style = parseBorderStyle(options.borderStyle, "single");
10957
10935
  const borderChars = options.customBorderChars ?? BorderCharArrays[style];
10958
- const packedOptions = packDrawOptions(options.border, options.shouldFill ?? false, options.titleAlignment || "left");
10959
- this.lib.bufferDrawBox(this.bufferPtr, options.x, options.y, options.width, options.height, borderChars, packedOptions, options.borderColor, options.backgroundColor, options.title ?? null);
10936
+ const packedOptions = packDrawOptions(options.border, options.shouldFill ?? false, options.titleAlignment || "left", options.bottomTitleAlignment || "left");
10937
+ this.lib.bufferDrawBox(this.bufferPtr, options.x, options.y, options.width, options.height, borderChars, packedOptions, options.borderColor, options.backgroundColor, options.title ?? null, options.bottomTitle ?? null);
10960
10938
  }
10961
10939
  pushScissorRect(x, y, width, height) {
10962
10940
  this.guard();
@@ -12084,7 +12062,7 @@ function getOpenTUILib(libPath) {
12084
12062
  returns: "void"
12085
12063
  },
12086
12064
  bufferDrawBox: {
12087
- args: ["ptr", "i32", "i32", "u32", "u32", "ptr", "u32", "ptr", "ptr", "ptr", "u32"],
12065
+ args: ["ptr", "i32", "i32", "u32", "u32", "ptr", "u32", "ptr", "ptr", "ptr", "u32", "ptr", "u32"],
12088
12066
  returns: "void"
12089
12067
  },
12090
12068
  bufferPushScissorRect: {
@@ -13252,11 +13230,14 @@ class FFIRenderLib {
13252
13230
  });
13253
13231
  this.opentui.symbols.bufferDrawGrid(buffer, borderChars, borderFg.buffer, borderBg.buffer, columnOffsets, columnCount, rowOffsets, rowCount, ptr4(optionsBuffer));
13254
13232
  }
13255
- bufferDrawBox(buffer, x, y, width, height, borderChars, packedOptions, borderColor, backgroundColor, title) {
13233
+ bufferDrawBox(buffer, x, y, width, height, borderChars, packedOptions, borderColor, backgroundColor, title, bottomTitle) {
13256
13234
  const titleBytes = title ? this.encoder.encode(title) : null;
13257
13235
  const titleLen = title ? titleBytes.length : 0;
13258
13236
  const titlePtr = title ? titleBytes : null;
13259
- this.opentui.symbols.bufferDrawBox(buffer, x, y, width, height, borderChars, packedOptions, borderColor.buffer, backgroundColor.buffer, titlePtr, titleLen);
13237
+ const bottomTitleBytes = bottomTitle ? this.encoder.encode(bottomTitle) : null;
13238
+ const bottomTitleLen = bottomTitle ? bottomTitleBytes.length : 0;
13239
+ const bottomTitlePtr = bottomTitle ? bottomTitleBytes : null;
13240
+ this.opentui.symbols.bufferDrawBox(buffer, x, y, width, height, borderChars, packedOptions, borderColor.buffer, backgroundColor.buffer, titlePtr, titleLen, bottomTitlePtr, bottomTitleLen);
13260
13241
  }
13261
13242
  bufferResize(buffer, width, height) {
13262
13243
  this.opentui.symbols.bufferResize(buffer, width, height);
@@ -14650,6 +14631,7 @@ class Renderable extends BaseRenderable {
14650
14631
  frameBuffer = null;
14651
14632
  _focusable = false;
14652
14633
  _focused = false;
14634
+ _hasFocusedDescendant = false;
14653
14635
  keypressHandler = null;
14654
14636
  pasteHandler = null;
14655
14637
  _live = false;
@@ -14799,11 +14781,24 @@ class Renderable extends BaseRenderable {
14799
14781
  };
14800
14782
  this.ctx._internalKeyInput.onInternal("keypress", this.keypressHandler);
14801
14783
  this.ctx._internalKeyInput.onInternal("paste", this.pasteHandler);
14784
+ this.propagateFocusChange(true);
14802
14785
  this.emit("focused" /* FOCUSED */);
14803
14786
  }
14787
+ propagateFocusChange(hasFocus) {
14788
+ let parent = this.parent;
14789
+ while (parent) {
14790
+ if (parent._hasFocusedDescendant !== hasFocus) {
14791
+ parent._hasFocusedDescendant = hasFocus;
14792
+ parent.markDirty();
14793
+ }
14794
+ parent = parent.parent;
14795
+ }
14796
+ this.requestRender();
14797
+ }
14804
14798
  blur() {
14805
14799
  if (!this._focused || !this._focusable)
14806
14800
  return;
14801
+ this._ctx.blurRenderable(this);
14807
14802
  this._focused = false;
14808
14803
  this.requestRender();
14809
14804
  if (this.keypressHandler) {
@@ -14814,11 +14809,15 @@ class Renderable extends BaseRenderable {
14814
14809
  this.ctx._internalKeyInput.offInternal("paste", this.pasteHandler);
14815
14810
  this.pasteHandler = null;
14816
14811
  }
14812
+ this.propagateFocusChange(false);
14817
14813
  this.emit("blurred" /* BLURRED */);
14818
14814
  }
14819
14815
  get focused() {
14820
14816
  return this._focused;
14821
14817
  }
14818
+ get hasFocusedDescendant() {
14819
+ return this._hasFocusedDescendant;
14820
+ }
14822
14821
  get live() {
14823
14822
  return this._live;
14824
14823
  }
@@ -15354,7 +15353,10 @@ class Renderable extends BaseRenderable {
15354
15353
  }
15355
15354
  try {
15356
15355
  const widthMethod = this._ctx.widthMethod;
15357
- this.frameBuffer = OptimizedBuffer.create(w, h, widthMethod, { respectAlpha: true, id: `framebuffer-${this.id}` });
15356
+ this.frameBuffer = OptimizedBuffer.create(w, h, widthMethod, {
15357
+ respectAlpha: true,
15358
+ id: `framebuffer-${this.id}`
15359
+ });
15358
15360
  } catch (error) {
15359
15361
  console.error(`Failed to create frame buffer for ${this.id}:`, error);
15360
15362
  this.frameBuffer = null;
@@ -15741,7 +15743,14 @@ class Renderable extends BaseRenderable {
15741
15743
  class RootRenderable extends Renderable {
15742
15744
  renderList = [];
15743
15745
  constructor(ctx) {
15744
- super(ctx, { id: "__root__", zIndex: 0, visible: true, width: ctx.width, height: ctx.height, enableLayout: true });
15746
+ super(ctx, {
15747
+ id: "__root__",
15748
+ zIndex: 0,
15749
+ visible: true,
15750
+ width: ctx.width,
15751
+ height: ctx.height,
15752
+ enableLayout: true
15753
+ });
15745
15754
  if (this.yogaNode) {
15746
15755
  this.yogaNode.free();
15747
15756
  }
@@ -16583,6 +16592,41 @@ function mergeKeyBindings(defaults, custom) {
16583
16592
  function getKeyBindingKey(binding) {
16584
16593
  return `${binding.name}:${binding.ctrl ? 1 : 0}:${binding.shift ? 1 : 0}:${binding.meta ? 1 : 0}:${binding.super ? 1 : 0}`;
16585
16594
  }
16595
+ function getBaseCodeKeyName(baseCode) {
16596
+ if (baseCode === undefined || baseCode < 32 || baseCode === 127) {
16597
+ return;
16598
+ }
16599
+ try {
16600
+ const name = String.fromCodePoint(baseCode);
16601
+ if (name.length === 1 && name >= "A" && name <= "Z") {
16602
+ return name.toLowerCase();
16603
+ }
16604
+ return name;
16605
+ } catch {
16606
+ return;
16607
+ }
16608
+ }
16609
+ function getKeyBindingKeys(binding) {
16610
+ const names = new Set([binding.name]);
16611
+ const baseCodeName = getBaseCodeKeyName(binding.baseCode);
16612
+ if (baseCodeName) {
16613
+ names.add(baseCodeName);
16614
+ }
16615
+ return [...names].map((name) => getKeyBindingKey({ ...binding, name }));
16616
+ }
16617
+ function getKeyBindingAction(map, binding) {
16618
+ for (const key of getKeyBindingKeys(binding)) {
16619
+ const action = map.get(key);
16620
+ if (action !== undefined) {
16621
+ return action;
16622
+ }
16623
+ }
16624
+ return;
16625
+ }
16626
+ function matchesKeyBinding(binding, match) {
16627
+ const matchKey = getKeyBindingKey(match);
16628
+ return getKeyBindingKeys(binding).includes(matchKey);
16629
+ }
16586
16630
  function buildKeyBindingsMap(bindings, aliasMap) {
16587
16631
  const map = new Map;
16588
16632
  const aliases = aliasMap || {};
@@ -16966,15 +17010,7 @@ class TerminalConsole extends EventEmitter8 {
16966
17010
  this.blur();
16967
17011
  return;
16968
17012
  }
16969
- const bindingKey = getKeyBindingKey({
16970
- name: event.name,
16971
- ctrl: event.ctrl,
16972
- shift: event.shift,
16973
- meta: event.meta,
16974
- super: event.super,
16975
- action: "scroll-up"
16976
- });
16977
- const action = this._keyBindingsMap.get(bindingKey);
17013
+ const action = getKeyBindingAction(this._keyBindingsMap, event);
16978
17014
  if (action) {
16979
17015
  const handler = this._actionHandlers.get(action);
16980
17016
  if (handler) {
@@ -18250,6 +18286,8 @@ class EditBufferRenderable extends Renderable {
18250
18286
  const cursor = this.editorView.getCursor();
18251
18287
  if (cursor.col > 0) {
18252
18288
  this.editBuffer.deleteRange(cursor.row, 0, cursor.row, cursor.col);
18289
+ } else if (cursor.row > 0) {
18290
+ this.editBuffer.deleteCharBackward();
18253
18291
  }
18254
18292
  this.requestRender();
18255
18293
  return true;
@@ -18843,7 +18881,7 @@ var rendererTracker = singleton("RendererTracker", () => {
18843
18881
  });
18844
18882
  async function createCliRenderer(config = {}) {
18845
18883
  if (process.argv.includes("--delay-start")) {
18846
- await new Promise((resolve4) => setTimeout(resolve4, 5000));
18884
+ await new Promise((resolve3) => setTimeout(resolve3, 5000));
18847
18885
  }
18848
18886
  const stdin = config.stdin || process.stdin;
18849
18887
  const stdout = config.stdout || process.stdout;
@@ -19003,7 +19041,11 @@ class CliRenderer extends EventEmitter9 {
19003
19041
  _capabilities = null;
19004
19042
  _latestPointer = { x: 0, y: 0 };
19005
19043
  _hasPointer = false;
19006
- _lastPointerModifiers = { shift: false, alt: false, ctrl: false };
19044
+ _lastPointerModifiers = {
19045
+ shift: false,
19046
+ alt: false,
19047
+ ctrl: false
19048
+ };
19007
19049
  _currentMousePointerStyle = undefined;
19008
19050
  _currentFocusedRenderable = null;
19009
19051
  lifecyclePasses = new Set;
@@ -19093,8 +19135,7 @@ Captured output:
19093
19135
  "SIGHUP",
19094
19136
  "SIGBREAK",
19095
19137
  "SIGPIPE",
19096
- "SIGBUS",
19097
- "SIGFPE"
19138
+ "SIGBUS"
19098
19139
  ];
19099
19140
  this.clipboard = new Clipboard(this.lib, this.rendererPtr);
19100
19141
  this.resizeDebounceDelay = config.debounceDelay || 100;
@@ -19124,7 +19165,7 @@ Captured output:
19124
19165
  const useKittyForParsing = kittyConfig !== null;
19125
19166
  this._keyHandler = new InternalKeyHandler;
19126
19167
  this._keyHandler.on("keypress", (event) => {
19127
- if (this.exitOnCtrlC && event.name === "c" && event.ctrl) {
19168
+ if (this.exitOnCtrlC && matchesKeyBinding(event, { name: "c", ctrl: true })) {
19128
19169
  process.nextTick(() => {
19129
19170
  this.destroy();
19130
19171
  });
@@ -19235,15 +19276,18 @@ Captured output:
19235
19276
  if (this._currentFocusedRenderable === renderable)
19236
19277
  return;
19237
19278
  const prev = this.currentFocusedEditor;
19238
- if (this._currentFocusedRenderable) {
19239
- this._currentFocusedRenderable.blur();
19240
- }
19279
+ this._currentFocusedRenderable?.blur();
19241
19280
  this._currentFocusedRenderable = renderable;
19242
19281
  const next = this.currentFocusedEditor;
19243
19282
  if (prev !== next) {
19244
19283
  this.emit("focused_editor" /* FOCUSED_EDITOR */, next, prev);
19245
19284
  }
19246
19285
  }
19286
+ blurRenderable(renderable) {
19287
+ if (this._currentFocusedRenderable === renderable) {
19288
+ this._currentFocusedRenderable = null;
19289
+ }
19290
+ }
19247
19291
  setCapturedRenderable(renderable) {
19248
19292
  if (this.capturedRenderable === renderable) {
19249
19293
  return;
@@ -19335,8 +19379,8 @@ Captured output:
19335
19379
  if (!this.isIdleNow())
19336
19380
  return;
19337
19381
  const resolvers = this.idleResolvers.splice(0);
19338
- for (const resolve4 of resolvers) {
19339
- resolve4();
19382
+ for (const resolve3 of resolvers) {
19383
+ resolve3();
19340
19384
  }
19341
19385
  }
19342
19386
  idle() {
@@ -19344,8 +19388,8 @@ Captured output:
19344
19388
  return Promise.resolve();
19345
19389
  if (this.isIdleNow())
19346
19390
  return Promise.resolve();
19347
- return new Promise((resolve4) => {
19348
- this.idleResolvers.push(resolve4);
19391
+ return new Promise((resolve3) => {
19392
+ this.idleResolvers.push(resolve3);
19349
19393
  });
19350
19394
  }
19351
19395
  get resolution() {
@@ -19823,14 +19867,20 @@ Captured output:
19823
19867
  if (mouseEvent.type === "drag" && this.currentSelection?.isDragging) {
19824
19868
  this.updateSelection(maybeRenderable, mouseEvent.x, mouseEvent.y);
19825
19869
  if (maybeRenderable) {
19826
- const event2 = new MouseEvent(maybeRenderable, { ...mouseEvent, isDragging: true });
19870
+ const event2 = new MouseEvent(maybeRenderable, {
19871
+ ...mouseEvent,
19872
+ isDragging: true
19873
+ });
19827
19874
  maybeRenderable.processMouseEvent(event2);
19828
19875
  }
19829
19876
  return true;
19830
19877
  }
19831
19878
  if (mouseEvent.type === "up" && this.currentSelection?.isDragging) {
19832
19879
  if (maybeRenderable) {
19833
- const event2 = new MouseEvent(maybeRenderable, { ...mouseEvent, isDragging: true });
19880
+ const event2 = new MouseEvent(maybeRenderable, {
19881
+ ...mouseEvent,
19882
+ isDragging: true
19883
+ });
19834
19884
  maybeRenderable.processMouseEvent(event2);
19835
19885
  }
19836
19886
  this.finishSelection();
@@ -19845,7 +19895,10 @@ Captured output:
19845
19895
  }
19846
19896
  if (!sameElement && (mouseEvent.type === "drag" || mouseEvent.type === "move")) {
19847
19897
  if (this.lastOverRenderable && this.lastOverRenderable !== this.capturedRenderable && !this.lastOverRenderable.isDestroyed) {
19848
- const event2 = new MouseEvent(this.lastOverRenderable, { ...mouseEvent, type: "out" });
19898
+ const event2 = new MouseEvent(this.lastOverRenderable, {
19899
+ ...mouseEvent,
19900
+ type: "out"
19901
+ });
19849
19902
  this.lastOverRenderable.processMouseEvent(event2);
19850
19903
  }
19851
19904
  this.lastOverRenderable = maybeRenderable;
@@ -19864,7 +19917,10 @@ Captured output:
19864
19917
  return true;
19865
19918
  }
19866
19919
  if (this.capturedRenderable && mouseEvent.type === "up") {
19867
- const event2 = new MouseEvent(this.capturedRenderable, { ...mouseEvent, type: "drag-end" });
19920
+ const event2 = new MouseEvent(this.capturedRenderable, {
19921
+ ...mouseEvent,
19922
+ type: "drag-end"
19923
+ });
19868
19924
  this.capturedRenderable.processMouseEvent(event2);
19869
19925
  this.capturedRenderable.processMouseEvent(new MouseEvent(this.capturedRenderable, mouseEvent));
19870
19926
  if (maybeRenderable) {
@@ -20272,6 +20328,7 @@ Captured output:
20272
20328
  pixelResolutionQueryActive: false,
20273
20329
  explicitWidthCprActive: false
20274
20330
  }, true);
20331
+ this._useMouse = false;
20275
20332
  this.setCapturedRenderable(undefined);
20276
20333
  this.stdin.removeListener("data", this.stdinListener);
20277
20334
  if (this.stdin.setRawMode) {
@@ -20602,7 +20659,7 @@ Captured output:
20602
20659
  }
20603
20660
  }
20604
20661
 
20605
- export { __toESM, __commonJS, __export, __require, Edge, Gutter, MeasureMode, exports_src, isValidBorderStyle, parseBorderStyle, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, KeyEvent, PasteEvent, KeyHandler, InternalKeyHandler, RGBA, hexToRgb, rgbToHex, hsvToRgb, parseColor, fonts, measureText, getCharacterPositions, coordinateToCharacterIndex, renderFontToFrameBuffer, TextAttributes, ATTRIBUTE_BASE_BITS, ATTRIBUTE_BASE_MASK, getBaseAttributes, DebugOverlayCorner, TargetChannel, createTextAttributes, attributesWithLink, getLinkId, 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, link, t, hastToStyledText, SystemClock, nonAlphanumericKeys, parseKeypress, LinearScrollAccel, MacOSScrollAccel, parseAlign, parseAlignItems, parseBoxSizing, parseDimension, parseDirection, parseDisplay, parseEdge, parseFlexDirection, parseGutter, parseJustify, parseLogLevel, parseMeasureMode, parseOverflow, parsePositionType, parseUnit, parseWrap, MouseParser, Selection, convertGlobalToLocalSelection, ASCIIFontSelectionHelper, envRegistry, registerEnvVar, clearEnvCache, generateEnvMarkdown, generateEnvColored, env, StdinParser, treeSitterToTextChunks, treeSitterToStyledText, addDefaultParsers, TreeSitterClient, DataPathsManager, getDataPaths, extensionToFiletype, basenameToFiletype, extToFiletype, pathToFiletype, infoStringToFiletype, main, getTreeSitterClient, ExtmarksController, createExtmarksController, TerminalPalette, createTerminalPalette, decodePasteBytes, stripAnsiSequences, detectLinks, TextBuffer, SpanInfoStruct, LogLevel2 as LogLevel, setRenderLibPath, resolveRenderLib, OptimizedBuffer, h, isVNode, maybeMakeRenderable, wrapWithDelegates, instantiate, delegate, isValidPercentage, LayoutEvents, RenderableEvents, isRenderable, BaseRenderable, Renderable, RootRenderable, EditBuffer, EditorView, ANSI, defaultKeyAliases, mergeKeyAliases, mergeKeyBindings, getKeyBindingKey, buildKeyBindingsMap, capture, ConsolePosition, TerminalConsole, getObjectsInViewport, EditBufferRenderableEvents, isEditBufferRenderable, EditBufferRenderable, buildKittyKeyboardFlags, MouseEvent, MouseButton, createCliRenderer, CliRenderEvents, RendererControlState, CliRenderer };
20662
+ export { __toESM, __commonJS, __export, __require, Edge, Gutter, MeasureMode, exports_src, isValidBorderStyle, parseBorderStyle, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, KeyEvent, PasteEvent, KeyHandler, InternalKeyHandler, RGBA, hexToRgb, rgbToHex, hsvToRgb, parseColor, fonts, measureText, getCharacterPositions, coordinateToCharacterIndex, renderFontToFrameBuffer, TextAttributes, ATTRIBUTE_BASE_BITS, ATTRIBUTE_BASE_MASK, getBaseAttributes, DebugOverlayCorner, TargetChannel, createTextAttributes, attributesWithLink, getLinkId, 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, link, t, hastToStyledText, SystemClock, nonAlphanumericKeys, parseKeypress, LinearScrollAccel, MacOSScrollAccel, parseAlign, parseAlignItems, parseBoxSizing, parseDimension, parseDirection, parseDisplay, parseEdge, parseFlexDirection, parseGutter, parseJustify, parseLogLevel, parseMeasureMode, parseOverflow, parsePositionType, parseUnit, parseWrap, MouseParser, Selection, convertGlobalToLocalSelection, ASCIIFontSelectionHelper, envRegistry, registerEnvVar, clearEnvCache, generateEnvMarkdown, generateEnvColored, env, StdinParser, treeSitterToTextChunks, treeSitterToStyledText, addDefaultParsers, TreeSitterClient, DataPathsManager, getDataPaths, extensionToFiletype, basenameToFiletype, extToFiletype, pathToFiletype, infoStringToFiletype, main, getTreeSitterClient, ExtmarksController, createExtmarksController, TerminalPalette, createTerminalPalette, decodePasteBytes, stripAnsiSequences, detectLinks, TextBuffer, SpanInfoStruct, LogLevel2 as LogLevel, setRenderLibPath, resolveRenderLib, OptimizedBuffer, h, isVNode, maybeMakeRenderable, wrapWithDelegates, instantiate, delegate, isValidPercentage, LayoutEvents, RenderableEvents, isRenderable, BaseRenderable, Renderable, RootRenderable, EditBuffer, EditorView, ANSI, defaultKeyAliases, mergeKeyAliases, mergeKeyBindings, getKeyBindingAction, buildKeyBindingsMap, capture, ConsolePosition, TerminalConsole, getObjectsInViewport, EditBufferRenderableEvents, isEditBufferRenderable, EditBufferRenderable, buildKittyKeyboardFlags, MouseEvent, MouseButton, createCliRenderer, CliRenderEvents, RendererControlState, CliRenderer };
20606
20663
 
20607
- //# debugId=D3013A6779DE950364756E2164756E21
20608
- //# sourceMappingURL=index-vy1rm1x3.js.map
20664
+ //# debugId=62BA1E72DD78CA1964756E2164756E21
20665
+ //# sourceMappingURL=index-e4g80551.js.map