UNPKG

@opentui/core

Version:

OpenTUI is a TypeScript library on a native Zig core for building terminal user interfaces (TUIs)

10,413 lines 344 kB
// @bun
import {
  Clipboard,
  InternalKeyHandler,
  KeyHandler,
  NativeMeasureTargetKind,
  OptimizedBuffer,
  RGBA,
  Selection,
  SpanInfoStruct,
  StdinParser,
  StyledText,
  SystemClock,
  TextBuffer,
  borderCharsToArray,
  buildTerminalPaletteSignature,
  convertGlobalToLocalSelection,
  createExtmarksController,
  createTerminalPalette,
  createTextAttributes,
  destroyTreeSitterClient,
  env,
  getBorderSides,
  getTreeSitterClient,
  isStyledText,
  normalizeTerminalPalette,
  parseAlign,
  parseAlignItems,
  parseBorderStyle,
  parseColor,
  parseFlexDirection,
  parseJustify,
  parseOverflow,
  parsePositionType,
  parseWrap,
  registerEnvVar,
  resolveRenderLib,
  singleton,
  sleep,
  stringToStyledText,
  toArrayBuffer,
  treeSitterToTextChunks,
  yoga_default
} from "./chunk-bun-9gqvxy8c.js";

// src/Renderable.ts
import { EventEmitter } from "events";

// src/lib/renderable.validations.ts
function validateOptions(id, options) {
  if (typeof options.width === "number") {
    if (options.width < 0) {
      throw new TypeError(`Invalid width for Renderable ${id}: ${options.width}`);
    }
  }
  if (typeof options.height === "number") {
    if (options.height < 0) {
      throw new TypeError(`Invalid height for Renderable ${id}: ${options.height}`);
    }
  }
}
function isValidPercentage(value) {
  if (typeof value === "string" && value.endsWith("%")) {
    const numPart = value.slice(0, -1);
    const num = parseFloat(numPart);
    return !Number.isNaN(num);
  }
  return false;
}
function isMarginType(value) {
  if (typeof value === "number" && !Number.isNaN(value)) {
    return true;
  }
  if (value === "auto") {
    return true;
  }
  return isValidPercentage(value);
}
function isPaddingType(value) {
  if (typeof value === "number" && !Number.isNaN(value)) {
    return true;
  }
  return isValidPercentage(value);
}
function isPositionType(value) {
  if (typeof value === "number" && !Number.isNaN(value)) {
    return true;
  }
  if (value === "auto") {
    return true;
  }
  return isValidPercentage(value);
}
function isPositionTypeType(value) {
  return value === "relative" || value === "absolute";
}
function isOverflowType(value) {
  return value === "visible" || value === "hidden" || value === "scroll";
}
function isDimensionType(value) {
  return isPositionType(value);
}
function isFlexBasisType(value) {
  if (value === undefined || value === "auto") {
    return true;
  }
  if (typeof value === "number" && !Number.isNaN(value)) {
    return true;
  }
  return false;
}
function isSizeType(value) {
  if (value === undefined) {
    return true;
  }
  if (typeof value === "number" && !Number.isNaN(value)) {
    return true;
  }
  return isValidPercentage(value);
}

// src/Renderable.ts
var BrandedRenderable = Symbol.for("@opentui/core/Renderable");
var LayoutEvents;
((LayoutEvents2) => {
  LayoutEvents2["LAYOUT_CHANGED"] = "layout-changed";
  LayoutEvents2["RESIZED"] = "resized";
})(LayoutEvents ||= {});
var RenderableEvents;
((RenderableEvents2) => {
  RenderableEvents2["FOCUSED"] = "focused";
  RenderableEvents2["BLURRED"] = "blurred";
  RenderableEvents2["DESTROYED"] = "destroyed";
})(RenderableEvents ||= {});
function isRenderable(obj) {
  return !!obj?.[BrandedRenderable];
}

class BaseRenderable extends EventEmitter {
  [BrandedRenderable] = true;
  static renderableNumber = 1;
  _id;
  num;
  _dirty = false;
  parent = null;
  _visible = true;
  constructor(options) {
    super();
    this.num = BaseRenderable.renderableNumber++;
    this._id = options.id ?? `renderable-${this.num}`;
  }
  get id() {
    return this._id;
  }
  set id(value) {
    this._id = value;
  }
  get isDirty() {
    return this._dirty;
  }
  markClean() {
    this._dirty = false;
  }
  markDirty() {
    this._dirty = true;
  }
  destroy() {}
  destroyRecursively() {}
  get visible() {
    return this._visible;
  }
  set visible(value) {
    this._visible = value;
  }
}
function getLayoutGeneration(ctx) {
  return ctx.__otuiLayoutGeneration ?? 0;
}
function bumpLayoutGeneration(ctx) {
  const next = getLayoutGeneration(ctx) + 1;
  const generationContext = ctx;
  generationContext.__otuiLayoutGeneration = next;
  return next;
}
function getRenderListRevision(ctx) {
  return ctx.__otuiRenderListRevision ?? 0;
}
function bumpRenderListRevision(ctx) {
  const generationContext = ctx;
  generationContext.__otuiRenderListRevision = getRenderListRevision(ctx) + 1;
}

class Renderable extends BaseRenderable {
  static renderablesByNumber = new Map;
  _isDestroyed = false;
  _ctx;
  _translateX = 0;
  _translateY = 0;
  _x = 0;
  _y = 0;
  _screenX = 0;
  _screenY = 0;
  _width;
  _height;
  _widthValue = 0;
  _heightValue = 0;
  _zIndex;
  selectable = false;
  buffered;
  frameBuffer = null;
  _focusable = false;
  _focused = false;
  _hasFocusedDescendant = false;
  keypressHandler = null;
  pasteHandler = null;
  _live = false;
  _liveCount = 0;
  _sizeChangeListener = undefined;
  _mouseListener = null;
  _mouseListeners = {};
  _pasteListener = undefined;
  _keyListeners = {};
  yogaNode;
  _positionType = "relative";
  _overflow = "visible";
  _position = {};
  _opacity = 1;
  _flexShrink = 1;
  _childrenInLayoutOrder = [];
  _childrenInZIndexOrder = [];
  needsZIndexSort = false;
  parent = null;
  childrenPrimarySortDirty = true;
  childrenSortedByPrimaryAxis = [];
  _shouldUpdateBefore = new Set;
  _lastLayoutFrame = -1;
  onLifecyclePass = null;
  renderBefore;
  renderAfter;
  constructor(ctx, options) {
    super(options);
    this._ctx = ctx;
    Renderable.renderablesByNumber.set(this.num, this);
    validateOptions(this.id, options);
    this.renderBefore = options.renderBefore;
    this.renderAfter = options.renderAfter;
    this._width = options.width ?? "auto";
    this._height = options.height ?? "auto";
    if (typeof this._width === "number") {
      this._widthValue = this._width;
    }
    if (typeof this._height === "number") {
      this._heightValue = this._height;
    }
    this._zIndex = options.zIndex ?? 0;
    this._visible = options.visible !== false;
    this.buffered = options.buffered ?? false;
    this._live = options.live ?? false;
    this._liveCount = this._live && this._visible ? 1 : 0;
    this._opacity = options.opacity !== undefined ? Math.max(0, Math.min(1, options.opacity)) : 1;
    this.yogaNode = yoga_default.Node.createForOpenTUI();
    this.yogaNode.setDisplay(this._visible ? 0 /* Flex */ : 1 /* None */);
    this.setupYogaProperties(options);
    this.applyEventOptions(options);
    if (this.buffered) {
      this.createFrameBuffer();
    }
  }
  get focusable() {
    return this._focusable;
  }
  set focusable(value) {
    this._focusable = value;
  }
  get ctx() {
    return this._ctx;
  }
  get visible() {
    return this._visible;
  }
  get primaryAxis() {
    const dir = this.yogaNode.getFlexDirection();
    return dir === 2 || dir === 3 ? "row" : "column";
  }
  set visible(value) {
    if (this._visible === value)
      return;
    const wasVisible = this._visible;
    this._visible = value;
    this.yogaNode.setDisplay(value ? 0 /* Flex */ : 1 /* None */);
    bumpRenderListRevision(this._ctx);
    if (this._live) {
      if (!wasVisible && value) {
        this.propagateLiveCount(1);
      } else if (wasVisible && !value) {
        this.propagateLiveCount(-1);
      }
    }
    if (this._focused) {
      this.blur();
    }
    this.requestRender();
  }
  get opacity() {
    return this._opacity;
  }
  set opacity(value) {
    const clamped = Math.max(0, Math.min(1, value));
    if (this._opacity !== clamped) {
      this._opacity = clamped;
      bumpRenderListRevision(this._ctx);
      this.requestRender();
    }
  }
  hasSelection() {
    return false;
  }
  onSelectionChanged(selection) {
    return false;
  }
  getSelectedText() {
    return "";
  }
  shouldStartSelection(x, y) {
    return false;
  }
  focus() {
    if (this._isDestroyed || this._focused || !this._focusable)
      return;
    this._focused = true;
    this._ctx.focusRenderable(this);
    this.requestRender();
    this.keypressHandler = (key) => {
      if (this._isDestroyed)
        return;
      this._keyListeners["down"]?.(key);
      if (this._isDestroyed)
        return;
      if (!key.defaultPrevented && this.handleKeyPress) {
        this.handleKeyPress(key);
      }
    };
    this.pasteHandler = (event) => {
      if (this._isDestroyed)
        return;
      this._pasteListener?.call(this, event);
      if (this._isDestroyed)
        return;
      if (!event.defaultPrevented && this.handlePaste) {
        this.handlePaste(event);
      }
    };
    this.ctx._internalKeyInput.onInternal("keypress", this.keypressHandler);
    this.ctx._internalKeyInput.onInternal("paste", this.pasteHandler);
    this.propagateFocusChange(true);
    this.emit("focused" /* FOCUSED */);
  }
  propagateFocusChange(hasFocus) {
    let parent = this.parent;
    while (parent) {
      if (parent._hasFocusedDescendant !== hasFocus) {
        parent._hasFocusedDescendant = hasFocus;
        parent.markDirty();
      }
      parent = parent.parent;
    }
    this.requestRender();
  }
  blur() {
    if (!this._focused || !this._focusable)
      return;
    this._ctx.blurRenderable(this);
    this._focused = false;
    this.requestRender();
    if (this.keypressHandler) {
      this.ctx._internalKeyInput.offInternal("keypress", this.keypressHandler);
      this.keypressHandler = null;
    }
    if (this.pasteHandler) {
      this.ctx._internalKeyInput.offInternal("paste", this.pasteHandler);
      this.pasteHandler = null;
    }
    this.propagateFocusChange(false);
    this.emit("blurred" /* BLURRED */);
  }
  get focused() {
    return this._focused;
  }
  get hasFocusedDescendant() {
    return this._hasFocusedDescendant;
  }
  get live() {
    return this._live;
  }
  get liveCount() {
    return this._liveCount;
  }
  set live(value) {
    if (this._live === value)
      return;
    this._live = value;
    if (this._visible) {
      const delta = value ? 1 : -1;
      this.propagateLiveCount(delta);
    }
  }
  propagateLiveCount(delta) {
    this._liveCount += delta;
    this.parent?.propagateLiveCount(delta);
  }
  findDescendantById(id) {
    for (const child of this._childrenInLayoutOrder) {
      if (child.id === id)
        return child;
      if (isRenderable(child)) {
        const found = child.findDescendantById(id);
        if (found)
          return found;
      }
    }
    return;
  }
  requestRender() {
    this.markDirty();
    this._ctx.requestRender();
  }
  get translateX() {
    return this._translateX;
  }
  set translateX(value) {
    if (this._translateX === value)
      return;
    this._translateX = value;
    const parentScreenX = this.parent ? this.parent._screenX : 0;
    this._screenX = parentScreenX + this._x + this._translateX;
    if (this.parent)
      this.parent.childrenPrimarySortDirty = true;
    bumpRenderListRevision(this._ctx);
    this.requestRender();
  }
  get translateY() {
    return this._translateY;
  }
  set translateY(value) {
    if (this._translateY === value)
      return;
    this._translateY = value;
    const parentScreenY = this.parent ? this.parent._screenY : 0;
    this._screenY = parentScreenY + this._y + this._translateY;
    if (this.parent)
      this.parent.childrenPrimarySortDirty = true;
    bumpRenderListRevision(this._ctx);
    this.requestRender();
  }
  get screenX() {
    const parentScreenX = this.parent ? this.parent._screenX : 0;
    return parentScreenX + this._x + this._translateX;
  }
  get screenY() {
    const parentScreenY = this.parent ? this.parent._screenY : 0;
    return parentScreenY + this._y + this._translateY;
  }
  get x() {
    if (this.parent) {
      return this.parent.x + this._x + this._translateX;
    }
    return this._x + this._translateX;
  }
  set x(value) {
    this.left = value;
  }
  get top() {
    return this._position.top;
  }
  set top(value) {
    if (isPositionType(value) || value === undefined) {
      this.setPosition({ top: value });
    }
  }
  get right() {
    return this._position.right;
  }
  set right(value) {
    if (isPositionType(value) || value === undefined) {
      this.setPosition({ right: value });
    }
  }
  get bottom() {
    return this._position.bottom;
  }
  set bottom(value) {
    if (isPositionType(value) || value === undefined) {
      this.setPosition({ bottom: value });
    }
  }
  get left() {
    return this._position.left;
  }
  set left(value) {
    if (isPositionType(value) || value === undefined) {
      this.setPosition({ left: value });
    }
  }
  get y() {
    if (this.parent) {
      return this.parent.y + this._y + this._translateY;
    }
    return this._y + this._translateY;
  }
  set y(value) {
    this.top = value;
  }
  get width() {
    return this._widthValue;
  }
  set width(value) {
    if (!isDimensionType(value) || this._width === value) {
      return;
    }
    this._width = value;
    this.yogaNode.setWidth(value);
    if (typeof value === "number" && this._flexShrink === 1) {
      this._flexShrink = 0;
      this.yogaNode.setFlexShrink(0);
    }
    this.requestRender();
  }
  get height() {
    return this._heightValue;
  }
  set height(value) {
    if (!isDimensionType(value) || this._height === value) {
      return;
    }
    this._height = value;
    this.yogaNode.setHeight(value);
    if (typeof value === "number" && this._flexShrink === 1) {
      this._flexShrink = 0;
      this.yogaNode.setFlexShrink(0);
    }
    this.requestRender();
  }
  get zIndex() {
    return this._zIndex;
  }
  set zIndex(value) {
    if (this._zIndex !== value) {
      this._zIndex = value;
      this.parent?.requestZIndexSort();
      bumpRenderListRevision(this._ctx);
      this.requestRender();
    }
  }
  requestZIndexSort() {
    this.needsZIndexSort = true;
  }
  ensureZIndexSorted() {
    if (this.needsZIndexSort) {
      this._childrenInZIndexOrder.sort((a, b) => a.zIndex > b.zIndex ? 1 : a.zIndex < b.zIndex ? -1 : 0);
      this.needsZIndexSort = false;
    }
  }
  getChildrenSortedByPrimaryAxis() {
    if (!this.childrenPrimarySortDirty && this.childrenSortedByPrimaryAxis.length === this._childrenInLayoutOrder.length) {
      return this.childrenSortedByPrimaryAxis;
    }
    const dir = this.yogaNode.getFlexDirection();
    const axis = dir === 2 || dir === 3 ? "x" : "y";
    const sorted = [...this._childrenInLayoutOrder];
    sorted.sort((a, b) => {
      const va = axis === "y" ? a.screenY : a.screenX;
      const vb = axis === "y" ? b.screenY : b.screenX;
      return va - vb;
    });
    this.childrenSortedByPrimaryAxis = sorted;
    this.childrenPrimarySortDirty = false;
    return this.childrenSortedByPrimaryAxis;
  }
  setupYogaProperties(options) {
    const node = this.yogaNode;
    if (isFlexBasisType(options.flexBasis)) {
      node.setFlexBasis(options.flexBasis);
    }
    if (isSizeType(options.minWidth)) {
      node.setMinWidth(options.minWidth);
    }
    if (isSizeType(options.minHeight)) {
      node.setMinHeight(options.minHeight);
    }
    if (options.flexGrow !== undefined) {
      node.setFlexGrow(options.flexGrow);
    } else {
      node.setFlexGrow(0);
    }
    if (options.flexShrink !== undefined) {
      this._flexShrink = options.flexShrink;
      node.setFlexShrink(options.flexShrink);
    } else {
      const hasExplicitWidth = typeof options.width === "number";
      const hasExplicitHeight = typeof options.height === "number";
      this._flexShrink = hasExplicitWidth || hasExplicitHeight ? 0 : 1;
      node.setFlexShrink(this._flexShrink);
    }
    node.setFlexDirection(parseFlexDirection(options.flexDirection));
    node.setFlexWrap(parseWrap(options.flexWrap));
    node.setAlignItems(parseAlignItems(options.alignItems));
    node.setJustifyContent(parseJustify(options.justifyContent));
    node.setAlignSelf(parseAlign(options.alignSelf));
    if (isDimensionType(options.width)) {
      this._width = options.width;
      this.yogaNode.setWidth(options.width);
    }
    if (isDimensionType(options.height)) {
      this._height = options.height;
      this.yogaNode.setHeight(options.height);
    }
    this._positionType = options.position === "absolute" ? "absolute" : "relative";
    if (this._positionType !== "relative") {
      node.setPositionType(parsePositionType(this._positionType));
    }
    this._overflow = options.overflow === "hidden" ? "hidden" : options.overflow === "scroll" ? "scroll" : "visible";
    if (this._overflow !== "visible") {
      node.setOverflow(parseOverflow(this._overflow));
    }
    const hasPositionProps = options.top !== undefined || options.right !== undefined || options.bottom !== undefined || options.left !== undefined;
    if (hasPositionProps) {
      this._position = {
        top: options.top,
        right: options.right,
        bottom: options.bottom,
        left: options.left
      };
      this.updateYogaPosition(this._position);
    }
    if (isSizeType(options.maxWidth)) {
      node.setMaxWidth(options.maxWidth);
    }
    if (isSizeType(options.maxHeight)) {
      node.setMaxHeight(options.maxHeight);
    }
    this.setupMarginAndPadding(options);
  }
  setupMarginAndPadding(options) {
    const node = this.yogaNode;
    if (isMarginType(options.margin)) {
      node.setMargin(8 /* All */, options.margin);
    }
    if (isMarginType(options.marginX)) {
      node.setMargin(6 /* Horizontal */, options.marginX);
    }
    if (isMarginType(options.marginY)) {
      node.setMargin(7 /* Vertical */, options.marginY);
    }
    if (isMarginType(options.marginTop)) {
      node.setMargin(1 /* Top */, options.marginTop);
    }
    if (isMarginType(options.marginRight)) {
      node.setMargin(2 /* Right */, options.marginRight);
    }
    if (isMarginType(options.marginBottom)) {
      node.setMargin(3 /* Bottom */, options.marginBottom);
    }
    if (isMarginType(options.marginLeft)) {
      node.setMargin(0 /* Left */, options.marginLeft);
    }
    if (isPaddingType(options.padding)) {
      node.setPadding(8 /* All */, options.padding);
    }
    if (isPaddingType(options.paddingX)) {
      node.setPadding(6 /* Horizontal */, options.paddingX);
    }
    if (isPaddingType(options.paddingY)) {
      node.setPadding(7 /* Vertical */, options.paddingY);
    }
    if (isPaddingType(options.paddingTop)) {
      node.setPadding(1 /* Top */, options.paddingTop);
    }
    if (isPaddingType(options.paddingRight)) {
      node.setPadding(2 /* Right */, options.paddingRight);
    }
    if (isPaddingType(options.paddingBottom)) {
      node.setPadding(3 /* Bottom */, options.paddingBottom);
    }
    if (isPaddingType(options.paddingLeft)) {
      node.setPadding(0 /* Left */, options.paddingLeft);
    }
  }
  set position(positionType) {
    if (!isPositionTypeType(positionType) || this._positionType === positionType)
      return;
    this._positionType = positionType;
    this.yogaNode.setPositionType(parsePositionType(positionType));
    this.requestRender();
  }
  get overflow() {
    return this._overflow;
  }
  set overflow(overflow) {
    if (!isOverflowType(overflow) || this._overflow === overflow)
      return;
    this._overflow = overflow;
    this.yogaNode.setOverflow(parseOverflow(overflow));
    bumpRenderListRevision(this._ctx);
    this.requestRender();
  }
  setPosition(position) {
    this._position = { ...this._position, ...position };
    this.updateYogaPosition(position);
  }
  updateYogaPosition(position) {
    const node = this.yogaNode;
    const { top, right, bottom, left } = position;
    if (isPositionType(top)) {
      if (top === "auto") {
        node.setPositionAuto(1 /* Top */);
      } else {
        node.setPosition(1 /* Top */, top);
      }
    }
    if (isPositionType(right)) {
      if (right === "auto") {
        node.setPositionAuto(2 /* Right */);
      } else {
        node.setPosition(2 /* Right */, right);
      }
    }
    if (isPositionType(bottom)) {
      if (bottom === "auto") {
        node.setPositionAuto(3 /* Bottom */);
      } else {
        node.setPosition(3 /* Bottom */, bottom);
      }
    }
    if (isPositionType(left)) {
      if (left === "auto") {
        node.setPositionAuto(0 /* Left */);
      } else {
        node.setPosition(0 /* Left */, left);
      }
    }
    this.requestRender();
  }
  set flexGrow(grow) {
    if (grow == null) {
      this.yogaNode.setFlexGrow(0);
    } else {
      this.yogaNode.setFlexGrow(grow);
    }
    this.requestRender();
  }
  set flexShrink(shrink) {
    const value = shrink == null ? 1 : shrink;
    this._flexShrink = value;
    this.yogaNode.setFlexShrink(value);
    this.requestRender();
  }
  set flexDirection(direction) {
    this.yogaNode.setFlexDirection(parseFlexDirection(direction));
    this.requestRender();
  }
  set flexWrap(wrap) {
    this.yogaNode.setFlexWrap(parseWrap(wrap));
    this.requestRender();
  }
  set alignItems(alignItems) {
    this.yogaNode.setAlignItems(parseAlignItems(alignItems));
    this.requestRender();
  }
  set justifyContent(justifyContent) {
    this.yogaNode.setJustifyContent(parseJustify(justifyContent));
    this.requestRender();
  }
  set alignSelf(alignSelf) {
    this.yogaNode.setAlignSelf(parseAlign(alignSelf));
    this.requestRender();
  }
  set flexBasis(basis) {
    if (isFlexBasisType(basis)) {
      this.yogaNode.setFlexBasis(basis);
      this.requestRender();
    }
  }
  set minWidth(minWidth) {
    if (isSizeType(minWidth)) {
      this.yogaNode.setMinWidth(minWidth);
      this.requestRender();
    }
  }
  set maxWidth(maxWidth) {
    if (isSizeType(maxWidth)) {
      this.yogaNode.setMaxWidth(maxWidth);
      this.requestRender();
    }
  }
  set minHeight(minHeight) {
    if (isSizeType(minHeight)) {
      this.yogaNode.setMinHeight(minHeight);
      this.requestRender();
    }
  }
  set maxHeight(maxHeight) {
    if (isSizeType(maxHeight)) {
      this.yogaNode.setMaxHeight(maxHeight);
      this.requestRender();
    }
  }
  set margin(margin) {
    if (isMarginType(margin)) {
      this.yogaNode.setMargin(8 /* All */, margin);
      this.requestRender();
    }
  }
  set marginX(marginX) {
    if (isMarginType(marginX)) {
      this.yogaNode.setMargin(6 /* Horizontal */, marginX);
      this.requestRender();
    }
  }
  set marginY(marginY) {
    if (isMarginType(marginY)) {
      this.yogaNode.setMargin(7 /* Vertical */, marginY);
      this.requestRender();
    }
  }
  set marginTop(margin) {
    if (isMarginType(margin)) {
      this.yogaNode.setMargin(1 /* Top */, margin);
      this.requestRender();
    }
  }
  get marginTop() {
    const margin = this.yogaNode.getMargin(1 /* Top */);
    if (typeof margin === "number")
      return margin;
    if (typeof margin === "object" && margin && "value" in margin && typeof margin.value === "number")
      return margin.value;
    return 0;
  }
  set marginRight(margin) {
    if (isMarginType(margin)) {
      this.yogaNode.setMargin(2 /* Right */, margin);
      this.requestRender();
    }
  }
  set marginBottom(margin) {
    if (isMarginType(margin)) {
      this.yogaNode.setMargin(3 /* Bottom */, margin);
      this.requestRender();
    }
  }
  set marginLeft(margin) {
    if (isMarginType(margin)) {
      this.yogaNode.setMargin(0 /* Left */, margin);
      this.requestRender();
    }
  }
  set padding(padding) {
    if (isPaddingType(padding)) {
      this.yogaNode.setPadding(8 /* All */, padding);
      this.requestRender();
    }
  }
  set paddingX(paddingX) {
    if (isPaddingType(paddingX)) {
      this.yogaNode.setPadding(6 /* Horizontal */, paddingX);
      this.requestRender();
    }
  }
  set paddingY(paddingY) {
    if (isPaddingType(paddingY)) {
      this.yogaNode.setPadding(7 /* Vertical */, paddingY);
      this.requestRender();
    }
  }
  set paddingTop(padding) {
    if (isPaddingType(padding)) {
      this.yogaNode.setPadding(1 /* Top */, padding);
      this.requestRender();
    }
  }
  set paddingRight(padding) {
    if (isPaddingType(padding)) {
      this.yogaNode.setPadding(2 /* Right */, padding);
      this.requestRender();
    }
  }
  set paddingBottom(padding) {
    if (isPaddingType(padding)) {
      this.yogaNode.setPadding(3 /* Bottom */, padding);
      this.requestRender();
    }
  }
  set paddingLeft(padding) {
    if (isPaddingType(padding)) {
      this.yogaNode.setPadding(0 /* Left */, padding);
      this.requestRender();
    }
  }
  getLayoutNode() {
    return this.yogaNode;
  }
  updateFromLayout() {
    const frameId = this._ctx.frameId;
    if (this._lastLayoutFrame === frameId)
      return;
    this._lastLayoutFrame = frameId;
    const layout = this.yogaNode.getComputedLayout();
    const oldX = this._x;
    const oldY = this._y;
    const oldWidth = this._widthValue;
    const oldHeight = this._heightValue;
    this._x = layout.left;
    this._y = layout.top;
    const parentScreenX = this.parent ? this.parent._screenX : 0;
    const parentScreenY = this.parent ? this.parent._screenY : 0;
    this._screenX = parentScreenX + this._x + this._translateX;
    this._screenY = parentScreenY + this._y + this._translateY;
    const newWidth = Math.max(layout.width, 1);
    const newHeight = Math.max(layout.height, 1);
    const sizeChanged = oldWidth !== newWidth || oldHeight !== newHeight;
    this._widthValue = newWidth;
    this._heightValue = newHeight;
    if (sizeChanged) {
      this.onLayoutResize(newWidth, newHeight);
    }
    const positionChanged = oldX !== this._x || oldY !== this._y;
    if (positionChanged) {
      if (this.parent)
        this.parent.childrenPrimarySortDirty = true;
    }
  }
  onLayoutResize(width, height) {
    if (this._visible) {
      this.handleFrameBufferResize(width, height);
      this.onResize(width, height);
      this.requestRender();
    }
  }
  handleFrameBufferResize(width, height) {
    if (!this.buffered)
      return;
    if (width <= 0 || height <= 0) {
      return;
    }
    if (this.frameBuffer) {
      this.frameBuffer.resize(width, height);
    } else {
      this.createFrameBuffer();
    }
  }
  createFrameBuffer() {
    const w = this.width;
    const h = this.height;
    if (w <= 0 || h <= 0) {
      return;
    }
    try {
      const widthMethod = this._ctx.widthMethod;
      this.frameBuffer = OptimizedBuffer.create(w, h, widthMethod, {
        respectAlpha: true,
        id: `framebuffer-${this.id}`
      });
    } catch (error) {
      console.error(`Failed to create frame buffer for ${this.id}:`, error);
      this.frameBuffer = null;
    }
  }
  onResize(width, height) {
    this.onSizeChange?.();
    this.emit("resize");
  }
  replaceParent(obj) {
    if (obj.parent) {
      obj.parent.remove(obj);
    }
    obj.parent = this;
  }
  add(obj, index) {
    if (!obj) {
      return -1;
    }
    const renderable = maybeMakeRenderable(this._ctx, obj);
    if (!renderable) {
      return -1;
    }
    if (renderable.isDestroyed) {
      if (true) {
        console.warn(`Renderable with id ${renderable.id} was already destroyed, skipping add`);
      }
      return -1;
    }
    const anchorRenderable = index !== undefined ? this._childrenInLayoutOrder[index] : undefined;
    if (anchorRenderable) {
      return this.insertBefore(renderable, anchorRenderable);
    }
    if (renderable.parent === this) {
      this.yogaNode.removeChild(renderable.getLayoutNode());
      this._childrenInLayoutOrder.splice(this._childrenInLayoutOrder.indexOf(renderable), 1);
    } else {
      this.replaceParent(renderable);
      this.needsZIndexSort = true;
      this._childrenInZIndexOrder.push(renderable);
      if (typeof renderable.onLifecyclePass === "function") {
        this._ctx.registerLifecyclePass(renderable);
      }
      if (renderable._liveCount > 0) {
        this.propagateLiveCount(renderable._liveCount);
      }
    }
    const childLayoutNode = renderable.getLayoutNode();
    const insertedIndex = this._childrenInLayoutOrder.length;
    this._childrenInLayoutOrder.push(renderable);
    this.yogaNode.insertChild(childLayoutNode, insertedIndex);
    this.childrenPrimarySortDirty = true;
    this._shouldUpdateBefore.add(renderable);
    bumpRenderListRevision(this._ctx);
    this.requestRender();
    return insertedIndex;
  }
  insertBefore(obj, anchor) {
    if (!anchor) {
      return this.add(obj);
    }
    if (!obj) {
      return -1;
    }
    const renderable = maybeMakeRenderable(this._ctx, obj);
    if (!renderable) {
      return -1;
    }
    if (renderable.isDestroyed) {
      if (true) {
        console.warn(`Renderable with id ${renderable.id} was already destroyed, skipping insertBefore`);
      }
      return -1;
    }
    if (!isRenderable(anchor)) {
      throw new Error("Anchor must be a Renderable");
    }
    if (anchor.isDestroyed) {
      if (true) {
        console.warn(`Anchor with id ${anchor.id} was already destroyed, skipping insertBefore`);
      }
      return -1;
    }
    if (this._childrenInLayoutOrder.indexOf(anchor) === -1) {
      if (true) {
        console.warn(`Anchor with id ${anchor.id} does not exist within the parent ${this.id}, skipping insertBefore`);
      }
      return -1;
    }
    if (renderable === anchor) {
      if (true) {
        console.warn(`Anchor is the same as the node ${renderable.id} being inserted, skipping insertBefore`);
      }
      return -1;
    }
    if (renderable.parent === this) {
      this.yogaNode.removeChild(renderable.getLayoutNode());
      this._childrenInLayoutOrder.splice(this._childrenInLayoutOrder.indexOf(renderable), 1);
    } else {
      this.replaceParent(renderable);
      this.needsZIndexSort = true;
      this._childrenInZIndexOrder.push(renderable);
      if (typeof renderable.onLifecyclePass === "function") {
        this._ctx.registerLifecyclePass(renderable);
      }
      if (renderable._liveCount > 0) {
        this.propagateLiveCount(renderable._liveCount);
      }
    }
    this.childrenPrimarySortDirty = true;
    const anchorIndex = this._childrenInLayoutOrder.indexOf(anchor);
    const insertedIndex = Math.max(0, Math.min(anchorIndex, this._childrenInLayoutOrder.length));
    this._childrenInLayoutOrder.splice(insertedIndex, 0, renderable);
    this.yogaNode.insertChild(renderable.getLayoutNode(), insertedIndex);
    this._shouldUpdateBefore.add(renderable);
    bumpRenderListRevision(this._ctx);
    this.requestRender();
    return insertedIndex;
  }
  getRenderable(id) {
    return this._childrenInLayoutOrder.find((child) => child.id === id);
  }
  remove(child) {
    if (!(child instanceof BaseRenderable)) {
      throw new Error("remove expects a renderable child object");
    }
    const index = this._childrenInLayoutOrder.indexOf(child);
    if (index === -1) {
      if (true) {
        console.warn(`Renderable with id ${child.id} is not a child of ${this.id}, skipping remove`);
      }
      return;
    }
    const renderable = this._childrenInLayoutOrder[index];
    if (renderable._liveCount > 0) {
      this.propagateLiveCount(-renderable._liveCount);
    }
    this.yogaNode.removeChild(renderable.getLayoutNode());
    this._childrenInLayoutOrder.splice(index, 1);
    const zIndexIndex = this._childrenInZIndexOrder.indexOf(renderable);
    if (zIndexIndex !== -1) {
      this._childrenInZIndexOrder.splice(zIndexIndex, 1);
    }
    this._shouldUpdateBefore.delete(renderable);
    this.requestRender();
    renderable.onRemove();
    renderable.parent = null;
    this._ctx.unregisterLifecyclePass(renderable);
    this.childrenPrimarySortDirty = true;
    bumpRenderListRevision(this._ctx);
  }
  onRemove() {}
  getChildren() {
    return [...this._childrenInLayoutOrder];
  }
  getChildrenCount() {
    return this._childrenInLayoutOrder.length;
  }
  updateLayout(deltaTime, renderList = []) {
    if (!this.visible)
      return;
    this.onUpdate(deltaTime);
    if (this._isDestroyed)
      return;
    this.updateFromLayout();
    if (this._shouldUpdateBefore.size > 0) {
      for (const child of this._shouldUpdateBefore) {
        if (!child.isDestroyed) {
          child.updateFromLayout();
        }
      }
      this._shouldUpdateBefore.clear();
    }
    if (this._isDestroyed)
      return;
    const shouldPushOpacity = this._opacity < 1;
    if (shouldPushOpacity) {
      renderList.push({ action: "pushOpacity", opacity: this._opacity });
    }
    renderList.push({ action: "render", renderable: this });
    this.ensureZIndexSorted();
    const shouldPushScissor = this._overflow !== "visible" && this.width > 0 && this.height > 0;
    if (shouldPushScissor) {
      const scissorRect = this.getScissorRect();
      renderList.push({
        action: "pushScissorRect",
        x: scissorRect.x,
        y: scissorRect.y,
        width: scissorRect.width,
        height: scissorRect.height,
        screenX: this.buffered ? this._screenX : scissorRect.x,
        screenY: this.buffered ? this._screenY : scissorRect.y
      });
    }
    if (!this._hasVisibleChildFilter()) {
      for (const child of this._childrenInZIndexOrder) {
        child.updateLayout(deltaTime, renderList);
      }
    } else {
      for (const child of this._childrenInZIndexOrder) {
        if (child.isDestroyed)
          continue;
        child.updateFromLayout();
      }
      const visibleChildren = this._getVisibleChildren();
      const visibleChildSet = new Set(visibleChildren);
      for (const child of this._childrenInZIndexOrder) {
        if (!visibleChildSet.has(child.num))
          continue;
        child.updateLayout(deltaTime, renderList);
      }
    }
    if (shouldPushScissor) {
      renderList.push({ action: "popScissorRect" });
    }
    if (shouldPushOpacity) {
      renderList.push({ action: "popOpacity" });
    }
  }
  render(buffer, deltaTime) {
    let renderBuffer = buffer;
    if (this.buffered && this.frameBuffer) {
      renderBuffer = this.frameBuffer;
    }
    if (this.renderBefore) {
      this.renderBefore.call(this, renderBuffer, deltaTime);
    }
    this.renderSelf(renderBuffer, deltaTime);
    if (this.renderAfter) {
      this.renderAfter.call(this, renderBuffer, deltaTime);
    }
    const screenX = this._screenX;
    const screenY = this._screenY;
    this.markClean();
    this._ctx.addToHitGrid(screenX, screenY, this.width, this.height, this.num);
    if (this.buffered && this.frameBuffer) {
      buffer.drawFrameBuffer(screenX, screenY, this.frameBuffer);
    }
  }
  _hasVisibleChildFilter() {
    return this._getVisibleChildren !== Renderable.prototype._getVisibleChildren;
  }
  _getVisibleChildren() {
    return this._childrenInZIndexOrder.map((child) => child.num);
  }
  canReuseRenderCommandList() {
    return this.onUpdate === Renderable.prototype.onUpdate && (this._overflow === "visible" || this.getScissorRect === Renderable.prototype.getScissorRect) && !this._hasVisibleChildFilter();
  }
  onUpdate(deltaTime) {}
  getScissorRect() {
    return {
      x: this.buffered ? 0 : this._screenX,
      y: this.buffered ? 0 : this._screenY,
      width: this.width,
      height: this.height
    };
  }
  renderSelf(buffer, deltaTime) {}
  get isDestroyed() {
    return this._isDestroyed;
  }
  destroy() {
    if (this._isDestroyed) {
      return;
    }
    this._isDestroyed = true;
    this.emit("destroyed" /* DESTROYED */);
    if (this.parent) {
      this.parent.remove(this);
    }
    if (this.frameBuffer) {
      this.frameBuffer.destroy();
      this.frameBuffer = null;
    }
    for (const child of [...this._childrenInLayoutOrder]) {
      this.remove(child);
    }
    this._childrenInLayoutOrder = [];
    this._childrenInZIndexOrder = [];
    this._shouldUpdateBefore.clear();
    Renderable.renderablesByNumber.delete(this.num);
    this.blur();
    this.removeAllListeners();
    this.destroySelf();
    try {
      this.yogaNode.free();
    } catch (e) {}
  }
  destroyRecursively() {
    const children = [...this._childrenInLayoutOrder];
    for (const child of children) {
      child.destroyRecursively();
    }
    this.destroy();
  }
  destroySelf() {}
  processMouseEvent(event) {
    event.currentTarget = this;
    this._mouseListener?.call(this, event);
    this._mouseListeners[event.type]?.call(this, event);
    this.onMouseEvent(event);
    if (this.parent && !event.propagationStopped) {
      this.parent.processMouseEvent(event);
    }
  }
  onMouseEvent(event) {}
  set onMouse(handler) {
    if (handler)
      this._mouseListener = handler;
    else
      this._mouseListener = null;
  }
  set onMouseDown(handler) {
    if (handler)
      this._mouseListeners["down"] = handler;
    else
      delete this._mouseListeners["down"];
  }
  set onMouseUp(handler) {
    if (handler)
      this._mouseListeners["up"] = handler;
    else
      delete this._mouseListeners["up"];
  }
  set onMouseMove(handler) {
    if (handler)
      this._mouseListeners["move"] = handler;
    else
      delete this._mouseListeners["move"];
  }
  set onMouseDrag(handler) {
    if (handler)
      this._mouseListeners["drag"] = handler;
    else
      delete this._mouseListeners["drag"];
  }
  set onMouseDragEnd(handler) {
    if (handler)
      this._mouseListeners["drag-end"] = handler;
    else
      delete this._mouseListeners["drag-end"];
  }
  set onMouseDrop(handler) {
    if (handler)
      this._mouseListeners["drop"] = handler;
    else
      delete this._mouseListeners["drop"];
  }
  set onMouseOver(handler) {
    if (handler)
      this._mouseListeners["over"] = handler;
    else
      delete this._mouseListeners["over"];
  }
  set onMouseOut(handler) {
    if (handler)
      this._mouseListeners["out"] = handler;
    else
      delete this._mouseListeners["out"];
  }
  set onMouseScroll(handler) {
    if (handler)
      this._mouseListeners["scroll"] = handler;
    else
      delete this._mouseListeners["scroll"];
  }
  set onPaste(handler) {
    this._pasteListener = handler;
  }
  get onPaste() {
    return this._pasteListener;
  }
  set onKeyDown(handler) {
    if (handler)
      this._keyListeners["down"] = handler;
    else
      delete this._keyListeners["down"];
  }
  get onKeyDown() {
    return this._keyListeners["down"];
  }
  set onSizeChange(handler) {
    this._sizeChangeListener = handler;
  }
  get onSizeChange() {
    return this._sizeChangeListener;
  }
  applyEventOptions(options) {
    this.onMouse = options.onMouse;
    this.onMouseDown = options.onMouseDown;
    this.onMouseUp = options.onMouseUp;
    this.onMouseMove = options.onMouseMove;
    this.onMouseDrag = options.onMouseDrag;
    this.onMouseDragEnd = options.onMouseDragEnd;
    this.onMouseDrop = options.onMouseDrop;
    this.onMouseOver = options.onMouseOver;
    this.onMouseOut = options.onMouseOut;
    this.onMouseScroll = options.onMouseScroll;
    this.onPaste = options.onPaste;
    this.onKeyDown = options.onKeyDown;
    this.onSizeChange = options.onSizeChange;
  }
}

class RootRenderable extends Renderable {
  renderList = [];
  _currentRenderable;
  appliedLayoutGeneration = -1;
  appliedRenderListRevision = -1;
  renderListReusable = false;
  constructor(ctx) {
    super(ctx, {
      id: "__root__",
      zIndex: 0,
      visible: true,
      width: ctx.width,
      height: ctx.height,
      enableLayout: true
    });
    if (this.yogaNode) {
      this.yogaNode.free();
    }
    this.yogaNode = yoga_default.Node.createForOpenTUI();
    this.yogaNode.setWidth(ctx.width);
    this.yogaNode.setHeight(ctx.height);
    this.yogaNode.setFlexDirection(0 /* Column */);
    this.calculateLayout();
  }
  get currentRenderable() {
    return this._currentRenderable;
  }
  takeCurrentRenderable() {
    const renderable = this._currentRenderable;
    this._currentRenderable = undefined;
    return renderable;
  }
  render(buffer, deltaTime) {
    this._currentRenderable = undefined;
    if (!this.visible)
      return;
    for (const renderable of this._ctx.getLifecyclePasses()) {
      if (!renderable.isDestroyed) {
        renderable.onLifecyclePass?.call(renderable);
      }
    }
    if (this.yogaNode.isDirty()) {
      this.calculateLayout();
    } else {
      this.syncExternalLayoutGeneration();
    }
    const layoutGeneration = getLayoutGeneration(this._ctx);
    const renderListRevision = getRenderListRevision(this._ctx);
    const canReuseRenderList = this.renderListReusable && this.appliedLayoutGeneration === layoutGeneration && this.appliedRenderListRevision === renderListRevision;
    if (!canReuseRenderList) {
      this.renderList.length = 0;
      super.updateLayout(deltaTime, this.renderList);
      this.appliedLayoutGeneration = layoutGeneration;
      this.appliedRenderListRevision = getRenderListRevision(this._ctx);
      this.renderListReusable = this.canReuseCurrentRenderList();
    }
    this._ctx.clearHitGridScissorRects();
    for (let i = 1;i < this.renderList.length; i++) {
      const command = this.renderList[i];
      switch (command.action) {
        case "render":
          if (!command.renderable.isDestroyed) {
            this._currentRenderable = command.renderable;
            command.renderable.render(buffer, deltaTime);
            this._currentRenderable = undefined;
          }
          break;
        case "pushScissorRect":
          buffer.pushScissorRect(command.x, command.y, command.width, command.height);
          this._ctx.pushHitGridScissorRect(command.screenX, command.screenY, command.width, command.height);
          break;
        case "popScissorRect":
          buffer.popScissorRect();
          this._ctx.popHitGridScissorRect();
          break;
        case "pushOpacity":
          buffer.pushOpacity(command.opacity);
          break;
        case "popOpacity":
          buffer.popOpacity();
          break;
      }
    }
  }
  propagateLiveCount(delta) {
    const oldCount = this._liveCount;
    this._liveCount += delta;
    if (oldCount === 0 && this._liveCount > 0) {
      this._ctx.requestLive();
    } else if (oldCount > 0 && this._liveCount === 0) {
      this._ctx.dropLive();
    }
  }
  calculateLayout() {
    this.yogaNode.calculateLayout(this.width, this.height, 1 /* LTR */);
    bumpLayoutGeneration(this._ctx);
    this.yogaNode.markLayoutSeen();
    this.emit("layout-changed" /* LAYOUT_CHANGED */);
  }
  syncExternalLayoutGeneration() {
    if (!this.yogaNode.hasNewLayout())
      return;
    bumpLayoutGeneration(this._ctx);
    this.yogaNode.markLayoutSeen();
  }
  canReuseCurrentRenderList() {
    if (this._liveCount > 0)
      return false;
    for (const command of this.renderList) {
      if (command.action !== "render")
        continue;
      if (!command.renderable.canReuseRenderCommandList())
        return false;
    }
    return true;
  }
  resize(width, height) {
    this.width = width;
    this.height = height;
    this.emit("resized" /* RESIZED */, { width, height });
  }
}

// src/renderables/composition/vnode.ts
import util from "util";
var BrandedVNode = Symbol.for("@opentui/core/VNode");
function isRenderableConstructor(value) {
  return typeof value === "function" && value.prototype && Renderable.prototype.isPrototypeOf(value.prototype);
}
function flattenChildren(children) {
  const result = [];
  for (const child of children) {
    if (Array.isArray(child)) {
      result.push(...flattenChildren(child));
    } else if (child !== null && child !== undefined && child !== false) {
      result.push(child);
    }
  }
  return result;
}
function h(type, props, ...children) {
  if (typeof type !== "function") {
    throw new TypeError("h() received an invalid vnode type");
  }
  const vnode = {
    [BrandedVNode]: true,
    type,
    props,
    children: flattenChildren(children),
    __pendingCalls: []
  };
  if (isRenderableConstructor(type)) {
    return new Proxy(vnode, {
      get(target, prop, receiver) {
        if (prop in target) {
          return Reflect.get(target, prop, receiver);
        }
        if (typeof prop === "string") {
          const prototype = type.prototype;
          const hasMethod = prototype && (typeof prototype[prop] === "function" || Object.getOwnPropertyDescriptor(prototype, prop) || Object.getOwnPropertyDescriptor(Object.getPrototypeOf(prototype), prop));
          if (hasMethod) {
            return (...args) => {
              target.__pendingCalls = target.__pendingCalls || [];
              target.__pendingCalls.push({ method: prop, args });
              return target;
            };
          }
        }
        return Reflect.get(target, prop, receiver);
      },
      set(target, prop, value, receiver) {
        if (typeof prop === "string" && isRenderableConstructor(type)) {
          const prototype = type.prototype;
          const descriptor = Object.getOwnPropertyDescriptor(prototype, prop) || Object.getOwnPropertyDescriptor(Object.getPrototypeOf(prototype), prop);
          if (descriptor && descriptor.set) {
            target.__pendingCalls = target.__pendingCalls || [];
            target.__pendingCalls.push({ method: prop, args: [value], isProperty: true });
            return true;
          }
        }
        return Reflect.set(target, prop, value, receiver);
      }
    });
  }
  return vnode;
}
function isVNode(node) {
  return node && node[BrandedVNode];
}
function maybeMakeRenderable(ctx, node) {
  if (isRenderable(node))
    return node;
  if (isVNode(node))
    return instantiate(ctx, node);
  if (true) {
    console.warn("maybeMakeRenderable received an invalid node", util.inspect(node, { depth: 2 }));
  }
  return null;
}
function wrapWithDelegates(instance, delegateMap) {
  if (!delegateMap || Object.keys(delegateMap).length === 0)
    return instance;
  const getDescendant = (id) => {
    return instance.findDescendantById(id);
  };
  const proxy = new Proxy(instance, {
    get(target, prop, receiver) {
      if (typeof prop === "string" && delegateMap[prop]) {
        const host = getDescendant(delegateMap[prop]);
        if (host) {
          const value = host[prop];
          if (typeof value === "function") {
            return value.bind(host);
          }
          return value;
        }
      }
      return Reflect.get(target, prop, receiver);
    },
    set(target, prop, value, receiver) {
      if (typeof prop === "string" && delegateMap[prop]) {
        const host = getDescendant(delegateMap[prop]);
        if (host) {
          return Reflect.set(host, prop, value);
        }
      }
      return Reflect.set(target, prop, value, receiver);
    }
  });
  return proxy;
}
function instantiate(ctx, node) {
  if (isRenderable(node))
    return node;
  if (!node || typeof node !== "object") {
    throw new TypeError("mount() received an invalid vnode");
  }
  const vnode = node;
  const { type, props } = vnode;
  const children = flattenChildren(vnode.children || []);
  const delegateMap = vnode.__delegateMap;
  if (isRenderableConstructor(type)) {
    const instance = new type(ctx, props || {});
    for (const child of children) {
      if (isRenderable(child)) {
        instance.add(child);
      } else {
        const mounted = instantiate(ctx, child);
        instance.add(mounted);
      }
    }
    const delegatedInstance = wrapWithDelegates(instance, delegateMap);
    const pendingCalls = vnode.__pendingCalls;
    if (pendingCalls) {
      for (const call of pendingCalls) {
        if (call.isProperty) {
          delegatedInstance[call.method] = call.args[0];
        } else {
          delegatedInstance[call.method].apply(delegatedInstance, call.args);
        }
      }
    }
    return delegatedInstance;
  }
  const resolved = type(props || {}, children);
  const inst = instantiate(ctx, resolved);
  return wrapWithDelegates(inst, delegateMap);
}
function delegate(mapping, vnode) {
  if (isRenderable(vnode)) {
    return wrapWithDelegates(vnode, mapping);
  }
  if (!vnode || typeof vnode !== "object")
    return vnode;
  vnode.__delegateMap = { ...vnode.__delegateMap || {}, ...mapping };
  return vnode;
}

// src/text-buffer-view.ts
class TextBufferView {
  lib;
  viewPtr;
  textBuffer;
  _destroyed = false;
  constructor(lib, ptr, textBuffer) {
    this.lib = lib;
    this.viewPtr = ptr;
    this.textBuffer = textBuffer;
  }
  static create(textBuffer) {
    const lib = resolveRenderLib();
    const viewPtr = lib.createTextBufferView(textBuffer.ptr);
    return new TextBufferView(lib, viewPtr, textBuffer);
  }
  guard() {
    if (this._destroyed)
      throw new Error("TextBufferView is destroyed");
  }
  get ptr() {
    this.guard();
    return this.viewPtr;
  }
  setSelection(start, end, bgColor, fgColor) {
    this.guard();
    this.lib.textBufferViewSetSelection(this.viewPtr, start, end, bgColor || null, fgColor || null);
  }
  updateSelection(end, bgColor, fgColor) {
    this.guard();
    this.lib.textBufferViewUpdateSelection(this.viewPtr, end, bgColor || null, fgColor || null);
  }
  resetSelection() {
    this.guard();
    this.lib.textBufferViewResetSelection(this.viewPtr);
  }
  getSelection() {
    this.guard();
    return this.lib.textBufferViewGetSelection(this.viewPtr);
  }
  hasSelection() {
    this.guard();
    return this.getSelection() !== null;
  }
  setLocalSelection(anchorX, anchorY, focusX, focusY, bgColor, fgColor, behavior = "cell") {
    this.guard();
    return this.lib.textBufferViewSetLocalSelection(this.viewPtr, anchorX, anchorY, focusX, focusY, bgColor || null, fgColor || null, behavior);
  }
  updateLocalSelection(anchorX, anchorY, focusX, focusY, bgColor, fgColor, behavior = "cell") {
    this.guard();
    return this.lib.textBufferViewUpdateLocalSelection(this.viewPtr, anchorX, anchorY, focusX, focusY, bgColor || null, fgColor || null, behavior);
  }
  resetLocalSelection() {
    this.guard();
    this.lib.textBufferViewResetLocalSelection(this.viewPtr);
  }
  setSelectionOccupancy(occupancy) {
    this.guard();
    this.lib.textBufferViewSetSelectionOccupancy(this.viewPtr, occupancy);
  }
  getSelectionOccupancy() {
    this.guard();
    return this.lib.textBufferViewGetSelectionOccupancy(this.viewPtr);
  }
  setWrapWidth(width) {
    this.guard();
    this.lib.textBufferViewSetWrapWidth(this.viewPtr, width ?? 0);
  }
  setWrapMode(mode) {
    this.guard();
    this.lib.textBufferViewSetWrapMode(this.viewPtr, mode);
  }
  setFirstLineOffset(offset) {
    this.guard();
    this.lib.textBufferViewSetFirstLineOffset(this.viewPtr, offset);
  }
  setViewportSize(width, height) {
    this.guard();
    this.lib.textBufferViewSetViewportSize(this.viewPtr, width, height);
  }
  setViewport(x, y, width, height) {
    this.guard();
    this.lib.textBufferViewSetViewport(this.viewPtr, x, y, width, height);
  }
  get lineInfo() {
    this.guard();
    return this.lib.textBufferViewGetLineInfo(this.viewPtr);
  }
  get logicalLineInfo() {
    this.guard();
    return this.lib.textBufferViewGetLogicalLineInfo(this.viewPtr);
  }
  getSelectedText() {
    this.guard();
    const byteSize = this.textBuffer.byteSize;
    if (byteSize === 0)
      return "";
    const selectedBytes = this.lib.textBufferViewGetSelectedTextBytes(this.viewPtr, byteSize);
    if (!selectedBytes)
      return "";
    return this.lib.decoder.decode(selectedBytes);
  }
  getPlainText() {
    this.guard();
    const byteSize = this.textBuffer.byteSize;
    if (byteSize === 0)
      return "";
    const plainBytes = this.lib.textBufferViewGetPlainTextBytes(this.viewPtr, byteSize);
    if (!plainBytes)
      return "";
    return this.lib.decoder.decode(plainBytes);
  }
  setTabIndicator(indicator) {
    this.guard();
    const codePoint = typeof indicator === "string" ? indicator.codePointAt(0) ?? 0 : indicator;
    this.lib.textBufferViewSetTabIndicator(this.viewPtr, codePoint);
  }
  setTabIndicatorColor(color) {
    this.guard();
    this.lib.textBufferViewSetTabIndicatorColor(this.viewPtr, color);
  }
  setTruncate(truncate) {
    this.guard();
    this.lib.textBufferViewSetTruncate(this.viewPtr, truncate);
  }
  measureForDimensions(width, height) {
    this.guard();
    return this.lib.textBufferViewMeasureForDimensions(this.viewPtr, width, height);
  }
  getVirtualLineCount() {
    this.guard();
    return this.lib.textBufferViewGetVirtualLineCount(this.viewPtr);
  }
  destroy() {
    if (this._destroyed)
      return;
    this._destroyed = true;
    this.lib.destroyTextBufferView(this.viewPtr);
  }
}

// src/edit-buffer.ts
import { EventEmitter as EventEmitter2 } from "events";

class EditBuffer extends EventEmitter2 {
  static registry = new Map;
  static nativeEventsSubscribed = false;
  lib;
  bufferPtr;
  textBufferPtr;
  id;
  _destroyed = false;
  _textBytes = [];
  _singleTextBytes = null;
  _singleTextMemId = null;
  _syntaxStyle;
  constructor(lib, ptr) {
    super();
    this.lib = lib;
    this.bufferPtr = ptr;
    this.textBufferPtr = lib.editBufferGetTextBuffer(ptr);
    this.id = lib.editBufferGetId(ptr);
    EditBuffer.registry.set(this.id, this);
    EditBuffer.subscribeToNativeEvents(lib);
  }
  static create(widthMethod) {
    const lib = resolveRenderLib();
    const ptr = lib.createEditBuffer(widthMethod);
    return new EditBuffer(lib, ptr);
  }
  static subscribeToNativeEvents(lib) {
    if (EditBuffer.nativeEventsSubscribed)
      return;
    EditBuffer.nativeEventsSubscribed = true;
    lib.onAnyNativeEvent((name, data) => {
      const buffer = new Uint16Array(data);
      if (name.startsWith("eb_") && buffer.length >= 1) {
        const id = buffer[0];
        const instance = EditBuffer.registry.get(id);
        if (instance) {
          const eventName = name.slice(3);
          const eventData = data.slice(2);
          instance.emit(eventName, eventData);
        }
      }
    });
  }
  guard() {
    if (this._destroyed)
      throw new Error("EditBuffer is destroyed");
  }
  get ptr() {
    this.guard();
    return this.bufferPtr;
  }
  setText(text) {
    this.guard();
    const textBytes = this.lib.encoder.encode(text);
    if (this._singleTextMemId !== null) {
      this.lib.textBufferReplaceMemBuffer(this.textBufferPtr, this._singleTextMemId, textBytes, false);
    } else {
      this._singleTextMemId = this.lib.textBufferRegisterMemBuffer(this.textBufferPtr, textBytes, false);
    }
    this._singleTextBytes = textBytes;
    this.lib.editBufferSetTextFromMem(this.bufferPtr, this._singleTextMemId);
  }
  setTextOwned(text) {
    this.guard();
    const textBytes = this.lib.encoder.encode(text);
    this.lib.editBufferSetText(this.bufferPtr, textBytes);
  }
  replaceText(text) {
    this.guard();
    const textBytes = this.lib.encoder.encode(text);
    this._textBytes.push(textBytes);
    const memId = this.lib.textBufferRegisterMemBuffer(this.textBufferPtr, textBytes, false);
    this.lib.editBufferReplaceTextFromMem(this.bufferPtr, memId);
  }
  replaceTextOwned(text) {
    this.guard();
    const textBytes = this.lib.encoder.encode(text);
    this.lib.editBufferReplaceText(this.bufferPtr, textBytes);
  }
  getLineCount() {
    this.guard();
    return this.lib.textBufferGetLineCount(this.textBufferPtr);
  }
  setTabWidth(width) {
    this.guard();
    this.lib.editBufferSetTabWidth(this.bufferPtr, width);
  }
  getTabWidth() {
    this.guard();
    return this.lib.textBufferGetTabWidth(this.textBufferPtr);
  }
  getText() {
    this.guard();
    const maxSize = 1024 * 1024;
    const textBytes = this.lib.editBufferGetText(this.bufferPtr, maxSize);
    if (!textBytes)
      return "";
    return this.lib.decoder.decode(textBytes);
  }
  insertChar(char) {
    this.guard();
    this.lib.editBufferInsertChar(this.bufferPtr, char);
  }
  insertText(text) {
    this.guard();
    this.lib.editBufferInsertText(this.bufferPtr, text);
  }
  deleteChar() {
    this.guard();
    this.lib.editBufferDeleteChar(this.bufferPtr);
  }
  deleteCharBackward() {
    this.guard();
    this.lib.editBufferDeleteCharBackward(this.bufferPtr);
  }
  deleteRange(startLine, startCol, endLine, endCol) {
    this.guard();
    this.lib.editBufferDeleteRange(this.bufferPtr, startLine, startCol, endLine, endCol);
  }
  newLine() {
    this.guard();
    this.lib.editBufferNewLine(this.bufferPtr);
  }
  deleteLine() {
    this.guard();
    this.lib.editBufferDeleteLine(this.bufferPtr);
  }
  moveCursorLeft() {
    this.guard();
    this.lib.editBufferMoveCursorLeft(this.bufferPtr);
  }
  moveCursorRight() {
    this.guard();
    this.lib.editBufferMoveCursorRight(this.bufferPtr);
  }
  moveCursorUp() {
    this.guard();
    this.lib.editBufferMoveCursorUp(this.bufferPtr);
  }
  moveCursorDown() {
    this.guard();
    this.lib.editBufferMoveCursorDown(this.bufferPtr);
  }
  gotoLine(line) {
    this.guard();
    this.lib.editBufferGotoLine(this.bufferPtr, line);
  }
  setCursor(line, col) {
    this.guard();
    this.lib.editBufferSetCursor(this.bufferPtr, line, col);
  }
  setCursorToLineCol(line, col) {
    this.guard();
    this.lib.editBufferSetCursorToLineCol(this.bufferPtr, line, col);
  }
  setCursorByOffset(offset) {
    this.guard();
    this.lib.editBufferSetCursorByOffset(this.bufferPtr, offset);
  }
  getCursorPosition() {
    this.guard();
    return this.lib.editBufferGetCursorPosition(this.bufferPtr);
  }
  getNextWordBoundary() {
    this.guard();
    const boundary = this.lib.editBufferGetNextWordBoundary(this.bufferPtr);
    return {
      row: boundary.row,
      col: boundary.col,
      offset: boundary.offset
    };
  }
  getPrevWordBoundary() {
    this.guard();
    const boundary = this.lib.editBufferGetPrevWordBoundary(this.bufferPtr);
    return {
      row: boundary.row,
      col: boundary.col,
      offset: boundary.offset
    };
  }
  getEOL() {
    this.guard();
    const boundary = this.lib.editBufferGetEOL(this.bufferPtr);
    return {
      row: boundary.row,
      col: boundary.col,
      offset: boundary.offset
    };
  }
  offsetToPosition(offset) {
    this.guard();
    const result = this.lib.editBufferOffsetToPosition(this.bufferPtr, offset);
    if (!result)
      return null;
    return { row: result.row, col: result.col };
  }
  positionToOffset(row, col) {
    this.guard();
    return this.lib.editBufferPositionToOffset(this.bufferPtr, row, col);
  }
  getLineStartOffset(row) {
    this.guard();
    return this.lib.editBufferGetLineStartOffset(this.bufferPtr, row);
  }
  getTextRange(startOffset, endOffset) {
    this.guard();
    if (startOffset >= endOffset)
      return "";
    const maxSize = 1024 * 1024;
    const textBytes = this.lib.editBufferGetTextRange(this.bufferPtr, startOffset, endOffset, maxSize);
    if (!textBytes)
      return "";
    return this.lib.decoder.decode(textBytes);
  }
  getTextRangeByCoords(startRow, startCol, endRow, endCol) {
    this.guard();
    const maxSize = 1024 * 1024;
    const textBytes = this.lib.editBufferGetTextRangeByCoords(this.bufferPtr, startRow, startCol, endRow, endCol, maxSize);
    if (!textBytes)
      return "";
    return this.lib.decoder.decode(textBytes);
  }
  debugLogRope() {
    this.guard();
    this.lib.editBufferDebugLogRope(this.bufferPtr);
  }
  undo() {
    this.guard();
    const maxSize = 256;
    const metaBytes = this.lib.editBufferUndo(this.bufferPtr, maxSize);
    if (!metaBytes)
      return null;
    return this.lib.decoder.decode(metaBytes);
  }
  redo() {
    this.guard();
    const maxSize = 256;
    const metaBytes = this.lib.editBufferRedo(this.bufferPtr, maxSize);
    if (!metaBytes)
      return null;
    return this.lib.decoder.decode(metaBytes);
  }
  canUndo() {
    this.guard();
    return this.lib.editBufferCanUndo(this.bufferPtr);
  }
  canRedo() {
    this.guard();
    return this.lib.editBufferCanRedo(this.bufferPtr);
  }
  clearHistory() {
    this.guard();
    this.lib.editBufferClearHistory(this.bufferPtr);
  }
  setDefaultFg(fg) {
    this.guard();
    this.lib.textBufferSetDefaultFg(this.textBufferPtr, fg);
  }
  setDefaultBg(bg) {
    this.guard();
    this.lib.textBufferSetDefaultBg(this.textBufferPtr, bg);
  }
  setDefaultAttributes(attributes) {
    this.guard();
    this.lib.textBufferSetDefaultAttributes(this.textBufferPtr, attributes);
  }
  resetDefaults() {
    this.guard();
    this.lib.textBufferResetDefaults(this.textBufferPtr);
  }
  setSyntaxStyle(style) {
    this.guard();
    if (this.lib.textBufferSetSyntaxStyle(this.textBufferPtr, style?.ptr ?? null)) {
      this._syntaxStyle = style ?? undefined;
    }
  }
  getSyntaxStyle() {
    this.guard();
    return this._syntaxStyle ?? null;
  }
  addHighlight(lineIdx, highlight) {
    this.guard();
    this.lib.textBufferAddHighlight(this.textBufferPtr, lineIdx, highlight);
  }
  addHighlightByCharRange(highlight) {
    this.guard();
    this.lib.textBufferAddHighlightByCharRange(this.textBufferPtr, highlight);
  }
  removeHighlightsByRef(hlRef) {
    this.guard();
    this.lib.textBufferRemoveHighlightsByRef(this.textBufferPtr, hlRef);
  }
  clearLineHighlights(lineIdx) {
    this.guard();
    this.lib.textBufferClearLineHighlights(this.textBufferPtr, lineIdx);
  }
  clearAllHighlights() {
    this.guard();
    this.lib.textBufferClearAllHighlights(this.textBufferPtr);
  }
  getLineHighlights(lineIdx) {
    this.guard();
    return this.lib.textBufferGetLineHighlights(this.textBufferPtr, lineIdx);
  }
  clear() {
    this.guard();
    this.lib.editBufferClear(this.bufferPtr);
  }
  destroy() {
    if (this._destroyed)
      return;
    this._destroyed = true;
    EditBuffer.registry.delete(this.id);
    this.lib.destroyEditBuffer(this.bufferPtr);
  }
}

// src/editor-view.ts
class EditorView {
  lib;
  viewPtr;
  editBuffer;
  _destroyed = false;
  _extmarksController;
  _textBufferViewPtr;
  constructor(lib, ptr, editBuffer) {
    this.lib = lib;
    this.viewPtr = ptr;
    this.editBuffer = editBuffer;
  }
  static create(editBuffer, viewportWidth, viewportHeight) {
    const lib = resolveRenderLib();
    const viewPtr = lib.createEditorView(editBuffer.ptr, viewportWidth, viewportHeight);
    return new EditorView(lib, viewPtr, editBuffer);
  }
  guard() {
    if (this._destroyed)
      throw new Error("EditorView is destroyed");
  }
  get ptr() {
    this.guard();
    return this.viewPtr;
  }
  setViewportSize(width, height) {
    this.guard();
    this.lib.editorViewSetViewportSize(this.viewPtr, width, height);
  }
  setViewport(x, y, width, height, moveCursor = true) {
    this.guard();
    this.lib.editorViewSetViewport(this.viewPtr, x, y, width, height, moveCursor);
  }
  getViewport() {
    this.guard();
    return this.lib.editorViewGetViewport(this.viewPtr);
  }
  setScrollMargin(margin) {
    this.guard();
    this.lib.editorViewSetScrollMargin(this.viewPtr, margin);
  }
  setWrapMode(mode) {
    this.guard();
    this.lib.editorViewSetWrapMode(this.viewPtr, mode);
  }
  getVirtualLineCount() {
    this.guard();
    return this.lib.editorViewGetVirtualLineCount(this.viewPtr);
  }
  getTotalVirtualLineCount() {
    this.guard();
    return this.lib.editorViewGetTotalVirtualLineCount(this.viewPtr);
  }
  setSelection(start, end, bgColor, fgColor) {
    this.guard();
    this.lib.editorViewSetSelection(this.viewPtr, start, end, bgColor || null, fgColor || null);
  }
  updateSelection(end, bgColor, fgColor) {
    this.guard();
    this.lib.editorViewUpdateSelection(this.viewPtr, end, bgColor || null, fgColor || null);
  }
  resetSelection() {
    this.guard();
    this.lib.editorViewResetSelection(this.viewPtr);
  }
  getSelection() {
    this.guard();
    return this.lib.editorViewGetSelection(this.viewPtr);
  }
  hasSelection() {
    this.guard();
    return this.getSelection() !== null;
  }
  setLocalSelection(anchorX, anchorY, focusX, focusY, bgColor, fgColor, updateCursor, followCursor, behavior = "cell") {
    this.guard();
    return this.lib.editorViewSetLocalSelection(this.viewPtr, anchorX, anchorY, focusX, focusY, bgColor || null, fgColor || null, updateCursor ?? false, followCursor ?? false, behavior);
  }
  updateLocalSelection(anchorX, anchorY, focusX, focusY, bgColor, fgColor, updateCursor, followCursor, behavior = "cell") {
    this.guard();
    return this.lib.editorViewUpdateLocalSelection(this.viewPtr, anchorX, anchorY, focusX, focusY, bgColor || null, fgColor || null, updateCursor ?? false, followCursor ?? false, behavior);
  }
  resetLocalSelection() {
    this.guard();
    this.lib.editorViewResetLocalSelection(this.viewPtr);
  }
  convertSelectionToCell() {
    this.guard();
    return this.lib.editorViewConvertSelectionToCell(this.viewPtr);
  }
  setSelectionOccupancy(occupancy) {
    this.guard();
    this.lib.editorViewSetSelectionOccupancy(this.viewPtr, occupancy);
  }
  getSelectionOccupancy() {
    this.guard();
    this._textBufferViewPtr ??= this.lib.editorViewGetTextBufferView(this.viewPtr);
    return this.lib.textBufferViewGetSelectionOccupancy(this._textBufferViewPtr);
  }
  setSelectionInclusive(start, end, bgColor, fgColor) {
    this.guard();
    this.lib.editorViewSetSelectionInclusive(this.viewPtr, start, end, bgColor || null, fgColor || null);
  }
  setSelectionColors(bgColor, fgColor) {
    this.guard();
    this.lib.editorViewSetSelectionColors(this.viewPtr, bgColor || null, fgColor || null);
  }
  getSelectedText() {
    this.guard();
    const maxLength = 1024 * 1024;
    const selectedBytes = this.lib.editorViewGetSelectedTextBytes(this.viewPtr, maxLength);
    if (!selectedBytes)
      return "";
    return this.lib.decoder.decode(selectedBytes);
  }
  getCursor() {
    this.guard();
    return this.lib.editorViewGetCursor(this.viewPtr);
  }
  getText() {
    this.guard();
    const maxLength = 1024 * 1024;
    const textBytes = this.lib.editorViewGetText(this.viewPtr, maxLength);
    if (!textBytes)
      return "";
    return this.lib.decoder.decode(textBytes);
  }
  getVisualCursor() {
    this.guard();
    return this.lib.editorViewGetVisualCursor(this.viewPtr);
  }
  moveUpVisual() {
    this.guard();
    this.lib.editorViewMoveUpVisual(this.viewPtr);
  }
  moveDownVisual() {
    this.guard();
    this.lib.editorViewMoveDownVisual(this.viewPtr);
  }
  deleteSelectedText() {
    this.guard();
    this.lib.editorViewDeleteSelectedText(this.viewPtr);
  }
  setCursorByOffset(offset) {
    this.guard();
    this.lib.editorViewSetCursorByOffset(this.viewPtr, offset);
  }
  getNextWordBoundary() {
    this.guard();
    return this.lib.editorViewGetNextWordBoundary(this.viewPtr);
  }
  getPrevWordBoundary() {
    this.guard();
    return this.lib.editorViewGetPrevWordBoundary(this.viewPtr);
  }
  getEOL() {
    this.guard();
    return this.lib.editorViewGetEOL(this.viewPtr);
  }
  getVisualSOL() {
    this.guard();
    return this.lib.editorViewGetVisualSOL(this.viewPtr);
  }
  getVisualEOL() {
    this.guard();
    return this.lib.editorViewGetVisualEOL(this.viewPtr);
  }
  gotoVisualLineEnd() {
    this.guard();
    this.lib.editorViewGotoVisualLineEnd(this.viewPtr);
  }
  getLineInfo() {
    this.guard();
    return this.lib.editorViewGetLineInfo(this.viewPtr);
  }
  getLogicalLineInfo() {
    this.guard();
    return this.lib.editorViewGetLogicalLineInfo(this.viewPtr);
  }
  get extmarks() {
    if (!this._extmarksController) {
      this._extmarksController = createExtmarksController(this.editBuffer, this);
    }
    return this._extmarksController;
  }
  setPlaceholderStyledText(chunks) {
    this.guard();
    this.lib.editorViewSetPlaceholderStyledText(this.viewPtr, chunks);
  }
  setTabIndicator(indicator) {
    this.guard();
    const codePoint = typeof indicator === "string" ? indicator.codePointAt(0) ?? 0 : indicator;
    this.lib.editorViewSetTabIndicator(this.viewPtr, codePoint);
  }
  setTabIndicatorColor(color) {
    this.guard();
    this.lib.editorViewSetTabIndicatorColor(this.viewPtr, color);
  }
  measureForDimensions(width, height) {
    this.guard();
    this._textBufferViewPtr ??= this.lib.editorViewGetTextBufferView(this.viewPtr);
    return this.lib.textBufferViewMeasureForDimensions(this._textBufferViewPtr, width, height);
  }
  destroy() {
    if (this._destroyed)
      return;
    if (this._extmarksController) {
      this._extmarksController.destroy();
      this._extmarksController = undefined;
    }
    this._destroyed = true;
    this.lib.destroyEditorView(this.viewPtr);
  }
}

// src/syntax-style.ts
function convertThemeToStyles(theme) {
  const flatStyles = {};
  for (const tokenStyle of theme) {
    const styleDefinition = {};
    if (tokenStyle.style.foreground) {
      styleDefinition.fg = parseColor(tokenStyle.style.foreground);
    }
    if (tokenStyle.style.background) {
      styleDefinition.bg = parseColor(tokenStyle.style.background);
    }
    if (tokenStyle.style.bold !== undefined) {
      styleDefinition.bold = tokenStyle.style.bold;
    }
    if (tokenStyle.style.italic !== undefined) {
      styleDefinition.italic = tokenStyle.style.italic;
    }
    if (tokenStyle.style.underline !== undefined) {
      styleDefinition.underline = tokenStyle.style.underline;
    }
    if (tokenStyle.style.dim !== undefined) {
      styleDefinition.dim = tokenStyle.style.dim;
    }
    for (const scope of tokenStyle.scope) {
      flatStyles[scope] = styleDefinition;
    }
  }
  return flatStyles;
}

class SyntaxStyle {
  lib;
  stylePtr;
  _destroyed = false;
  nameCache = new Map;
  styleDefs = new Map;
  mergedCache = new Map;
  constructor(lib, ptr) {
    this.lib = lib;
    this.stylePtr = ptr;
  }
  static create() {
    const lib = resolveRenderLib();
    const ptr = lib.createSyntaxStyle();
    return new SyntaxStyle(lib, ptr);
  }
  static fromTheme(theme) {
    const style = SyntaxStyle.create();
    const flatStyles = convertThemeToStyles(theme);
    for (const [name, styleDef] of Object.entries(flatStyles)) {
      style.registerStyle(name, styleDef);
    }
    return style;
  }
  static fromStyles(styles) {
    const style = SyntaxStyle.create();
    for (const [name, styleDef] of Object.entries(styles)) {
      style.registerStyle(name, styleDef);
    }
    return style;
  }
  guard() {
    if (this._destroyed)
      throw new Error("NativeSyntaxStyle is destroyed");
  }
  registerStyle(name, style) {
    this.guard();
    const attributes = createTextAttributes({
      bold: style.bold,
      italic: style.italic,
      underline: style.underline,
      dim: style.dim
    });
    const fg = style.fg ? parseColor(style.fg) : null;
    const bg = style.bg ? parseColor(style.bg) : null;
    const id = this.lib.syntaxStyleRegister(this.stylePtr, name, fg, bg, attributes);
    this.nameCache.set(name, id);
    this.styleDefs.set(name, { ...style, fg: fg ?? undefined, bg: bg ?? undefined });
    return id;
  }
  resolveStyleId(name) {
    this.guard();
    const cached = this.nameCache.get(name);
    if (cached !== undefined)
      return cached;
    const id = this.lib.syntaxStyleResolveByName(this.stylePtr, name);
    if (id !== null) {
      this.nameCache.set(name, id);
    }
    return id;
  }
  getStyleId(name) {
    this.guard();
    const id = this.resolveStyleId(name);
    if (id !== null)
      return id;
    if (name.includes(".")) {
      const baseName = name.split(".")[0];
      return this.resolveStyleId(baseName);
    }
    return null;
  }
  get ptr() {
    this.guard();
    return this.stylePtr;
  }
  getStyleCount() {
    this.guard();
    return this.lib.syntaxStyleGetStyleCount(this.stylePtr);
  }
  clearNameCache() {
    this.nameCache.clear();
  }
  getStyle(name) {
    this.guard();
    if (Object.prototype.hasOwnProperty.call(this.styleDefs, name)) {
      return;
    }
    const style = this.styleDefs.get(name);
    if (style)
      return style;
    if (name.includes(".")) {
      const baseName = name.split(".")[0];
      if (Object.prototype.hasOwnProperty.call(this.styleDefs, baseName)) {
        return;
      }
      return this.styleDefs.get(baseName);
    }
    return;
  }
  mergeStyles(...styleNames) {
    this.guard();
    const cacheKey = styleNames.join(":");
    const cached = this.mergedCache.get(cacheKey);
    if (cached)
      return cached;
    const styleDefinition = {};
    for (const name of styleNames) {
      const style = this.getStyle(name);
      if (!style)
        continue;
      if (style.fg)
        styleDefinition.fg = style.fg;
      if (style.bg)
        styleDefinition.bg = style.bg;
      if (style.bold !== undefined)
        styleDefinition.bold = style.bold;
      if (style.italic !== undefined)
        styleDefinition.italic = style.italic;
      if (style.underline !== undefined)
        styleDefinition.underline = style.underline;
      if (style.dim !== undefined)
        styleDefinition.dim = style.dim;
    }
    const attributes = createTextAttributes({
      bold: styleDefinition.bold,
      italic: styleDefinition.italic,
      underline: styleDefinition.underline,
      dim: styleDefinition.dim
    });
    const merged = {
      fg: styleDefinition.fg,
      bg: styleDefinition.bg,
      attributes
    };
    this.mergedCache.set(cacheKey, merged);
    return merged;
  }
  clearCache() {
    this.guard();
    this.mergedCache.clear();
  }
  getCacheSize() {
    this.guard();
    return this.mergedCache.size;
  }
  getAllStyles() {
    this.guard();
    return new Map(this.styleDefs);
  }
  getRegisteredNames() {
    this.guard();
    return Array.from(this.styleDefs.keys());
  }
  destroy() {
    if (this._destroyed)
      return;
    this._destroyed = true;
    this.nameCache.clear();
    this.styleDefs.clear();
    this.mergedCache.clear();
    this.lib.destroySyntaxStyle(this.stylePtr);
  }
}

// src/renderables/Box.ts
function isGapType(value) {
  if (value === undefined) {
    return true;
  }
  if (typeof value === "number" && !Number.isNaN(value)) {
    return true;
  }
  return isValidPercentage(value);
}

class BoxRenderable extends Renderable {
  _backgroundColor;
  _border;
  _borderStyle;
  _borderColor;
  _focusedBorderColor;
  _customBorderCharsObj;
  _customBorderChars;
  borderSides;
  shouldFill;
  _title;
  _titleColor;
  _titleAlignment;
  _bottomTitle;
  _bottomTitleAlignment;
  _defaultOptions = {
    backgroundColor: "transparent",
    borderStyle: "single",
    border: false,
    borderColor: "#FFFFFF",
    shouldFill: true,
    titleAlignment: "left",
    bottomTitleAlignment: "left",
    focusedBorderColor: "#00AAFF"
  };
  constructor(ctx, options) {
    super(ctx, options);
    if (options.focusable === true) {
      this._focusable = true;
    }
    this._backgroundColor = parseColor(options.backgroundColor || this._defaultOptions.backgroundColor);
    this._border = options.border ?? this._defaultOptions.border;
    if (!options.border && (options.borderStyle || options.borderColor || options.focusedBorderColor || options.customBorderChars)) {
      this._border = true;
    }
    this._borderStyle = parseBorderStyle(options.borderStyle, this._defaultOptions.borderStyle);
    this._borderColor = parseColor(options.borderColor || this._defaultOptions.borderColor);
    this._focusedBorderColor = parseColor(options.focusedBorderColor || this._defaultOptions.focusedBorderColor);
    this._customBorderCharsObj = options.customBorderChars;
    this._customBorderChars = this._customBorderCharsObj ? borderCharsToArray(this._customBorderCharsObj) : undefined;
    this.borderSides = getBorderSides(this._border);
    this.shouldFill = options.shouldFill ?? this._defaultOptions.shouldFill;
    this._title = options.title;
    this._titleColor = options.titleColor ? parseColor(options.titleColor) : undefined;
    this._titleAlignment = options.titleAlignment || this._defaultOptions.titleAlignment;
    this._bottomTitle = options.bottomTitle;
    this._bottomTitleAlignment = options.bottomTitleAlignment || this._defaultOptions.bottomTitleAlignment;
    this.applyYogaBorders();
    const hasInitialGapProps = options.gap !== undefined || options.rowGap !== undefined || options.columnGap !== undefined;
    if (hasInitialGapProps) {
      this.applyYogaGap(options);
    }
  }
  initializeBorder() {
    if (this._border === false) {
      this._border = true;
      this.borderSides = getBorderSides(this._border);
      this.applyYogaBorders();
    }
  }
  get customBorderChars() {
    return this._customBorderCharsObj;
  }
  set customBorderChars(value) {
    this._customBorderCharsObj = value;
    this._customBorderChars = value ? borderCharsToArray(value) : undefined;
    this.requestRender();
  }
  get backgroundColor() {
    return this._backgroundColor;
  }
  set backgroundColor(value) {
    const newColor = parseColor(value ?? this._defaultOptions.backgroundColor);
    if (this._backgroundColor !== newColor) {
      this._backgroundColor = newColor;
      this.requestRender();
    }
  }
  get border() {
    return this._border;
  }
  set border(value) {
    if (this._border !== value) {
      this._border = value;
      this.borderSides = getBorderSides(value);
      this.applyYogaBorders();
      this.requestRender();
    }
  }
  get borderStyle() {
    return this._borderStyle;
  }
  set borderStyle(value) {
    const _value = parseBorderStyle(value, this._defaultOptions.borderStyle);
    if (this._borderStyle !== _value || !this._border) {
      this._borderStyle = _value;
      this._customBorderChars = undefined;
      this.initializeBorder();
      this.requestRender();
    }
  }
  get borderColor() {
    return this._borderColor;
  }
  set borderColor(value) {
    const newColor = parseColor(value ?? this._defaultOptions.borderColor);
    if (this._borderColor !== newColor) {
      this._borderColor = newColor;
      this.initializeBorder();
      this.requestRender();
    }
  }
  get focusedBorderColor() {
    return this._focusedBorderColor;
  }
  set focusedBorderColor(value) {
    const newColor = parseColor(value ?? this._defaultOptions.focusedBorderColor);
    if (this._focusedBorderColor !== newColor) {
      this._focusedBorderColor = newColor;
      this.initializeBorder();
      if (this._focused) {
        this.requestRender();
      }
    }
  }
  get title() {
    return this._title;
  }
  set title(value) {
    if (this._title !== value) {
      this._title = value;
      this.requestRender();
    }
  }
  get titleColor() {
    return this._titleColor;
  }
  set titleColor(value) {
    const newColor = value ? parseColor(value) : undefined;
    if (this._titleColor !== newColor) {
      this._titleColor = newColor;
      this.requestRender();
    }
  }
  get titleAlignment() {
    return this._titleAlignment;
  }
  set titleAlignment(value) {
    if (this._titleAlignment !== value) {
      this._titleAlignment = value;
      this.requestRender();
    }
  }
  get bottomTitle() {
    return this._bottomTitle;
  }
  set bottomTitle(value) {
    if (this._bottomTitle !== value) {
      this._bottomTitle = value;
      this.requestRender();
    }
  }
  get bottomTitleAlignment() {
    return this._bottomTitleAlignment;
  }
  set bottomTitleAlignment(value) {
    if (this._bottomTitleAlignment !== value) {
      this._bottomTitleAlignment = value;
      this.requestRender();
    }
  }
  renderSelf(buffer) {
    const hasBorder = this.borderSides.top || this.borderSides.right || this.borderSides.bottom || this.borderSides.left;
    const hasVisibleFill = this.shouldFill && this._backgroundColor.a > 0;
    if (!hasBorder && !hasVisibleFill) {
      return;
    }
    const hasFocusWithin = this._focusable && (this._focused || this._hasFocusedDescendant);
    const currentBorderColor = hasFocusWithin ? this._focusedBorderColor : this._borderColor;
    const screenX = this._screenX;
    const screenY = this._screenY;
    buffer.drawBox({
      x: screenX,
      y: screenY,
      width: this.width,
      height: this.height,
      borderStyle: this._borderStyle,
      customBorderChars: this._customBorderChars,
      border: this._border,
      borderColor: currentBorderColor,
      backgroundColor: this._backgroundColor,
      shouldFill: this.shouldFill,
      title: this._title,
      titleColor: this._titleColor ?? currentBorderColor,
      titleAlignment: this._titleAlignment,
      bottomTitle: this._bottomTitle,
      bottomTitleAlignment: this._bottomTitleAlignment
    });
  }
  getScissorRect() {
    const baseRect = super.getScissorRect();
    if (!this.borderSides.top && !this.borderSides.right && !this.borderSides.bottom && !this.borderSides.left) {
      return baseRect;
    }
    const leftInset = this.borderSides.left ? 1 : 0;
    const rightInset = this.borderSides.right ? 1 : 0;
    const topInset = this.borderSides.top ? 1 : 0;
    const bottomInset = this.borderSides.bottom ? 1 : 0;
    return {
      x: baseRect.x + leftInset,
      y: baseRect.y + topInset,
      width: Math.max(0, baseRect.width - leftInset - rightInset),
      height: Math.max(0, baseRect.height - topInset - bottomInset)
    };
  }
  applyYogaBorders() {
    const node = this.yogaNode;
    node.setBorder(0 /* Left */, this.borderSides.left ? 1 : 0);
    node.setBorder(2 /* Right */, this.borderSides.right ? 1 : 0);
    node.setBorder(1 /* Top */, this.borderSides.top ? 1 : 0);
    node.setBorder(3 /* Bottom */, this.borderSides.bottom ? 1 : 0);
    this.requestRender();
  }
  applyYogaGap(options) {
    const node = this.yogaNode;
    if (isGapType(options.gap)) {
      node.setGap(2 /* All */, options.gap);
    }
    if (isGapType(options.rowGap)) {
      node.setGap(1 /* Row */, options.rowGap);
    }
    if (isGapType(options.columnGap)) {
      node.setGap(0 /* Column */, options.columnGap);
    }
  }
  set gap(gap) {
    if (isGapType(gap)) {
      this.yogaNode.setGap(2 /* All */, gap);
      this.requestRender();
    }
  }
  set rowGap(rowGap) {
    if (isGapType(rowGap)) {
      this.yogaNode.setGap(1 /* Row */, rowGap);
      this.requestRender();
    }
  }
  set columnGap(columnGap) {
    if (isGapType(columnGap)) {
      this.yogaNode.setGap(0 /* Column */, columnGap);
      this.requestRender();
    }
  }
}

// src/renderables/TextBufferRenderable.ts
class TextBufferRenderable extends Renderable {
  selectable = true;
  _defaultFg;
  _defaultBg;
  _defaultAttributes;
  _selectionBg;
  _selectionFg;
  _wrapMode = "word";
  lastLocalSelection = null;
  _tabIndicator;
  _tabIndicatorColor;
  _scrollX = 0;
  _scrollY = 0;
  _truncate = false;
  _firstLineOffset = 0;
  textBuffer;
  textBufferView;
  _textBufferSyntaxStyle;
  nativeRenderable = null;
  _defaultOptions = {
    fg: RGBA.fromValues(1, 1, 1, 1),
    bg: RGBA.fromValues(0, 0, 0, 0),
    selectionBg: undefined,
    selectionFg: undefined,
    selectable: true,
    attributes: 0,
    wrapMode: "word",
    tabIndicator: undefined,
    tabIndicatorColor: undefined,
    truncate: false
  };
  constructor(ctx, options) {
    super(ctx, options);
    this._defaultFg = parseColor(options.fg ?? this._defaultOptions.fg);
    this._defaultBg = parseColor(options.bg ?? this._defaultOptions.bg);
    this._defaultAttributes = options.attributes ?? this._defaultOptions.attributes;
    this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) : this._defaultOptions.selectionBg;
    this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : this._defaultOptions.selectionFg;
    this.selectable = options.selectable ?? this._defaultOptions.selectable;
    this._wrapMode = options.wrapMode ?? this._defaultOptions.wrapMode;
    this._tabIndicator = options.tabIndicator ?? this._defaultOptions.tabIndicator;
    this._tabIndicatorColor = options.tabIndicatorColor ? parseColor(options.tabIndicatorColor) : this._defaultOptions.tabIndicatorColor;
    this._truncate = options.truncate ?? this._defaultOptions.truncate;
    this.textBuffer = TextBuffer.create(this._ctx.widthMethod);
    this.textBufferView = TextBufferView.create(this.textBuffer);
    this._firstLineOffset = ctx.claimFirstLineOffset?.(this) ?? 0;
    this._textBufferSyntaxStyle = SyntaxStyle.create();
    this.textBuffer.setSyntaxStyle(this._textBufferSyntaxStyle);
    this.textBufferView.setWrapMode(this._wrapMode);
    this.textBufferView.setFirstLineOffset(this._firstLineOffset);
    this.setupNativeRenderable();
    this.textBuffer.setDefaultFg(this._defaultFg);
    this.textBuffer.setDefaultBg(this._defaultBg);
    this.textBuffer.setDefaultAttributes(this._defaultAttributes);
    if (this._tabIndicator !== undefined) {
      this.textBufferView.setTabIndicator(this._tabIndicator);
    }
    if (this._tabIndicatorColor !== undefined) {
      this.textBufferView.setTabIndicatorColor(this._tabIndicatorColor);
    }
    if (this._wrapMode !== "none" && this.width > 0) {
      this.textBufferView.setWrapWidth(this.width);
    }
    if (this.width > 0 && this.height > 0) {
      this.textBufferView.setViewport(this._scrollX, this._scrollY, this.width, this.height);
    }
    this.textBufferView.setTruncate(this._truncate);
    this.updateTextInfo();
  }
  onMouseEvent(event) {
    if (event.type === "scroll") {
      this.handleScroll(event);
    }
  }
  handleScroll(event) {
    if (!event.scroll)
      return;
    const { direction, delta } = event.scroll;
    if (direction === "up") {
      this.scrollY -= delta;
    } else if (direction === "down") {
      this.scrollY += delta;
    }
    if (this._wrapMode === "none") {
      if (direction === "left") {
        this.scrollX -= delta;
      } else if (direction === "right") {
        this.scrollX += delta;
      }
    }
  }
  get lineInfo() {
    return this.textBufferView.logicalLineInfo;
  }
  get lineCount() {
    return this.textBuffer.getLineCount();
  }
  get virtualLineCount() {
    return this.textBufferView.getVirtualLineCount();
  }
  get scrollY() {
    return this._scrollY;
  }
  set scrollY(value) {
    const maxScrollY = Math.max(0, this.scrollHeight - this.height);
    const clamped = Math.max(0, Math.min(value, maxScrollY));
    if (this._scrollY !== clamped) {
      this._scrollY = clamped;
      this.updateViewportOffset();
      this.requestRender();
    }
  }
  get scrollX() {
    return this._scrollX;
  }
  set scrollX(value) {
    const maxScrollX = Math.max(0, this.scrollWidth - this.width);
    const clamped = Math.max(0, Math.min(value, maxScrollX));
    if (this._scrollX !== clamped) {
      this._scrollX = clamped;
      this.updateViewportOffset();
      this.requestRender();
    }
  }
  get scrollWidth() {
    return this.lineInfo.lineWidthColsMax;
  }
  get scrollHeight() {
    return this.lineInfo.lineStartCols.length;
  }
  get maxScrollY() {
    return Math.max(0, this.scrollHeight - this.height);
  }
  get maxScrollX() {
    return Math.max(0, this.scrollWidth - this.width);
  }
  updateViewportOffset() {
    if (this.width > 0 && this.height > 0) {
      this.textBufferView.setViewport(this._scrollX, this._scrollY, this.width, this.height);
    }
  }
  get plainText() {
    return this.textBuffer.getPlainText();
  }
  get textLength() {
    return this.textBuffer.length;
  }
  get fg() {
    return this._defaultFg;
  }
  set fg(value) {
    const newColor = parseColor(value ?? this._defaultOptions.fg);
    if (this._defaultFg !== newColor) {
      this._defaultFg = newColor;
      this.textBuffer.setDefaultFg(this._defaultFg);
      this.onFgChanged(newColor);
      this.requestRender();
    }
  }
  get selectionBg() {
    return this._selectionBg;
  }
  set selectionBg(value) {
    const newColor = value ? parseColor(value) : this._defaultOptions.selectionBg;
    if (this._selectionBg !== newColor) {
      this._selectionBg = newColor;
      if (this.lastLocalSelection) {
        this.updateLocalSelection(this.lastLocalSelection);
      }
      this.requestRender();
    }
  }
  get selectionFg() {
    return this._selectionFg;
  }
  set selectionFg(value) {
    const newColor = value ? parseColor(value) : this._defaultOptions.selectionFg;
    if (this._selectionFg !== newColor) {
      this._selectionFg = newColor;
      if (this.lastLocalSelection) {
        this.updateLocalSelection(this.lastLocalSelection);
      }
      this.requestRender();
    }
  }
  get bg() {
    return this._defaultBg;
  }
  set bg(value) {
    const newColor = parseColor(value ?? this._defaultOptions.bg);
    if (this._defaultBg !== newColor) {
      this._defaultBg = newColor;
      this.textBuffer.setDefaultBg(this._defaultBg);
      this.onBgChanged(newColor);
      this.requestRender();
    }
  }
  get attributes() {
    return this._defaultAttributes;
  }
  set attributes(value) {
    if (this._defaultAttributes !== value) {
      this._defaultAttributes = value;
      this.textBuffer.setDefaultAttributes(this._defaultAttributes);
      this.onAttributesChanged(value);
      this.requestRender();
    }
  }
  get wrapMode() {
    return this._wrapMode;
  }
  set wrapMode(value) {
    if (this._wrapMode !== value) {
      this._wrapMode = value;
      this.textBufferView.setWrapMode(this._wrapMode);
      if (value !== "none" && this.width > 0) {
        this.textBufferView.setWrapWidth(this.width);
      }
      this.yogaNode.markDirty();
      this.requestRender();
    }
  }
  get tabIndicator() {
    return this._tabIndicator;
  }
  set tabIndicator(value) {
    if (this._tabIndicator !== value) {
      this._tabIndicator = value;
      if (value !== undefined) {
        this.textBufferView.setTabIndicator(value);
      }
      this.requestRender();
    }
  }
  get tabIndicatorColor() {
    return this._tabIndicatorColor;
  }
  set tabIndicatorColor(value) {
    const newColor = value ? parseColor(value) : undefined;
    if (this._tabIndicatorColor !== newColor) {
      this._tabIndicatorColor = newColor;
      if (newColor !== undefined) {
        this.textBufferView.setTabIndicatorColor(newColor);
      }
      this.requestRender();
    }
  }
  get truncate() {
    return this._truncate;
  }
  set truncate(value) {
    if (this._truncate !== value) {
      this._truncate = value;
      this.textBufferView.setTruncate(value);
      this.requestRender();
    }
  }
  onResize(width, height) {
    this.textBufferView.setViewport(this._scrollX, this._scrollY, width, height);
    this.yogaNode.markDirty();
    this.requestRender();
    this.emit("line-info-change");
  }
  refreshLocalSelection() {
    if (this.lastLocalSelection) {
      return this.updateLocalSelection(this.lastLocalSelection);
    }
    return false;
  }
  updateLocalSelection(localSelection) {
    if (!localSelection?.isActive) {
      this.textBufferView.resetLocalSelection();
      return true;
    }
    return this.textBufferView.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg, localSelection.behavior);
  }
  updateTextInfo() {
    if (this.lastLocalSelection) {
      this.updateLocalSelection(this.lastLocalSelection);
    }
    this.yogaNode.markDirty();
    this.requestRender();
    this.emit("line-info-change");
  }
  setupNativeRenderable() {
    const lib = resolveRenderLib();
    const nativeRenderable = lib.createNativeRenderable();
    if (!lib.nativeRenderableAttachYogaNode(nativeRenderable, this.yogaNode.ptr)) {
      lib.destroyNativeRenderable(nativeRenderable);
      throw new Error("Failed to attach native renderable Yoga node");
    }
    if (!lib.nativeRenderableSetMeasureTarget(nativeRenderable, NativeMeasureTargetKind.TextBufferView, this.textBufferView.ptr)) {
      lib.destroyNativeRenderable(nativeRenderable);
      throw new Error("Failed to attach text buffer native measure target");
    }
    this.nativeRenderable = nativeRenderable;
  }
  shouldStartSelection(x, y) {
    if (!this.selectable)
      return false;
    const localX = x - this.x;
    const localY = y - this.y;
    return localX >= 0 && localX < this.width && localY >= 0 && localY < this.height;
  }
  onSelectionChanged(selection) {
    const localSelection = convertGlobalToLocalSelection(selection, this.x, this.y);
    this.lastLocalSelection = localSelection;
    let changed;
    if (!localSelection?.isActive) {
      this.textBufferView.resetLocalSelection();
      changed = true;
    } else if (selection?.isStart) {
      changed = this.textBufferView.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg, localSelection.behavior);
    } else {
      changed = this.textBufferView.updateLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg, localSelection.behavior);
    }
    if (changed) {
      this.requestRender();
    }
    return this.hasSelection();
  }
  getSelectedText() {
    return this.textBufferView.getSelectedText();
  }
  hasSelection() {
    return this.textBufferView.hasSelection();
  }
  getSelection() {
    return this.textBufferView.getSelection();
  }
  render(buffer, deltaTime) {
    if (!this.visible)
      return;
    const screenX = this._screenX;
    const screenY = this._screenY;
    this.markClean();
    this._ctx.addToHitGrid(screenX, screenY, this.width, this.height, this.num);
    this.renderSelf(buffer);
    if (this.buffered && this.frameBuffer) {
      buffer.drawFrameBuffer(screenX, screenY, this.frameBuffer);
    }
  }
  renderSelf(buffer) {
    if (this.textBuffer.ptr) {
      buffer.drawTextBuffer(this.textBufferView, this._screenX, this._screenY);
    }
  }
  destroy() {
    if (this.isDestroyed)
      return;
    if (this.nativeRenderable) {
      resolveRenderLib().destroyNativeRenderable(this.nativeRenderable);
      this.nativeRenderable = null;
    }
    this.textBuffer.setSyntaxStyle(null);
    this._textBufferSyntaxStyle.destroy();
    this.textBufferView.destroy();
    this.textBuffer.destroy();
    super.destroy();
  }
  onFgChanged(newColor) {}
  onBgChanged(newColor) {}
  onAttributesChanged(newAttributes) {}
}

// src/renderables/Code.ts
class CodeRenderable extends TextBufferRenderable {
  _content;
  _filetype;
  _syntaxStyle;
  _isHighlighting = false;
  _treeSitterClient;
  _highlightsDirty = false;
  _highlightSnapshotId = 0;
  _highlightLoopActive = false;
  _highlightPromise;
  _highlightRerun = false;
  _conceal;
  _drawUnstyledText;
  _shouldRenderTextBuffer = true;
  _streaming;
  _initialStyledText;
  _hadInitialContent = false;
  _lastHighlights = [];
  _baseHighlight;
  _onHighlight;
  _onChunks;
  _highlightingPromise = Promise.resolve();
  _renderedLineSources;
  _mappedLineInfo;
  _contentDefaultOptions = {
    content: "",
    conceal: true,
    drawUnstyledText: true,
    streaming: false
  };
  constructor(ctx, options) {
    super(ctx, options);
    this._content = options.content ?? this._contentDefaultOptions.content;
    this._filetype = options.filetype;
    this._syntaxStyle = options.syntaxStyle;
    this._treeSitterClient = options.treeSitterClient ?? getTreeSitterClient();
    this._conceal = options.conceal ?? this._contentDefaultOptions.conceal;
    this._drawUnstyledText = options.drawUnstyledText ?? this._contentDefaultOptions.drawUnstyledText;
    this._streaming = options.streaming ?? this._contentDefaultOptions.streaming;
    this._initialStyledText = options.initialStyledText;
    this._baseHighlight = options.baseHighlight;
    this._onHighlight = options.onHighlight;
    this._onChunks = options.onChunks;
    if (this._content.length > 0) {
      if (this._initialStyledText && this._drawUnstyledText) {
        this.textBuffer.setStyledText(this._initialStyledText);
      } else {
        this.textBuffer.setText(this._content);
      }
      this.updateTextInfo();
      this._shouldRenderTextBuffer = this._drawUnstyledText || !this._filetype;
    }
    this._highlightsDirty = this._content.length > 0;
  }
  get content() {
    return this._content;
  }
  invalidateHighlights() {
    this._highlightsDirty = true;
    this._highlightSnapshotId++;
  }
  set content(value) {
    if (this._content !== value) {
      this._content = value;
      this.invalidateHighlights();
      if (this._streaming && this._filetype && !this._drawUnstyledText) {
        this.requestRender();
        return;
      }
      if (this._initialStyledText && this._drawUnstyledText) {
        this.textBuffer.setStyledText(this._initialStyledText);
      } else {
        this.textBuffer.setText(value);
      }
      this.setRenderedLineSources(undefined);
      this.updateTextInfo();
    }
  }
  get lineInfo() {
    if (!this._renderedLineSources)
      return super.lineInfo;
    if (this._mappedLineInfo)
      return this._mappedLineInfo;
    const lineInfo = super.lineInfo;
    const renderedLineSources = this._renderedLineSources;
    this._mappedLineInfo = {
      ...lineInfo,
      lineSources: lineInfo.lineSources.map((line) => renderedLineSources[line] ?? line)
    };
    return this._mappedLineInfo;
  }
  get wrapMode() {
    return super.wrapMode;
  }
  set wrapMode(value) {
    if (super.wrapMode !== value) {
      this._mappedLineInfo = undefined;
      super.wrapMode = value;
    }
  }
  onResize(width, height) {
    this._mappedLineInfo = undefined;
    super.onResize(width, height);
  }
  updateTextInfo() {
    this._mappedLineInfo = undefined;
    super.updateTextInfo();
  }
  get filetype() {
    return this._filetype;
  }
  set filetype(value) {
    if (this._filetype !== value) {
      this._filetype = value;
      this.invalidateHighlights();
    }
  }
  get syntaxStyle() {
    return this._syntaxStyle;
  }
  set syntaxStyle(value) {
    if (this._syntaxStyle !== value) {
      this._syntaxStyle = value;
      this.invalidateHighlights();
    }
  }
  get conceal() {
    return this._conceal;
  }
  set conceal(value) {
    if (this._conceal !== value) {
      this._conceal = value;
      this.invalidateHighlights();
    }
  }
  get drawUnstyledText() {
    return this._drawUnstyledText;
  }
  set drawUnstyledText(value) {
    if (this._drawUnstyledText !== value) {
      this._drawUnstyledText = value;
      this.invalidateHighlights();
    }
  }
  get streaming() {
    return this._streaming;
  }
  set initialStyledText(value) {
    if (this._initialStyledText !== value) {
      this._initialStyledText = value;
      this.invalidateHighlights();
    }
  }
  set streaming(value) {
    if (this._streaming !== value) {
      this._streaming = value;
      this._hadInitialContent = false;
      this._lastHighlights = [];
      this.invalidateHighlights();
    }
  }
  get treeSitterClient() {
    return this._treeSitterClient;
  }
  set treeSitterClient(value) {
    if (this._treeSitterClient !== value) {
      this._treeSitterClient = value;
      this.invalidateHighlights();
    }
  }
  get onHighlight() {
    return this._onHighlight;
  }
  get baseHighlight() {
    return this._baseHighlight;
  }
  set baseHighlight(value) {
    if (this._baseHighlight !== value) {
      this._baseHighlight = value;
      this.invalidateHighlights();
    }
  }
  set onHighlight(value) {
    if (this._onHighlight !== value) {
      this._onHighlight = value;
      this.invalidateHighlights();
    }
  }
  get onChunks() {
    return this._onChunks;
  }
  set onChunks(value) {
    if (this._onChunks !== value) {
      this._onChunks = value;
      this.invalidateHighlights();
    }
  }
  get isHighlighting() {
    return this._isHighlighting || this._highlightRerun;
  }
  get highlightingDone() {
    return this._highlightingPromise;
  }
  async transformChunks(chunks, context) {
    if (!this._onChunks)
      return chunks;
    const modified = await this._onChunks(chunks, context);
    return modified ?? chunks;
  }
  ensureVisibleTextBeforeHighlight() {
    if (this.isDestroyed)
      return;
    const content = this._content;
    if (!this._filetype) {
      this._shouldRenderTextBuffer = true;
      return;
    }
    const isInitialContent = this._streaming && !this._hadInitialContent;
    const shouldDrawUnstyledNow = this._streaming ? isInitialContent && this._drawUnstyledText : this._drawUnstyledText;
    if (this._streaming && !isInitialContent) {
      this._shouldRenderTextBuffer = true;
    } else if (shouldDrawUnstyledNow) {
      if (this._initialStyledText) {
        this.textBuffer.setStyledText(this._initialStyledText);
      } else {
        this.textBuffer.setText(content);
      }
      this.setRenderedLineSources(undefined);
      this._shouldRenderTextBuffer = true;
    } else {
      this._shouldRenderTextBuffer = false;
    }
  }
  async startHighlight() {
    const content = this._content;
    const filetype = this._filetype;
    const snapshotId = ++this._highlightSnapshotId;
    if (!filetype)
      return;
    const isInitialContent = this._streaming && !this._hadInitialContent;
    if (isInitialContent) {
      this._hadInitialContent = true;
    }
    this._isHighlighting = true;
    try {
      const result = await this._treeSitterClient.highlightOnce(content, filetype);
      if (snapshotId !== this._highlightSnapshotId) {
        this.requestRender();
        return;
      }
      if (this.isDestroyed)
        return;
      let highlights = result.highlights ?? [];
      if (this._onHighlight && highlights.length >= 0) {
        const context = {
          content,
          filetype,
          syntaxStyle: this._syntaxStyle
        };
        const modified = await this._onHighlight(highlights, context);
        if (modified !== undefined) {
          highlights = modified;
        }
      }
      if (snapshotId !== this._highlightSnapshotId) {
        this.requestRender();
        return;
      }
      if (this.isDestroyed)
        return;
      if (highlights.length > 0) {
        if (this._streaming) {
          this._lastHighlights = highlights;
        }
      }
      if (highlights.length > 0 || this._onChunks || this._baseHighlight) {
        const context = {
          content,
          filetype,
          syntaxStyle: this._syntaxStyle,
          highlights
        };
        let chunks = treeSitterToTextChunks(content, highlights, this._syntaxStyle, {
          enabled: this._conceal,
          baseHighlight: this._baseHighlight
        });
        const renderedLineSources = this._onChunks ? undefined : this.getConcealLinesSourceMap(content, highlights);
        chunks = await this.transformChunks(chunks, context);
        if (snapshotId !== this._highlightSnapshotId) {
          this.requestRender();
          return;
        }
        if (this.isDestroyed)
          return;
        const styledText = new StyledText(chunks);
        this.textBuffer.setStyledText(styledText);
        this.setRenderedLineSources(renderedLineSources);
      } else {
        this.textBuffer.setText(content);
        this.setRenderedLineSources(undefined);
      }
      this._shouldRenderTextBuffer = true;
      this._isHighlighting = false;
      this._highlightsDirty = false;
      this.updateTextInfo();
      this.requestRender();
    } catch (error) {
      if (snapshotId !== this._highlightSnapshotId) {
        this.requestRender();
        return;
      }
      console.warn("Code highlighting failed, falling back to plain text:", error);
      if (this.isDestroyed)
        return;
      this.textBuffer.setText(content);
      this.setRenderedLineSources(undefined);
      this._shouldRenderTextBuffer = true;
      this._isHighlighting = false;
      this._highlightsDirty = false;
      this.updateTextInfo();
      this.requestRender();
    }
  }
  async runHighlights() {
    try {
      do {
        this._highlightRerun = false;
        await this.startHighlight();
      } while (this._highlightRerun && !this.isDestroyed && this._content.length > 0 && this._filetype);
    } finally {
      this._highlightLoopActive = false;
      this._highlightRerun = false;
    }
  }
  clearPendingHighlight() {
    this._highlightSnapshotId++;
    this._isHighlighting = false;
    this._highlightRerun = false;
    this._highlightingPromise = Promise.resolve();
  }
  setRenderedLineSources(lineSources) {
    this._renderedLineSources = lineSources;
    this._mappedLineInfo = undefined;
  }
  static isIdentityLineSources(lineSources) {
    for (let i = 0;i < lineSources.length; i++) {
      if (lineSources[i] !== i)
        return false;
    }
    return true;
  }
  static getMergedConcealLineRanges(highlights) {
    const ranges = [];
    for (const highlight of highlights) {
      const meta = highlight[3];
      if (meta?.concealLines === undefined)
        continue;
      const group = highlight[2];
      const isEmptyConceal = meta.conceal === "" || meta.conceal === undefined && (group === "conceal" || group.startsWith("conceal."));
      if (isEmptyConceal) {
        ranges.push([highlight[0], highlight[1]]);
      }
    }
    if (ranges.length <= 1)
      return ranges;
    ranges.sort((a, b) => a[0] - b[0]);
    let writeIndex = 0;
    for (let i = 1;i < ranges.length; i++) {
      const current = ranges[writeIndex];
      const next = ranges[i];
      if (next[0] <= current[1]) {
        current[1] = Math.max(current[1], next[1]);
      } else {
        writeIndex++;
        ranges[writeIndex] = next;
      }
    }
    ranges.length = writeIndex + 1;
    return ranges;
  }
  getConcealLinesSourceMap(content, highlights) {
    if (!this._conceal || content.length === 0)
      return;
    const concealLineRanges = CodeRenderable.getMergedConcealLineRanges(highlights);
    if (concealLineRanges.length === 0)
      return;
    const lineSources = [];
    let sourceLine = 0;
    let lineStart = 0;
    let rangeIndex = 0;
    let currentRenderedLineHasText = false;
    const setCurrentRenderedLineSource = (line, hasText) => {
      if (lineSources.length === 0) {
        lineSources.push(line);
      } else if (!currentRenderedLineHasText) {
        lineSources[lineSources.length - 1] = line;
      }
      if (hasText)
        currentRenderedLineHasText = true;
    };
    while (lineStart <= content.length) {
      const newlineOffset = content.indexOf(`
`, lineStart);
      const lineEnd = newlineOffset === -1 ? content.length : newlineOffset;
      while (rangeIndex < concealLineRanges.length && concealLineRanges[rangeIndex][1] <= lineStart) {
        rangeIndex++;
      }
      const range = concealLineRanges[rangeIndex];
      const fullyConcealed = !!range && lineEnd > lineStart && range[0] <= lineStart && range[1] >= lineEnd;
      const lineBreakConcealed = newlineOffset !== -1 && !!range && range[0] <= newlineOffset && range[1] >= newlineOffset;
      if (!fullyConcealed || !lineBreakConcealed) {
        const hasText = lineEnd > lineStart && !fullyConcealed;
        if (hasText || newlineOffset !== -1 || !fullyConcealed) {
          setCurrentRenderedLineSource(sourceLine, hasText);
        }
        if (newlineOffset !== -1 && !lineBreakConcealed) {
          lineSources.push(sourceLine + 1);
          currentRenderedLineHasText = false;
        }
      }
      sourceLine++;
      if (newlineOffset === -1)
        break;
      lineStart = newlineOffset + 1;
    }
    if (lineSources.length === 0 || CodeRenderable.isIdentityLineSources(lineSources))
      return;
    return lineSources;
  }
  getLineHighlights(lineIdx) {
    return this.textBuffer.getLineHighlights(lineIdx);
  }
  renderSelf(buffer) {
    if (this._highlightsDirty) {
      if (this.isDestroyed)
        return;
      const hasContent = this._content.length > 0;
      if (!hasContent || !this._filetype) {
        this._shouldRenderTextBuffer = hasContent;
        this._highlightsDirty = false;
        this.clearPendingHighlight();
        if (hasContent) {
          this.textBuffer.setText(this._content);
          this.setRenderedLineSources(undefined);
          this.updateTextInfo();
        }
      } else {
        this.ensureVisibleTextBeforeHighlight();
        this._highlightsDirty = false;
        if (this._highlightLoopActive) {
          this._isHighlighting = true;
          this._highlightRerun = true;
          this._highlightingPromise = this._highlightPromise;
        } else {
          const { promise: highlightingPromise, resolve, reject } = Promise.withResolvers();
          this._highlightLoopActive = true;
          this._highlightPromise = highlightingPromise;
          this._highlightingPromise = highlightingPromise;
          const clearHighlight = () => {
            if (this._highlightPromise === highlightingPromise) {
              this._highlightPromise = undefined;
            }
          };
          this.runHighlights().then(() => {
            clearHighlight();
            resolve();
          }, (error) => {
            clearHighlight();
            reject(error);
          });
        }
      }
    }
    if (!this._shouldRenderTextBuffer)
      return;
    super.renderSelf(buffer);
  }
  destroy() {
    if (this.isDestroyed)
      return;
    this.clearPendingHighlight();
    super.destroy();
  }
}

// src/renderables/TextNode.ts
var BrandedTextNodeRenderable = Symbol.for("@opentui/core/TextNodeRenderable");
function isTextNodeRenderable(obj) {
  return !!obj?.[BrandedTextNodeRenderable];
}
function styledTextToTextNodes(styledText) {
  return styledText.chunks.map((chunk) => {
    const node = new TextNodeRenderable({
      fg: chunk.fg,
      bg: chunk.bg,
      attributes: chunk.attributes,
      link: chunk.link
    });
    node.add(chunk.text);
    return node;
  });
}

class TextNodeRenderable extends BaseRenderable {
  [BrandedTextNodeRenderable] = true;
  _fg;
  _bg;
  _attributes;
  _link;
  _children = [];
  parent = null;
  constructor(options) {
    super(options);
    this._fg = options.fg ? parseColor(options.fg) : undefined;
    this._bg = options.bg ? parseColor(options.bg) : undefined;
    this._attributes = options.attributes ?? 0;
    this._link = options.link;
  }
  get children() {
    return this._children;
  }
  set children(children) {
    for (const child of this._children) {
      if (isTextNodeRenderable(child) && child.parent === this) {
        child.parent = null;
      }
    }
    for (const child of children) {
      if (isTextNodeRenderable(child)) {
        if (child.parent && child.parent !== this) {
          child.parent.remove(child);
        }
        child.parent = this;
      }
    }
    this._children = children;
    this.requestRender();
  }
  requestRender() {
    this.markDirty();
    this.parent?.requestRender();
  }
  add(obj, index) {
    if (typeof obj === "string") {
      if (index !== undefined) {
        this._children.splice(index, 0, obj);
        this.requestRender();
        return index;
      }
      const insertIndex = this._children.length;
      this._children.push(obj);
      this.requestRender();
      return insertIndex;
    }
    if (isTextNodeRenderable(obj)) {
      const insertIndex = this.prepareChildInsert(obj, index);
      this._children.splice(insertIndex, 0, obj);
      obj.parent = this;
      this.requestRender();
      return insertIndex;
    }
    if (isStyledText(obj)) {
      const textNodes = styledTextToTextNodes(obj);
      if (index !== undefined) {
        this._children.splice(index, 0, ...textNodes);
        textNodes.forEach((node) => node.parent = this);
        this.requestRender();
        return index;
      }
      const insertIndex = this._children.length;
      this._children.push(...textNodes);
      textNodes.forEach((node) => node.parent = this);
      this.requestRender();
      return insertIndex;
    }
    throw new Error("TextNodeRenderable only accepts strings, TextNodeRenderable instances, or StyledText instances");
  }
  prepareChildInsert(child, index) {
    let insertIndex = index ?? this._children.length;
    if (child.parent && child.parent !== this) {
      child.parent.remove(child);
    } else if (child.parent === this) {
      const currentIndex = this._children.indexOf(child);
      if (currentIndex !== -1) {
        this._children.splice(currentIndex, 1);
        if (currentIndex < insertIndex)
          insertIndex -= 1;
      }
    }
    return Math.max(0, Math.min(insertIndex, this._children.length));
  }
  replace(obj, index) {
    const existing = this._children[index];
    if (isTextNodeRenderable(existing) && existing.parent === this) {
      existing.parent = null;
    }
    if (isTextNodeRenderable(obj)) {
      if (obj.parent && obj.parent !== this) {
        obj.parent.remove(obj);
      } else if (obj.parent === this) {
        const currentIndex = this._children.indexOf(obj);
        if (currentIndex !== -1 && currentIndex !== index) {
          this._children.splice(currentIndex, 1);
          if (currentIndex < index)
            index -= 1;
        }
      }
      obj.parent = this;
    }
    this._children[index] = obj;
    this.requestRender();
  }
  insertBefore(child, anchorNode) {
    if (!anchorNode || !isTextNodeRenderable(anchorNode)) {
      throw new Error("Anchor must be a TextNodeRenderable");
    }
    const anchorIndex = this._children.indexOf(anchorNode);
    if (anchorIndex === -1) {
      throw new Error("Anchor node not found in children");
    }
    if (child === anchorNode) {
      return this;
    }
    if (isTextNodeRenderable(child)) {
      this.add(child, anchorIndex);
      return this;
    }
    if (typeof child === "string") {
      this._children.splice(anchorIndex, 0, child);
    } else if (isStyledText(child)) {
      const textNodes = styledTextToTextNodes(child);
      this._children.splice(anchorIndex, 0, ...textNodes);
      textNodes.forEach((node) => node.parent = this);
    } else {
      throw new Error("Child must be a string, TextNodeRenderable, or StyledText instance");
    }
    this.requestRender();
    return this;
  }
  remove(child) {
    if (!isTextNodeRenderable(child)) {
      throw new Error("remove expects a TextNodeRenderable child object");
    }
    const childIndex = this._children.indexOf(child);
    if (childIndex === -1) {
      if (true) {
        console.warn(`TextNodeRenderable with id ${child.id} is not a child of ${this.id}, skipping remove`);
      }
      return;
    }
    this._children.splice(childIndex, 1);
    child.parent = null;
    this.requestRender();
  }
  clear() {
    for (const child of this._children) {
      if (isTextNodeRenderable(child) && child.parent === this) {
        child.parent = null;
      }
    }
    this._children = [];
    this.requestRender();
  }
  mergeStyles(parentStyle) {
    return {
      fg: this._fg ?? parentStyle.fg,
      bg: this._bg ?? parentStyle.bg,
      attributes: this._attributes | parentStyle.attributes,
      link: this._link ?? parentStyle.link
    };
  }
  gatherWithInheritedStyle(parentStyle = {
    fg: undefined,
    bg: undefined,
    attributes: 0
  }) {
    const currentStyle = this.mergeStyles(parentStyle);
    const chunks = [];
    for (const child of this._children) {
      if (typeof child === "string") {
        chunks.push({
          __isChunk: true,
          text: child,
          fg: currentStyle.fg,
          bg: currentStyle.bg,
          attributes: currentStyle.attributes,
          link: currentStyle.link
        });
      } else {
        const childChunks = child.gatherWithInheritedStyle(currentStyle);
        chunks.push(...childChunks);
      }
    }
    this.markClean();
    return chunks;
  }
  static fromString(text, options = {}) {
    const node = new TextNodeRenderable(options);
    node.add(text);
    return node;
  }
  static fromNodes(nodes, options = {}) {
    const node = new TextNodeRenderable(options);
    for (const childNode of nodes) {
      node.add(childNode);
    }
    return node;
  }
  toChunks(parentStyle = {
    fg: undefined,
    bg: undefined,
    attributes: 0
  }) {
    return this.gatherWithInheritedStyle(parentStyle);
  }
  getChildren() {
    return this._children.filter((child) => typeof child !== "string");
  }
  getChildrenCount() {
    return this._children.length;
  }
  getRenderable(id) {
    return this._children.find((child) => typeof child !== "string" && child.id === id);
  }
  getRenderableIndex(id) {
    return this._children.findIndex((child) => isTextNodeRenderable(child) && child.id === id);
  }
  get fg() {
    return this._fg;
  }
  set fg(fg) {
    if (!fg) {
      this._fg = undefined;
      this.requestRender();
      return;
    }
    this._fg = parseColor(fg);
    this.requestRender();
  }
  set bg(bg) {
    if (!bg) {
      this._bg = undefined;
      this.requestRender();
      return;
    }
    this._bg = parseColor(bg);
    this.requestRender();
  }
  get bg() {
    return this._bg;
  }
  set attributes(attributes) {
    this._attributes = attributes;
    this.requestRender();
  }
  get attributes() {
    return this._attributes;
  }
  set link(link) {
    this._link = link;
    this.requestRender();
  }
  get link() {
    return this._link;
  }
  findDescendantById(id) {
    return;
  }
}

class RootTextNodeRenderable extends TextNodeRenderable {
  ctx;
  textParent;
  constructor(ctx, options, textParent) {
    super(options);
    this.ctx = ctx;
    this.textParent = textParent;
  }
  requestRender() {
    this.markDirty();
    this.ctx.requestRender();
  }
}

// src/renderables/Text.ts
class TextRenderable extends TextBufferRenderable {
  _text;
  _hasManualStyledText = false;
  rootTextNode;
  _contentDefaultOptions = {
    content: ""
  };
  constructor(ctx, options) {
    super(ctx, options);
    const content = options.content ?? this._contentDefaultOptions.content;
    const styledText = typeof content === "string" ? stringToStyledText(content) : content;
    this._text = styledText;
    this._hasManualStyledText = options.content !== undefined && content !== "";
    this.rootTextNode = new RootTextNodeRenderable(ctx, {
      id: `${this.id}-root`,
      fg: this._defaultFg,
      bg: this._defaultBg,
      attributes: this._defaultAttributes
    }, this);
    this.updateTextBuffer(styledText);
  }
  updateTextBuffer(styledText) {
    this.textBuffer.setStyledText(styledText);
    this.clearChunks(styledText);
  }
  clearChunks(styledText) {}
  get content() {
    return this._text;
  }
  get chunks() {
    return this._text.chunks;
  }
  get textNode() {
    return this.rootTextNode;
  }
  set content(value) {
    this._hasManualStyledText = true;
    const styledText = typeof value === "string" ? stringToStyledText(value) : value;
    if (this._text !== styledText) {
      this._text = styledText;
      this.updateTextBuffer(styledText);
      this.updateTextInfo();
    }
  }
  updateTextFromNodes() {
    if (this.rootTextNode.isDirty && !this._hasManualStyledText) {
      const chunks = this.rootTextNode.gatherWithInheritedStyle({
        fg: this._defaultFg,
        bg: this._defaultBg,
        attributes: this._defaultAttributes,
        link: undefined
      });
      this.textBuffer.setStyledText(new StyledText(chunks));
      this.refreshLocalSelection();
      this.yogaNode.markDirty();
    }
  }
  add(obj, index) {
    return this.rootTextNode.add(obj, index);
  }
  remove(child) {
    this.rootTextNode.remove(child);
  }
  insertBefore(obj, anchor) {
    this.rootTextNode.insertBefore(obj, anchor);
    return this.rootTextNode.children.indexOf(obj);
  }
  getTextChildren() {
    return this.rootTextNode.getChildren();
  }
  clear() {
    this.rootTextNode.clear();
    const emptyStyledText = stringToStyledText("");
    this._text = emptyStyledText;
    this.updateTextBuffer(emptyStyledText);
    this.updateTextInfo();
    this.requestRender();
  }
  onLifecyclePass = () => {
    this.updateTextFromNodes();
  };
  onFgChanged(newColor) {
    this.rootTextNode.fg = newColor;
  }
  onBgChanged(newColor) {
    this.rootTextNode.bg = newColor;
  }
  onAttributesChanged(newAttributes) {
    this.rootTextNode.attributes = newAttributes;
  }
  destroy() {
    this.rootTextNode.children.length = 0;
    super.destroy();
  }
}

// src/NativeSpanFeed.ts
function toNumber(value) {
  return typeof value === "bigint" ? Number(value) : value;
}
var canThrowAcrossNativeCallback = typeof process !== "undefined" && typeof process.versions === "object" && process.versions !== null && typeof process.versions.bun === "string";

class NativeSpanFeed {
  static create(options) {
    const lib = resolveRenderLib();
    const streamPtr = lib.createNativeSpanFeed(options);
    const stream = new NativeSpanFeed(streamPtr);
    lib.registerNativeSpanFeedStream(streamPtr, stream.eventHandler);
    const status = lib.attachNativeSpanFeed(streamPtr);
    if (status !== 0) {
      lib.unregisterNativeSpanFeedStream(streamPtr);
      lib.destroyNativeSpanFeed(streamPtr);
      throw new Error(`Failed to attach stream: ${status}`);
    }
    return stream;
  }
  static attach(streamPtr, _options) {
    const lib = resolveRenderLib();
    const stream = new NativeSpanFeed(streamPtr);
    lib.registerNativeSpanFeedStream(streamPtr, stream.eventHandler);
    const status = lib.attachNativeSpanFeed(streamPtr);
    if (status !== 0) {
      lib.unregisterNativeSpanFeedStream(streamPtr);
      throw new Error(`Failed to attach stream: ${status}`);
    }
    return stream;
  }
  streamPtr;
  lib = resolveRenderLib();
  eventHandler;
  chunkMap = new Map;
  chunkSizes = new Map;
  dataHandlers = new Set;
  errorHandlers = new Set;
  drainBuffer = null;
  stateBuffer = null;
  closed = false;
  destroyed = false;
  draining = false;
  pendingDataAvailable = false;
  pendingClose = false;
  closing = false;
  pendingAsyncHandlers = 0;
  inCallback = false;
  closeQueued = false;
  idleResolvers = [];
  pendingHandlerError = null;
  pendingHandlerErrorQueued = false;
  constructor(streamPtr) {
    this.streamPtr = streamPtr;
    this.eventHandler = (eventId, arg0, arg1) => {
      this.handleEvent(eventId, arg0, arg1);
    };
    this.ensureDrainBuffer();
  }
  ensureDrainBuffer() {
    if (this.drainBuffer)
      return;
    const capacity = 256;
    this.drainBuffer = new Uint8Array(capacity * SpanInfoStruct.size);
  }
  onData(handler) {
    this.dataHandlers.add(handler);
    if (this.pendingDataAvailable) {
      this.pendingDataAvailable = false;
      this.drainAll();
    }
    return () => this.dataHandlers.delete(handler);
  }
  onError(handler) {
    this.errorHandlers.add(handler);
    return () => this.errorHandlers.delete(handler);
  }
  hasPinnedChunks() {
    if (!this.stateBuffer)
      return false;
    for (const refcount of this.stateBuffer) {
      if (refcount > 0)
        return true;
    }
    return false;
  }
  isBackpressured() {
    return this.pendingAsyncHandlers > 0 || this.pendingDataAvailable || this.hasPinnedChunks();
  }
  close() {
    if (this.destroyed)
      return;
    if (this.inCallback || this.draining || this.pendingAsyncHandlers > 0) {
      this.pendingClose = true;
      if (!this.closeQueued) {
        this.closeQueued = true;
        queueMicrotask(() => {
          this.closeQueued = false;
          this.processPendingClose();
        });
      }
      return;
    }
    this.performClose();
  }
  processPendingClose() {
    if (!this.pendingClose || this.destroyed)
      return;
    if (this.inCallback || this.draining || this.pendingAsyncHandlers > 0)
      return;
    this.pendingClose = false;
    this.performClose();
    this.resolveIdleIfNeeded();
  }
  performClose() {
    if (this.closing)
      return;
    this.closing = true;
    if (!this.closed) {
      const status = this.lib.streamClose(this.streamPtr);
      if (status !== 0) {
        this.closing = false;
        return;
      }
      this.closed = true;
    }
    this.finalizeDestroy();
  }
  finalizeDestroy() {
    if (this.destroyed)
      return;
    this.lib.unregisterNativeSpanFeedStream(this.streamPtr);
    this.lib.destroyNativeSpanFeed(this.streamPtr);
    this.destroyed = true;
    this.chunkMap.clear();
    this.chunkSizes.clear();
    this.stateBuffer = null;
    this.drainBuffer = null;
    this.dataHandlers.clear();
    this.errorHandlers.clear();
    this.pendingDataAvailable = false;
    this.resolveIdleIfNeeded();
  }
  isIdle() {
    return !this.inCallback && !this.draining && this.pendingAsyncHandlers === 0 && !this.pendingDataAvailable && !this.hasPinnedChunks();
  }
  resolveIdleIfNeeded() {
    if (!this.isIdle())
      return;
    const resolvers = this.idleResolvers.splice(0);
    for (const resolve of resolvers) {
      resolve();
    }
  }
  idle() {
    if (this.isIdle())
      return Promise.resolve();
    return new Promise((resolve) => {
      this.idleResolvers.push(resolve);
    });
  }
  handleEvent(eventId, arg0, arg1) {
    this.inCallback = true;
    try {
      switch (eventId) {
        case 8 /* StateBuffer */: {
          const len = toNumber(arg1);
          if (len > 0 && arg0) {
            const buffer = toArrayBuffer(arg0, 0, len);
            this.stateBuffer = new Uint8Array(buffer);
          }
          break;
        }
        case 7 /* DataAvailable */: {
          if (this.closing)
            break;
          if (this.dataHandlers.size === 0) {
            this.pendingDataAvailable = true;
            break;
          }
          this.drainAll();
          break;
        }
        case 2 /* ChunkAdded */: {
          const chunkLen = toNumber(arg1);
          if (chunkLen > 0 && arg0) {
            if (!this.chunkMap.has(arg0)) {
              const buffer = toArrayBuffer(arg0, 0, chunkLen);
              this.chunkMap.set(arg0, buffer);
            }
            this.chunkSizes.set(arg0, chunkLen);
          }
          break;
        }
        case 6 /* Error */: {
          const code = toNumber(arg0);
          for (const handler of this.errorHandlers)
            handler(code);
          break;
        }
        case 5 /* Closed */: {
          this.closed = true;
          break;
        }
        default:
          break;
      }
    } finally {
      this.inCallback = false;
      this.resolveIdleIfNeeded();
    }
  }
  decrementRefcount(chunkIndex) {
    if (this.stateBuffer && chunkIndex < this.stateBuffer.length) {
      const prev = this.stateBuffer[chunkIndex];
      this.stateBuffer[chunkIndex] = prev > 0 ? prev - 1 : 0;
    }
  }
  queuePendingHandlerError(error) {
    this.pendingHandlerError ??= error;
    if (this.pendingHandlerErrorQueued)
      return;
    this.pendingHandlerErrorQueued = true;
    queueMicrotask(() => {
      this.pendingHandlerErrorQueued = false;
      if (this.pendingHandlerError === null)
        return;
      const pendingError = this.pendingHandlerError;
      this.pendingHandlerError = null;
      throw pendingError;
    });
  }
  throwPendingHandlerError() {
    if (this.pendingHandlerError === null)
      return;
    const pendingError = this.pendingHandlerError;
    this.pendingHandlerError = null;
    throw pendingError;
  }
  drainOnce() {
    if (!this.drainBuffer || this.draining || this.pendingClose)
      return 0;
    const capacity = Math.floor(this.drainBuffer.byteLength / SpanInfoStruct.size);
    if (capacity === 0)
      return 0;
    const count = this.lib.streamDrainSpans(this.streamPtr, this.drainBuffer, capacity);
    if (count === 0)
      return 0;
    this.draining = true;
    const spans = SpanInfoStruct.unpackList(this.drainBuffer.buffer, count);
    let firstError = null;
    try {
      for (const span of spans) {
        if (span.len === 0)
          continue;
        let buffer = this.chunkMap.get(span.chunkPtr);
        if (!buffer) {
          const size = this.chunkSizes.get(span.chunkPtr);
          if (!size)
            continue;
          buffer = toArrayBuffer(span.chunkPtr, 0, size);
          this.chunkMap.set(span.chunkPtr, buffer);
        }
        if (span.offset + span.len > buffer.byteLength)
          continue;
        const slice = new Uint8Array(buffer, span.offset, span.len);
        let asyncResults = null;
        for (const handler of this.dataHandlers) {
          try {
            const result = handler(slice);
            if (result && typeof result.then === "function") {
              asyncResults ??= [];
              asyncResults.push(result);
            }
          } catch (e) {
            firstError ??= e;
          }
        }
        const shouldStopAfterThisSpan = this.pendingClose;
        if (asyncResults) {
          const chunkIndex = span.chunkIndex;
          this.pendingAsyncHandlers += 1;
          Promise.allSettled(asyncResults).then(() => {
            this.decrementRefcount(chunkIndex);
            this.pendingAsyncHandlers -= 1;
            this.processPendingClose();
            this.resolveIdleIfNeeded();
          });
        } else {
          this.decrementRefcount(span.chunkIndex);
        }
        if (shouldStopAfterThisSpan)
          break;
      }
    } finally {
      this.draining = false;
      this.resolveIdleIfNeeded();
    }
    if (firstError) {
      if (!this.inCallback || canThrowAcrossNativeCallback) {
        throw firstError;
      }
      this.queuePendingHandlerError(firstError);
    }
    return count;
  }
  drainAll() {
    let count = this.drainOnce();
    while (count > 0) {
      count = this.drainOnce();
    }
    if (!this.inCallback) {
      this.throwPendingHandlerError();
    }
  }
}

// src/console.ts
import { EventEmitter as EventEmitter4 } from "events";
import { Console } from "console";
import fs from "fs";
import path from "path";
import util2 from "util";

// src/lib/output.capture.ts
import { Writable } from "stream";
import { EventEmitter as EventEmitter3 } from "events";

class Capture extends EventEmitter3 {
  output = [];
  constructor() {
    super();
  }
  get size() {
    return this.output.length;
  }
  write(stream, data) {
    this.output.push({ stream, output: data });
    this.emit("write", stream, data);
  }
  claimOutput() {
    const output = this.output.map((o) => o.output).join("");
    this.clear();
    return output;
  }
  clear() {
    this.output = [];
  }
}

class CapturedWritableStream extends Writable {
  stream;
  capture;
  isTTY = true;
  columns = process.stdout.columns || 80;
  rows = process.stdout.rows || 24;
  constructor(stream, capture) {
    super();
    this.stream = stream;
    this.capture = capture;
  }
  _write(chunk, encoding, callback) {
    const data = chunk.toString();
    this.capture.write(this.stream, data);
    callback();
  }
  getColorDepth() {
    return process.stdout.getColorDepth?.() || 8;
  }
}

// src/lib/keybinding.internal.ts
var defaultKeyAliases = {
  enter: "return",
  esc: "escape",
  kp0: "0",
  kp1: "1",
  kp2: "2",
  kp3: "3",
  kp4: "4",
  kp5: "5",
  kp6: "6",
  kp7: "7",
  kp8: "8",
  kp9: "9",
  kpdecimal: ".",
  kpdivide: "/",
  kpmultiply: "*",
  kpminus: "-",
  kpplus: "+",
  kpenter: "enter",
  kpequal: "=",
  kpseparator: ",",
  kpleft: "left",
  kpright: "right",
  kpup: "up",
  kpdown: "down",
  kppageup: "pageup",
  kppagedown: "pagedown",
  kphome: "home",
  kpend: "end",
  kpinsert: "insert",
  kpdelete: "delete"
};
function mergeKeyAliases(defaults, custom) {
  return { ...defaults, ...custom };
}
function mergeKeyBindings(defaults, custom) {
  const map = new Map;
  for (const binding of defaults) {
    const key = getKeyBindingKey(binding);
    map.set(key, binding);
  }
  for (const binding of custom) {
    const key = getKeyBindingKey(binding);
    map.set(key, binding);
  }
  return Array.from(map.values());
}
function getKeyBindingKey(binding) {
  return `${binding.name}:${binding.ctrl ? 1 : 0}:${binding.shift ? 1 : 0}:${binding.meta ? 1 : 0}:${binding.super ? 1 : 0}`;
}
function getBaseCodeKeyName(baseCode) {
  if (baseCode === undefined || baseCode < 32 || baseCode === 127) {
    return;
  }
  try {
    const name = String.fromCodePoint(baseCode);
    if (name.length === 1 && name >= "A" && name <= "Z") {
      return name.toLowerCase();
    }
    return name;
  } catch {
    return;
  }
}
function getKeyBindingKeys(binding) {
  const names = new Set([binding.name]);
  const baseCodeName = getBaseCodeKeyName(binding.baseCode);
  if (baseCodeName) {
    names.add(baseCodeName);
  }
  return [...names].map((name) => getKeyBindingKey({ ...binding, name }));
}
function getKeyBindingAction(map, binding) {
  for (const key of getKeyBindingKeys(binding)) {
    const action = map.get(key);
    if (action !== undefined) {
      return action;
    }
  }
  return;
}
function matchesKeyBinding(binding, match) {
  const matchKey = getKeyBindingKey(match);
  return getKeyBindingKeys(binding).includes(matchKey);
}
function buildKeyBindingsMap(bindings, aliasMap) {
  const map = new Map;
  const aliases = aliasMap || {};
  for (const binding of bindings) {
    const key = getKeyBindingKey(binding);
    map.set(key, binding.action);
  }
  for (const binding of bindings) {
    const normalizedName = aliases[binding.name] || binding.name;
    if (normalizedName !== binding.name) {
      const aliasedKey = getKeyBindingKey({ ...binding, name: normalizedName });
      map.set(aliasedKey, binding.action);
    }
  }
  return map;
}
function keyBindingToString(binding) {
  const parts = [];
  if (binding.ctrl)
    parts.push("ctrl");
  if (binding.shift)
    parts.push("shift");
  if (binding.meta)
    parts.push("meta");
  if (binding.super)
    parts.push("super");
  parts.push(binding.name);
  return parts.join("+");
}

// src/console.ts
function getCallerInfo() {
  const err = new Error;
  const stackLines = err.stack?.split(`
`).slice(5) || [];
  if (!stackLines.length)
    return null;
  const callerLine = stackLines[0].trim();
  const regex = /at\s+(?:([\w$.<>]+)\s+\()?((?:\/|[A-Za-z]:\\)[^:]+):(\d+):(\d+)\)?/;
  const match = callerLine.match(regex);
  if (!match)
    return null;
  const functionName = match[1] || "<anonymous>";
  const fullPath = match[2];
  const fileName = fullPath.split(/[\\/]/).pop() || "<unknown>";
  const lineNumber = parseInt(match[3], 10) || 0;
  const columnNumber = parseInt(match[4], 10) || 0;
  return { functionName, fullPath, fileName, lineNumber, columnNumber };
}
var capture = singleton("ConsoleCapture", () => new Capture);
registerEnvVar({
  name: "OTUI_USE_CONSOLE",
  description: "Whether to use the console. Will not capture console output if set to false.",
  type: "boolean",
  default: true
});
registerEnvVar({
  name: "SHOW_CONSOLE",
  description: "Show the console at startup if set to true.",
  type: "boolean",
  default: false
});

class TerminalConsoleCache extends EventEmitter4 {
  _cachedLogs = [];
  MAX_CACHE_SIZE = 1000;
  _collectCallerInfo = false;
  _cachingEnabled = true;
  _originalConsole = null;
  get cachedLogs() {
    return this._cachedLogs;
  }
  constructor() {
    super();
  }
  activate() {
    if (!env.OTUI_USE_CONSOLE)
      return;
    if (!this._originalConsole) {
      this._originalConsole = global.console;
    }
    this.setupConsoleCapture();
    this.overrideConsoleMethods();
  }
  setupConsoleCapture() {
    if (!env.OTUI_USE_CONSOLE)
      return;
    const mockStdout = new CapturedWritableStream("stdout", capture);
    const mockStderr = new CapturedWritableStream("stderr", capture);
    global.console = new Console({
      stdout: mockStdout,
      stderr: mockStderr,
      colorMode: true,
      inspectOptions: {
        compact: false,
        breakLength: 80,
        depth: 2
      }
    });
  }
  overrideConsoleMethods() {
    console.log = (...args) => {
      this.appendToConsole("LOG" /* LOG */, ...args);
    };
    console.info = (...args) => {
      this.appendToConsole("INFO" /* INFO */, ...args);
    };
    console.warn = (...args) => {
      this.appendToConsole("WARN" /* WARN */, ...args);
    };
    console.error = (...args) => {
      this.appendToConsole("ERROR" /* ERROR */, ...args);
    };
    console.debug = (...args) => {
      this.appendToConsole("DEBUG" /* DEBUG */, ...args);
    };
    if (typeof console.timeStamp !== "function") {
      console.timeStamp = () => {};
    }
  }
  setCollectCallerInfo(enabled) {
    this._collectCallerInfo = enabled;
  }
  clearConsole() {
    this._cachedLogs = [];
  }
  setCachingEnabled(enabled) {
    this._cachingEnabled = enabled;
  }
  deactivate() {
    this.restoreOriginalConsole();
  }
  restoreOriginalConsole() {
    if (this._originalConsole) {
      global.console = this._originalConsole;
    }
  }
  addLogEntry(level, ...args) {
    const callerInfo = this._collectCallerInfo ? getCallerInfo() : null;
    const logEntry = [new Date, level, args, callerInfo];
    if (this._cachingEnabled) {
      if (this._cachedLogs.length >= this.MAX_CACHE_SIZE) {
        this._cachedLogs.shift();
      }
      this._cachedLogs.push(logEntry);
    }
    return logEntry;
  }
  appendToConsole(level, ...args) {
    if (this._cachedLogs.length >= this.MAX_CACHE_SIZE) {
      this._cachedLogs.shift();
    }
    const entry = this.addLogEntry(level, ...args);
    this.emit("entry", entry);
  }
  destroy() {
    this.deactivate();
  }
}
var terminalConsoleCache = singleton("TerminalConsoleCache", () => {
  const terminalConsoleCache2 = new TerminalConsoleCache;
  process.on("exit", () => {
    terminalConsoleCache2.destroy();
  });
  return terminalConsoleCache2;
});
var ConsolePosition;
((ConsolePosition2) => {
  ConsolePosition2["TOP"] = "top";
  ConsolePosition2["BOTTOM"] = "bottom";
  ConsolePosition2["LEFT"] = "left";
  ConsolePosition2["RIGHT"] = "right";
})(ConsolePosition ||= {});
var defaultConsoleKeybindings = [
  { name: "up", action: "scroll-up" },
  { name: "down", action: "scroll-down" },
  { name: "up", shift: true, action: "scroll-to-top" },
  { name: "down", shift: true, action: "scroll-to-bottom" },
  { name: "p", ctrl: true, action: "position-previous" },
  { name: "o", ctrl: true, action: "position-next" },
  { name: "+", action: "size-increase" },
  { name: "=", shift: true, action: "size-increase" },
  { name: "-", action: "size-decrease" },
  { name: "s", ctrl: true, action: "save-logs" },
  { name: "c", ctrl: true, shift: true, action: "copy-selection" }
];
var DEFAULT_CONSOLE_OPTIONS = {
  position: "bottom" /* BOTTOM */,
  sizePercent: 30,
  zIndex: Infinity,
  colorInfo: "#00FFFF",
  colorWarn: "#FFFF00",
  colorError: "#FF0000",
  colorDebug: "#808080",
  colorDefault: "#FFFFFF",
  backgroundColor: RGBA.fromValues(0.1, 0.1, 0.1, 0.7),
  startInDebugMode: false,
  title: "Console",
  titleBarColor: RGBA.fromValues(0.05, 0.05, 0.05, 0.7),
  titleBarTextColor: "#FFFFFF",
  cursorColor: "#00A0FF",
  maxStoredLogs: 2000,
  maxDisplayLines: 3000,
  onCopySelection: undefined,
  keyBindings: undefined,
  keyAliasMap: undefined,
  selectionColor: RGBA.fromValues(0.3, 0.5, 0.8, 0.5),
  copyButtonColor: "#00A0FF"
};
var INDENT_WIDTH = 2;

class TerminalConsole extends EventEmitter4 {
  isVisible = false;
  isFocused = false;
  renderer;
  keyHandler;
  options;
  _debugModeEnabled = false;
  frameBuffer = null;
  consoleX = 0;
  consoleY = 0;
  consoleWidth = 0;
  consoleHeight = 0;
  scrollTopIndex = 0;
  isScrolledToBottom = true;
  currentLineIndex = 0;
  _displayLines = [];
  _allLogEntries = [];
  _needsFrameBufferUpdate = false;
  _entryListener;
  _selectionStart = null;
  _selectionEnd = null;
  _isDragging = false;
  _copyButtonBounds = {
    x: 0,
    y: 0,
    width: 0,
    height: 0
  };
  _autoScrollInterval = null;
  clock;
  _keyBindingsMap;
  _keyAliasMap;
  _keyBindings;
  _mergedKeyBindings;
  _actionHandlers;
  markNeedsRerender() {
    this._needsFrameBufferUpdate = true;
    this.renderer.requestRender();
  }
  getCopyButtonLabel() {
    const copyBindings = this._mergedKeyBindings.filter((b) => b.action === "copy-selection");
    const copyBinding = copyBindings[copyBindings.length - 1];
    if (copyBinding) {
      const shortcut = keyBindingToString(copyBinding);
      return `[Copy (${shortcut})]`;
    }
    return "[Copy]";
  }
  _rgbaInfo;
  _rgbaWarn;
  _rgbaError;
  _rgbaDebug;
  _rgbaDefault;
  backgroundColor;
  _rgbaTitleBar;
  _rgbaTitleBarText;
  _title;
  _rgbaCursor;
  _rgbaSelection;
  _rgbaCopyButton;
  _positions = [
    "top" /* TOP */,
    "right" /* RIGHT */,
    "bottom" /* BOTTOM */,
    "left" /* LEFT */
  ];
  constructor(renderer, options = {}) {
    super();
    this.renderer = renderer;
    this.clock = options.clock ?? new SystemClock;
    this.options = { ...DEFAULT_CONSOLE_OPTIONS, ...options };
    this.keyHandler = this.handleKeyPress.bind(this);
    this._debugModeEnabled = this.options.startInDebugMode;
    terminalConsoleCache.setCollectCallerInfo(this._debugModeEnabled);
    this._rgbaInfo = parseColor(this.options.colorInfo);
    this._rgbaWarn = parseColor(this.options.colorWarn);
    this._rgbaError = parseColor(this.options.colorError);
    this._rgbaDebug = parseColor(this.options.colorDebug);
    this._rgbaDefault = parseColor(this.options.colorDefault);
    this.backgroundColor = parseColor(this.options.backgroundColor);
    this._rgbaTitleBar = parseColor(this.options.titleBarColor);
    this._rgbaTitleBarText = parseColor(this.options.titleBarTextColor || this.options.colorDefault);
    this._title = this.options.title;
    this._rgbaCursor = parseColor(this.options.cursorColor);
    this._rgbaSelection = parseColor(this.options.selectionColor);
    this._rgbaCopyButton = parseColor(this.options.copyButtonColor);
    this._keyAliasMap = mergeKeyAliases(defaultKeyAliases, options.keyAliasMap || {});
    this._keyBindings = options.keyBindings || [];
    this._mergedKeyBindings = mergeKeyBindings(defaultConsoleKeybindings, this._keyBindings);
    this._keyBindingsMap = buildKeyBindingsMap(this._mergedKeyBindings, this._keyAliasMap);
    this._actionHandlers = this.buildActionHandlers();
    this._updateConsoleDimensions();
    this._scrollToBottom(true);
    this._entryListener = (logEntry) => {
      this._handleNewLog(logEntry);
    };
    terminalConsoleCache.on("entry", this._entryListener);
    if (env.SHOW_CONSOLE) {
      this.show();
    }
  }
  buildActionHandlers() {
    return new Map([
      ["scroll-up", () => this.scrollUp()],
      ["scroll-down", () => this.scrollDown()],
      ["scroll-to-top", () => this.scrollToTop()],
      ["scroll-to-bottom", () => this.scrollToBottomAction()],
      ["position-previous", () => this.positionPrevious()],
      ["position-next", () => this.positionNext()],
      ["size-increase", () => this.sizeIncrease()],
      ["size-decrease", () => this.sizeDecrease()],
      ["save-logs", () => this.saveLogsAction()],
      ["copy-selection", () => this.triggerCopyAction()]
    ]);
  }
  activate() {
    terminalConsoleCache.activate();
  }
  deactivate() {
    terminalConsoleCache.deactivate();
  }
  _handleNewLog(logEntry) {
    if (!this.isVisible)
      return;
    this._allLogEntries.push(logEntry);
    if (this._allLogEntries.length > this.options.maxStoredLogs) {
      this._allLogEntries.splice(0, this._allLogEntries.length - this.options.maxStoredLogs);
    }
    const newDisplayLines = this._processLogEntry(logEntry);
    this._displayLines.push(...newDisplayLines);
    if (this._displayLines.length > this.options.maxDisplayLines) {
      this._displayLines.splice(0, this._displayLines.length - this.options.maxDisplayLines);
      const linesRemoved = this._displayLines.length - this.options.maxDisplayLines;
      this.scrollTopIndex = Math.max(0, this.scrollTopIndex - linesRemoved);
    }
    if (this.isScrolledToBottom) {
      this._scrollToBottom();
    }
    this.markNeedsRerender();
  }
  _updateConsoleDimensions(termWidth, termHeight) {
    const width = termWidth ?? this.renderer.width;
    const height = termHeight ?? this.renderer.height;
    const sizePercent = this.options.sizePercent / 100;
    switch (this.options.position) {
      case "top" /* TOP */:
        this.consoleX = 0;
        this.consoleY = 0;
        this.consoleWidth = width;
        this.consoleHeight = Math.max(1, Math.floor(height * sizePercent));
        break;
      case "bottom" /* BOTTOM */:
        this.consoleHeight = Math.max(1, Math.floor(height * sizePercent));
        this.consoleWidth = width;
        this.consoleX = 0;
        this.consoleY = height - this.consoleHeight;
        break;
      case "left" /* LEFT */:
        this.consoleWidth = Math.max(1, Math.floor(width * sizePercent));
        this.consoleHeight = height;
        this.consoleX = 0;
        this.consoleY = 0;
        break;
      case "right" /* RIGHT */:
        this.consoleWidth = Math.max(1, Math.floor(width * sizePercent));
        this.consoleHeight = height;
        this.consoleY = 0;
        this.consoleX = width - this.consoleWidth;
        break;
    }
    this.currentLineIndex = Math.max(0, Math.min(this.currentLineIndex, this.consoleHeight - 1));
  }
  handleKeyPress(event) {
    if (event.name === "escape") {
      this.blur();
      return;
    }
    const action = getKeyBindingAction(this._keyBindingsMap, event);
    if (action) {
      const handler = this._actionHandlers.get(action);
      if (handler) {
        handler();
        return;
      }
    }
  }
  scrollUp() {
    const logAreaHeight = Math.max(1, this.consoleHeight - 1);
    if (this.currentLineIndex > 0) {
      this.currentLineIndex--;
      this.markNeedsRerender();
    } else if (this.scrollTopIndex > 0) {
      this.scrollTopIndex--;
      this.isScrolledToBottom = false;
      this.markNeedsRerender();
    }
    return true;
  }
  scrollDown() {
    const displayLineCount = this._displayLines.length;
    const logAreaHeight = Math.max(1, this.consoleHeight - 1);
    const maxScrollTop = Math.max(0, displayLineCount - logAreaHeight);
    const canCursorMoveDown = this.currentLineIndex < logAreaHeight - 1 && this.scrollTopIndex + this.currentLineIndex < displayLineCount - 1;
    if (canCursorMoveDown) {
      this.currentLineIndex++;
      this.markNeedsRerender();
    } else if (this.scrollTopIndex < maxScrollTop) {
      this.scrollTopIndex++;
      this.isScrolledToBottom = this.scrollTopIndex === maxScrollTop;
      this.markNeedsRerender();
    }
    return true;
  }
  scrollToTop() {
    if (this.scrollTopIndex > 0 || this.currentLineIndex > 0) {
      this.scrollTopIndex = 0;
      this.currentLineIndex = 0;
      this.isScrolledToBottom = this._displayLines.length <= Math.max(1, this.consoleHeight - 1);
      this.markNeedsRerender();
    }
    return true;
  }
  scrollToBottomAction() {
    const logAreaHeightForScroll = Math.max(1, this.consoleHeight - 1);
    const maxScrollPossible = Math.max(0, this._displayLines.length - logAreaHeightForScroll);
    if (this.scrollTopIndex < maxScrollPossible || !this.isScrolledToBottom) {
      this._scrollToBottom(true);
      this.markNeedsRerender();
    }
    return true;
  }
  positionPrevious() {
    const currentPositionIndex = this._positions.indexOf(this.options.position);
    const prevIndex = (currentPositionIndex - 1 + this._positions.length) % this._positions.length;
    this.options.position = this._positions[prevIndex];
    this.resize(this.renderer.width, this.renderer.height);
    return true;
  }
  positionNext() {
    const currentPositionIndex = this._positions.indexOf(this.options.position);
    const nextIndex = (currentPositionIndex + 1) % this._positions.length;
    this.options.position = this._positions[nextIndex];
    this.resize(this.renderer.width, this.renderer.height);
    return true;
  }
  sizeIncrease() {
    this.options.sizePercent = Math.min(100, this.options.sizePercent + 5);
    this.resize(this.renderer.width, this.renderer.height);
    return true;
  }
  sizeDecrease() {
    this.options.sizePercent = Math.max(10, this.options.sizePercent - 5);
    this.resize(this.renderer.width, this.renderer.height);
    return true;
  }
  saveLogsAction() {
    this.saveLogsToFile();
    return true;
  }
  triggerCopyAction() {
    this.triggerCopy();
    return true;
  }
  attachStdin() {
    if (this.isFocused)
      return;
    this.renderer.keyInput.on("keypress", this.keyHandler);
    this.isFocused = true;
  }
  detachStdin() {
    if (!this.isFocused)
      return;
    this.renderer.keyInput.off("keypress", this.keyHandler);
    this.isFocused = false;
  }
  formatTimestamp(date) {
    return new Intl.DateTimeFormat("en-US", {
      hour: "2-digit",
      minute: "2-digit",
      second: "2-digit",
      hour12: false
    }).format(date);
  }
  formatArguments(args) {
    return args.map((arg) => {
      if (arg instanceof Error) {
        const errorProps = arg;
        return `Error: ${errorProps.message}
` + (errorProps.stack ? `${errorProps.stack}
` : "");
      }
      if (typeof arg === "object" && arg !== null) {
        try {
          return util2.inspect(arg, { depth: 2 });
        } catch (e) {
          return String(arg);
        }
      }
      try {
        return util2.inspect(arg, { depth: 2 });
      } catch (e) {
        return String(arg);
      }
    }).join(" ");
  }
  resize(width, height) {
    this._updateConsoleDimensions(width, height);
    if (this.frameBuffer) {
      this.frameBuffer.resize(this.consoleWidth, this.consoleHeight);
      const displayLineCount = this._displayLines.length;
      const logAreaHeight = Math.max(1, this.consoleHeight - 1);
      const maxScrollTop = Math.max(0, displayLineCount - logAreaHeight);
      this.scrollTopIndex = Math.min(this.scrollTopIndex, maxScrollTop);
      this.isScrolledToBottom = this.scrollTopIndex === maxScrollTop;
      const visibleLineCount = Math.min(logAreaHeight, displayLineCount - this.scrollTopIndex);
      this.currentLineIndex = Math.max(0, Math.min(this.currentLineIndex, visibleLineCount - 1));
      if (this.isVisible) {
        this.markNeedsRerender();
      }
    }
  }
  clear() {
    terminalConsoleCache.clearConsole();
    this._allLogEntries = [];
    this._displayLines = [];
    this.markNeedsRerender();
  }
  toggle() {
    if (this.isVisible) {
      if (this.isFocused) {
        this.hide();
      } else {
        this.focus();
      }
    } else {
      this.show();
    }
    if (!this.renderer.isRunning) {
      this.renderer.requestRender();
    }
  }
  focus() {
    this.attachStdin();
    this._scrollToBottom(true);
    this.markNeedsRerender();
  }
  blur() {
    this.detachStdin();
    this.markNeedsRerender();
  }
  show() {
    if (!this.isVisible) {
      this.isVisible = true;
      this._processCachedLogs();
      terminalConsoleCache.setCachingEnabled(false);
      if (!this.frameBuffer) {
        this.frameBuffer = OptimizedBuffer.create(this.consoleWidth, this.consoleHeight, this.renderer.widthMethod, {
          respectAlpha: this.backgroundColor.a < 1,
          id: "console framebuffer"
        });
      }
      const logCount = terminalConsoleCache.cachedLogs.length;
      const visibleLogLines = Math.min(this.consoleHeight, logCount);
      this.currentLineIndex = Math.max(0, visibleLogLines - 1);
      this.scrollTopIndex = 0;
      this._scrollToBottom(true);
      this.focus();
      this.markNeedsRerender();
    }
  }
  hide() {
    if (this.isVisible) {
      this.stopAutoScroll();
      this.isVisible = false;
      this.blur();
      terminalConsoleCache.setCachingEnabled(true);
    }
  }
  destroy() {
    this.stopAutoScroll();
    this.hide();
    this.deactivate();
    terminalConsoleCache.off("entry", this._entryListener);
  }
  getCachedLogs() {
    return terminalConsoleCache.cachedLogs.map((logEntry) => logEntry[0].toISOString() + " " + logEntry.slice(1).join(" ")).join(`
`);
  }
  updateFrameBuffer() {
    if (!this.frameBuffer)
      return;
    this.frameBuffer.clear(this.backgroundColor);
    const displayLines = this._displayLines;
    const displayLineCount = displayLines.length;
    const logAreaHeight = Math.max(1, this.consoleHeight - 1);
    this.frameBuffer.fillRect(0, 0, this.consoleWidth, 1, this._rgbaTitleBar);
    const dynamicTitle = `${this._title}${this.isFocused ? " (Focused)" : ""}`;
    const titleX = Math.max(0, Math.floor((this.consoleWidth - dynamicTitle.length) / 2));
    this.frameBuffer.drawText(dynamicTitle, titleX, 0, this._rgbaTitleBarText, this._rgbaTitleBar);
    const copyLabel = this.getCopyButtonLabel();
    const copyButtonX = this.consoleWidth - copyLabel.length - 1;
    if (copyButtonX >= 0) {
      const copyButtonEnabled = this.hasSelection();
      const disabledColor = RGBA.fromInts(100, 100, 100, 255);
      const copyColor = copyButtonEnabled ? this._rgbaCopyButton : disabledColor;
      this.frameBuffer.drawText(copyLabel, copyButtonX, 0, copyColor, this._rgbaTitleBar);
      this._copyButtonBounds = { x: copyButtonX, y: 0, width: copyLabel.length, height: 1 };
    } else {
      this._copyButtonBounds = { x: -1, y: -1, width: 0, height: 0 };
    }
    const startIndex = this.scrollTopIndex;
    const endIndex = Math.min(startIndex + logAreaHeight, displayLineCount);
    const visibleDisplayLines = displayLines.slice(startIndex, endIndex);
    let lineY = 1;
    for (let i = 0;i < visibleDisplayLines.length; i++) {
      if (lineY >= this.consoleHeight)
        break;
      const displayLine = visibleDisplayLines[i];
      const absoluteLineIndex = startIndex + i;
      let levelColor = this._rgbaDefault;
      switch (displayLine.level) {
        case "INFO" /* INFO */:
          levelColor = this._rgbaInfo;
          break;
        case "WARN" /* WARN */:
          levelColor = this._rgbaWarn;
          break;
        case "ERROR" /* ERROR */:
          levelColor = this._rgbaError;
          break;
        case "DEBUG" /* DEBUG */:
          levelColor = this._rgbaDebug;
          break;
      }
      const linePrefix = displayLine.indent ? " ".repeat(INDENT_WIDTH) : "";
      const textToDraw = displayLine.text;
      const textAvailableWidth = this.consoleWidth - 1 - (displayLine.indent ? INDENT_WIDTH : 0);
      const showCursor = this.isFocused && lineY - 1 === this.currentLineIndex;
      if (showCursor) {
        this.frameBuffer.drawText(">", 0, lineY, this._rgbaCursor, this.backgroundColor);
      } else {
        this.frameBuffer.drawText(" ", 0, lineY, this._rgbaDefault, this.backgroundColor);
      }
      const fullText = `${linePrefix}${textToDraw.substring(0, textAvailableWidth)}`;
      const selectionRange = this.getLineSelectionRange(absoluteLineIndex);
      if (selectionRange) {
        const adjustedStart = Math.max(0, selectionRange.start);
        const adjustedEnd = Math.min(fullText.length, selectionRange.end);
        if (adjustedStart > 0) {
          this.frameBuffer.drawText(fullText.substring(0, adjustedStart), 1, lineY, levelColor);
        }
        if (adjustedStart < adjustedEnd) {
          this.frameBuffer.fillRect(1 + adjustedStart, lineY, adjustedEnd - adjustedStart, 1, this._rgbaSelection);
          this.frameBuffer.drawText(fullText.substring(adjustedStart, adjustedEnd), 1 + adjustedStart, lineY, levelColor, this._rgbaSelection);
        }
        if (adjustedEnd < fullText.length) {
          this.frameBuffer.drawText(fullText.substring(adjustedEnd), 1 + adjustedEnd, lineY, levelColor);
        }
      } else {
        this.frameBuffer.drawText(fullText, 1, lineY, levelColor);
      }
      lineY++;
    }
  }
  renderToBuffer(buffer) {
    if (!this.isVisible || !this.frameBuffer)
      return;
    if (this._needsFrameBufferUpdate) {
      this.updateFrameBuffer();
      this._needsFrameBufferUpdate = false;
    }
    buffer.drawFrameBuffer(this.consoleX, this.consoleY, this.frameBuffer);
  }
  setDebugMode(enabled) {
    this._debugModeEnabled = enabled;
    terminalConsoleCache.setCollectCallerInfo(enabled);
    if (this.isVisible) {
      this.markNeedsRerender();
    }
  }
  toggleDebugMode() {
    this.setDebugMode(!this._debugModeEnabled);
  }
  set keyBindings(bindings) {
    this._keyBindings = bindings;
    this._mergedKeyBindings = mergeKeyBindings(defaultConsoleKeybindings, bindings);
    this._keyBindingsMap = buildKeyBindingsMap(this._mergedKeyBindings, this._keyAliasMap);
    this.markNeedsRerender();
  }
  set keyAliasMap(aliases) {
    this._keyAliasMap = mergeKeyAliases(defaultKeyAliases, aliases);
    this._mergedKeyBindings = mergeKeyBindings(defaultConsoleKeybindings, this._keyBindings);
    this._keyBindingsMap = buildKeyBindingsMap(this._mergedKeyBindings, this._keyAliasMap);
    this.markNeedsRerender();
  }
  set onCopySelection(callback) {
    this.options.onCopySelection = callback;
  }
  get onCopySelection() {
    return this.options.onCopySelection;
  }
  _scrollToBottom(forceCursorToLastLine = false) {
    const displayLineCount = this._displayLines.length;
    const logAreaHeight = Math.max(1, this.consoleHeight - 1);
    const maxScrollTop = Math.max(0, displayLineCount - logAreaHeight);
    this.scrollTopIndex = maxScrollTop;
    this.isScrolledToBottom = true;
    const visibleLineCount = Math.min(logAreaHeight, displayLineCount - this.scrollTopIndex);
    if (forceCursorToLastLine || this.currentLineIndex >= visibleLineCount) {
      this.currentLineIndex = Math.max(0, visibleLineCount - 1);
    }
  }
  _processLogEntry(logEntry) {
    const [date, level, args, callerInfo] = logEntry;
    const displayLines = [];
    const timestamp = this.formatTimestamp(date);
    const callerSource = callerInfo ? `${callerInfo.fileName}:${callerInfo.lineNumber}` : "unknown";
    const prefix = `[${timestamp}] [${level}]` + (this._debugModeEnabled ? ` [${callerSource}]` : "") + " ";
    const formattedArgs = this.formatArguments(args);
    const initialLines = formattedArgs.split(`
`);
    for (let i = 0;i < initialLines.length; i++) {
      const lineText = initialLines[i];
      const isFirstLineOfEntry = i === 0;
      const availableWidth = this.consoleWidth - 1 - (isFirstLineOfEntry ? 0 : INDENT_WIDTH);
      const linePrefix = isFirstLineOfEntry ? prefix : " ".repeat(INDENT_WIDTH);
      const textToWrap = isFirstLineOfEntry ? linePrefix + lineText : lineText;
      let currentPos = 0;
      while (currentPos < textToWrap.length || isFirstLineOfEntry && currentPos === 0 && textToWrap.length === 0) {
        const segment = textToWrap.substring(currentPos, currentPos + availableWidth);
        const isFirstSegmentOfLine = currentPos === 0;
        displayLines.push({
          text: isFirstSegmentOfLine && !isFirstLineOfEntry ? linePrefix + segment : segment,
          level,
          indent: !isFirstLineOfEntry || !isFirstSegmentOfLine
        });
        currentPos += availableWidth;
        if (isFirstLineOfEntry && currentPos === 0 && textToWrap.length === 0)
          break;
      }
    }
    return displayLines;
  }
  _processCachedLogs() {
    const logsToProcess = [...terminalConsoleCache.cachedLogs];
    terminalConsoleCache.clearConsole();
    this._allLogEntries.push(...logsToProcess);
    if (this._allLogEntries.length > this.options.maxStoredLogs) {
      this._allLogEntries.splice(0, this._allLogEntries.length - this.options.maxStoredLogs);
    }
    for (const logEntry of logsToProcess) {
      const processed = this._processLogEntry(logEntry);
      this._displayLines.push(...processed);
    }
    if (this._displayLines.length > this.options.maxDisplayLines) {
      this._displayLines.splice(0, this._displayLines.length - this.options.maxDisplayLines);
    }
  }
  hasSelection() {
    if (this._selectionStart === null || this._selectionEnd === null)
      return false;
    return this._selectionStart.line !== this._selectionEnd.line || this._selectionStart.col !== this._selectionEnd.col;
  }
  normalizeSelection() {
    if (!this._selectionStart || !this._selectionEnd)
      return null;
    const start = this._selectionStart;
    const end = this._selectionEnd;
    const startBeforeEnd = start.line < end.line || start.line === end.line && start.col <= end.col;
    if (startBeforeEnd) {
      return {
        startLine: start.line,
        startCol: start.col,
        endLine: end.line,
        endCol: end.col
      };
    } else {
      return {
        startLine: end.line,
        startCol: end.col,
        endLine: start.line,
        endCol: start.col
      };
    }
  }
  getSelectedText() {
    const selection = this.normalizeSelection();
    if (!selection)
      return "";
    const lines = [];
    for (let i = selection.startLine;i <= selection.endLine; i++) {
      if (i < 0 || i >= this._displayLines.length)
        continue;
      const line = this._displayLines[i];
      const linePrefix = line.indent ? " ".repeat(INDENT_WIDTH) : "";
      const textAvailableWidth = this.consoleWidth - 1 - (line.indent ? INDENT_WIDTH : 0);
      const fullText = linePrefix + line.text.substring(0, textAvailableWidth);
      let text = fullText;
      if (i === selection.startLine && i === selection.endLine) {
        text = fullText.substring(selection.startCol, selection.endCol);
      } else if (i === selection.startLine) {
        text = fullText.substring(selection.startCol);
      } else if (i === selection.endLine) {
        text = fullText.substring(0, selection.endCol);
      }
      lines.push(text);
    }
    return lines.join(`
`);
  }
  clearSelection() {
    this._selectionStart = null;
    this._selectionEnd = null;
    this._isDragging = false;
    this.stopAutoScroll();
  }
  stopAutoScroll() {
    if (this._autoScrollInterval !== null) {
      this.clock.clearInterval(this._autoScrollInterval);
      this._autoScrollInterval = null;
    }
  }
  startAutoScroll(direction) {
    this.stopAutoScroll();
    this._autoScrollInterval = this.clock.setInterval(() => {
      if (direction === "up") {
        if (this.scrollTopIndex > 0) {
          this.scrollTopIndex--;
          this.isScrolledToBottom = false;
          if (this._selectionEnd) {
            this._selectionEnd = {
              line: this.scrollTopIndex,
              col: this._selectionEnd.col
            };
          }
          this.markNeedsRerender();
        } else {
          this.stopAutoScroll();
        }
      } else {
        const displayLineCount = this._displayLines.length;
        const logAreaHeight = Math.max(1, this.consoleHeight - 1);
        const maxScrollTop = Math.max(0, displayLineCount - logAreaHeight);
        if (this.scrollTopIndex < maxScrollTop) {
          this.scrollTopIndex++;
          this.isScrolledToBottom = this.scrollTopIndex === maxScrollTop;
          if (this._selectionEnd) {
            const maxLine = this.scrollTopIndex + logAreaHeight - 1;
            this._selectionEnd = {
              line: Math.min(maxLine, displayLineCount - 1),
              col: this._selectionEnd.col
            };
          }
          this.markNeedsRerender();
        } else {
          this.stopAutoScroll();
        }
      }
    }, 50);
  }
  triggerCopy() {
    if (!this.hasSelection())
      return;
    const text = this.getSelectedText();
    if (text && this.options.onCopySelection) {
      try {
        this.options.onCopySelection(text);
      } catch {}
      this.clearSelection();
      this.markNeedsRerender();
    }
  }
  getLineSelectionRange(lineIndex) {
    const selection = this.normalizeSelection();
    if (!selection)
      return null;
    if (lineIndex < selection.startLine || lineIndex > selection.endLine) {
      return null;
    }
    const line = this._displayLines[lineIndex];
    if (!line)
      return null;
    const linePrefix = line.indent ? " ".repeat(INDENT_WIDTH) : "";
    const textAvailableWidth = this.consoleWidth - 1 - (line.indent ? INDENT_WIDTH : 0);
    const fullTextLength = linePrefix.length + Math.min(line.text.length, textAvailableWidth);
    let start = 0;
    let end = fullTextLength;
    if (lineIndex === selection.startLine) {
      start = Math.max(0, selection.startCol);
    }
    if (lineIndex === selection.endLine) {
      end = Math.min(fullTextLength, selection.endCol);
    }
    if (start >= end)
      return null;
    return { start, end };
  }
  handleMouse(event) {
    if (!this.isVisible)
      return false;
    const localX = event.x - this.consoleX;
    const localY = event.y - this.consoleY;
    if (localX < 0 || localX >= this.consoleWidth || localY < 0 || localY >= this.consoleHeight) {
      return false;
    }
    if (event.type === "scroll" && event.scroll) {
      if (event.scroll.direction === "up") {
        this.scrollUp();
      } else if (event.scroll.direction === "down") {
        this.scrollDown();
      }
      return true;
    }
    if (localY === 0) {
      if (event.type === "down" && event.button === 0 && localX >= this._copyButtonBounds.x && localX < this._copyButtonBounds.x + this._copyButtonBounds.width) {
        this.triggerCopy();
        return true;
      }
      return true;
    }
    const lineIndex = this.scrollTopIndex + (localY - 1);
    const colIndex = Math.max(0, localX - 1);
    if (event.type === "down" && event.button === 0) {
      this.clearSelection();
      this._selectionStart = { line: lineIndex, col: colIndex };
      this._selectionEnd = { line: lineIndex, col: colIndex };
      this._isDragging = true;
      this.markNeedsRerender();
      return true;
    }
    if (event.type === "drag" && this._isDragging) {
      this._selectionEnd = { line: lineIndex, col: colIndex };
      const logAreaHeight = Math.max(1, this.consoleHeight - 1);
      const relativeY = localY - 1;
      if (relativeY <= 0) {
        this.startAutoScroll("up");
      } else if (relativeY >= logAreaHeight - 1) {
        this.startAutoScroll("down");
      } else {
        this.stopAutoScroll();
      }
      this.markNeedsRerender();
      return true;
    }
    if (event.type === "up") {
      if (this._isDragging) {
        this._selectionEnd = { line: lineIndex, col: colIndex };
        this._isDragging = false;
        this.stopAutoScroll();
        this.markNeedsRerender();
      }
      return true;
    }
    return true;
  }
  get visible() {
    return this.isVisible;
  }
  get bounds() {
    return {
      x: this.consoleX,
      y: this.consoleY,
      width: this.consoleWidth,
      height: this.consoleHeight
    };
  }
  saveLogsToFile() {
    try {
      const timestamp = Date.now();
      const filename = `_console_${timestamp}.log`;
      const filepath = path.join(process.cwd(), filename);
      const allLogEntries = [...this._allLogEntries, ...terminalConsoleCache.cachedLogs];
      const logLines = [];
      for (const [date, level, args, callerInfo] of allLogEntries) {
        const timestampStr = this.formatTimestamp(date);
        const callerSource = callerInfo ? `${callerInfo.fileName}:${callerInfo.lineNumber}` : "unknown";
        const prefix = `[${timestampStr}] [${level}]` + (this._debugModeEnabled ? ` [${callerSource}]` : "") + " ";
        const formattedArgs = this.formatArguments(args);
        logLines.push(prefix + formattedArgs);
      }
      const content = logLines.join(`
`);
      fs.writeFileSync(filepath, content, "utf8");
      console.info(`Console logs saved to: ${filename}`);
    } catch (error) {
      console.error(`Failed to save console logs:`, error);
    }
  }
}

// src/renderables/EditBufferRenderable.ts
var BrandedEditBufferRenderable = Symbol.for("@opentui/core/EditBufferRenderable");
var EditBufferRenderableEvents;
((EditBufferRenderableEvents2) => {
  EditBufferRenderableEvents2["TRAITS_CHANGED"] = "traits-changed";
})(EditBufferRenderableEvents ||= {});
function sameCapture(a, b) {
  if (a === b)
    return true;
  if (!a || !b)
    return !a && !b;
  if (a.length !== b.length)
    return false;
  return a.every((item, i) => item === b[i]);
}
function sameTraits(a, b) {
  return a.suspend === b.suspend && a.status === b.status && sameCapture(a.capture, b.capture);
}
function isEditBufferRenderable(obj) {
  return !!(obj && typeof obj === "object" && (BrandedEditBufferRenderable in obj));
}

class EditBufferRenderable extends Renderable {
  [BrandedEditBufferRenderable] = true;
  _focusable = true;
  selectable = true;
  _traits = {};
  _textColor;
  _backgroundColor;
  _defaultAttributes;
  _selectionBg;
  _selectionFg;
  _wrapMode = "word";
  _scrollMargin = 0.2;
  _showCursor = true;
  _cursorColor;
  _cursorStyle;
  lastLocalSelection = null;
  _tabIndicator;
  _tabIndicatorColor;
  _cursorChangeListener = undefined;
  _contentChangeListener = undefined;
  _autoScrollVelocity = 0;
  _autoScrollAccumulator = 0;
  _scrollSpeed = 16;
  _keyboardSelectionActive = false;
  editBuffer;
  editorView;
  nativeRenderable = null;
  _defaultOptions = {
    textColor: RGBA.fromValues(1, 1, 1, 1),
    backgroundColor: "transparent",
    selectionBg: undefined,
    selectionFg: undefined,
    selectable: true,
    attributes: 0,
    wrapMode: "word",
    scrollMargin: 0.2,
    scrollSpeed: 16,
    showCursor: true,
    cursorColor: RGBA.fromValues(1, 1, 1, 1),
    cursorStyle: {
      style: "block",
      blinking: true
    },
    tabIndicator: undefined,
    tabIndicatorColor: undefined
  };
  constructor(ctx, options) {
    super(ctx, options);
    this._textColor = parseColor(options.textColor ?? this._defaultOptions.textColor);
    this._backgroundColor = parseColor(options.backgroundColor ?? this._defaultOptions.backgroundColor);
    this._defaultAttributes = options.attributes ?? this._defaultOptions.attributes;
    this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) : this._defaultOptions.selectionBg;
    this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : this._defaultOptions.selectionFg;
    this.selectable = options.selectable ?? this._defaultOptions.selectable;
    this._wrapMode = options.wrapMode ?? this._defaultOptions.wrapMode;
    this._scrollMargin = options.scrollMargin ?? this._defaultOptions.scrollMargin;
    this._scrollSpeed = options.scrollSpeed ?? this._defaultOptions.scrollSpeed;
    this._showCursor = options.showCursor ?? this._defaultOptions.showCursor;
    this._cursorColor = parseColor(options.cursorColor ?? this._defaultOptions.cursorColor);
    this._cursorStyle = options.cursorStyle ?? this._defaultOptions.cursorStyle;
    this._tabIndicator = options.tabIndicator ?? this._defaultOptions.tabIndicator;
    this._tabIndicatorColor = options.tabIndicatorColor ? parseColor(options.tabIndicatorColor) : this._defaultOptions.tabIndicatorColor;
    this.editBuffer = EditBuffer.create(this._ctx.widthMethod);
    this.editorView = EditorView.create(this.editBuffer, this.width || 80, this.height || 24);
    this.editorView.setWrapMode(this._wrapMode);
    this.editorView.setScrollMargin(this._scrollMargin);
    if (options.selectionOccupancy === "boundary") {
      this.editorView.setSelectionOccupancy("boundary");
    }
    this.editBuffer.setDefaultFg(this._textColor);
    this.editBuffer.setDefaultBg(this._backgroundColor);
    this.editBuffer.setDefaultAttributes(this._defaultAttributes);
    if (options.syntaxStyle) {
      this.editBuffer.setSyntaxStyle(options.syntaxStyle);
    }
    if (this._tabIndicator !== undefined) {
      this.editorView.setTabIndicator(this._tabIndicator);
    }
    if (this._tabIndicatorColor !== undefined) {
      this.editorView.setTabIndicatorColor(this._tabIndicatorColor);
    }
    this.setupNativeRenderable();
    this.setupEventListeners(options);
  }
  get lineInfo() {
    return this.editorView.getLogicalLineInfo();
  }
  setupEventListeners(options) {
    this._cursorChangeListener = options.onCursorChange;
    this._contentChangeListener = options.onContentChange;
    this.editBuffer.on("cursor-changed", () => {
      if (this._cursorChangeListener) {
        const cursor = this.editBuffer.getCursorPosition();
        this._cursorChangeListener({
          line: cursor.row,
          visualColumn: cursor.col
        });
      }
    });
    this.editBuffer.on("content-changed", () => {
      this.yogaNode.markDirty();
      this.requestRender();
      this.emit("line-info-change");
      if (this._contentChangeListener) {
        this._contentChangeListener({});
      }
    });
  }
  get lineCount() {
    return this.editBuffer.getLineCount();
  }
  get virtualLineCount() {
    return this.editorView.getVirtualLineCount();
  }
  get scrollY() {
    return this.editorView.getViewport().offsetY;
  }
  get plainText() {
    return this.editBuffer.getText();
  }
  get logicalCursor() {
    return this.editBuffer.getCursorPosition();
  }
  get visualCursor() {
    return this.editorView.getVisualCursor();
  }
  get cursorOffset() {
    return this.editorView.getVisualCursor().offset;
  }
  set cursorOffset(offset) {
    this.clearSelection();
    this.editorView.setCursorByOffset(offset);
    this.requestRender();
  }
  get cursorCharacterOffset() {
    const len = this.plainText.length;
    if (len <= 0)
      return;
    const cursor = this.logicalCursor;
    const offset = this.cursorOffset;
    if (offset >= len) {
      if (cursor.col > 0)
        return len - 1;
      return 0;
    }
    if (this.plainText[offset] === `
` && cursor.col > 0) {
      return offset - 1;
    }
    return offset;
  }
  get textColor() {
    return this._textColor;
  }
  set textColor(value) {
    const newColor = parseColor(value ?? this._defaultOptions.textColor);
    if (this._textColor !== newColor) {
      this._textColor = newColor;
      this.editBuffer.setDefaultFg(newColor);
      this.requestRender();
    }
  }
  get selectionBg() {
    return this._selectionBg;
  }
  get traits() {
    return this._traits;
  }
  set traits(value) {
    if (sameTraits(this._traits, value))
      return;
    const prev = this._traits;
    this._traits = value;
    this.emit("traits-changed" /* TRAITS_CHANGED */, value, prev);
  }
  set selectionBg(value) {
    const newColor = value ? parseColor(value) : this._defaultOptions.selectionBg;
    if (this._selectionBg !== newColor) {
      this._selectionBg = newColor;
      this.refreshSelectionStyle();
      this.requestRender();
    }
  }
  get selectionFg() {
    return this._selectionFg;
  }
  set selectionFg(value) {
    const newColor = value ? parseColor(value) : this._defaultOptions.selectionFg;
    if (this._selectionFg !== newColor) {
      this._selectionFg = newColor;
      this.refreshSelectionStyle();
      this.requestRender();
    }
  }
  get backgroundColor() {
    return this._backgroundColor;
  }
  set backgroundColor(value) {
    const newColor = parseColor(value ?? this._defaultOptions.backgroundColor);
    if (this._backgroundColor !== newColor) {
      this._backgroundColor = newColor;
      this.editBuffer.setDefaultBg(newColor);
      this.requestRender();
    }
  }
  get attributes() {
    return this._defaultAttributes;
  }
  set attributes(value) {
    if (this._defaultAttributes !== value) {
      this._defaultAttributes = value;
      this.editBuffer.setDefaultAttributes(value);
      this.requestRender();
    }
  }
  get wrapMode() {
    return this._wrapMode;
  }
  set wrapMode(value) {
    if (this._wrapMode !== value) {
      this._wrapMode = value;
      this.editorView.setWrapMode(value);
      this.yogaNode.markDirty();
      this.requestRender();
    }
  }
  get showCursor() {
    return this._showCursor;
  }
  set showCursor(value) {
    if (this._showCursor !== value) {
      this._showCursor = value;
      if (!value && this._focused) {
        this._ctx.setCursorPosition(0, 0, false);
      }
      this.requestRender();
    }
  }
  get cursorColor() {
    return this._cursorColor;
  }
  set cursorColor(value) {
    const newColor = parseColor(value);
    if (this._cursorColor !== newColor) {
      this._cursorColor = newColor;
      if (this._focused) {
        this.requestRender();
      }
    }
  }
  get cursorStyle() {
    return this._cursorStyle;
  }
  set cursorStyle(style) {
    const newStyle = style;
    if (this.cursorStyle.style !== newStyle.style || this.cursorStyle.blinking !== newStyle.blinking) {
      this._cursorStyle = newStyle;
      if (this._focused) {
        this.requestRender();
      }
    }
  }
  get selectionOccupancy() {
    return this.editorView.getSelectionOccupancy();
  }
  set selectionOccupancy(value) {
    const occupancy = value ?? "cell";
    if (this.selectionOccupancy === occupancy)
      return;
    this.editorView.setSelectionOccupancy(occupancy);
    this.requestRender();
  }
  get tabIndicator() {
    return this._tabIndicator;
  }
  set tabIndicator(value) {
    if (this._tabIndicator !== value) {
      this._tabIndicator = value;
      if (value !== undefined) {
        this.editorView.setTabIndicator(value);
      }
      this.requestRender();
    }
  }
  get tabIndicatorColor() {
    return this._tabIndicatorColor;
  }
  set tabIndicatorColor(value) {
    const newColor = value ? parseColor(value) : undefined;
    if (this._tabIndicatorColor !== newColor) {
      this._tabIndicatorColor = newColor;
      if (newColor !== undefined) {
        this.editorView.setTabIndicatorColor(newColor);
      }
      this.requestRender();
    }
  }
  get scrollSpeed() {
    return this._scrollSpeed;
  }
  set scrollSpeed(value) {
    this._scrollSpeed = Math.max(0, value);
  }
  onMouseEvent(event) {
    if (event.type === "scroll") {
      this.handleScroll(event);
    }
  }
  handleScroll(event) {
    if (!event.scroll)
      return;
    const { direction, delta } = event.scroll;
    const viewport = this.editorView.getViewport();
    if (direction === "up") {
      const newOffsetY = Math.max(0, viewport.offsetY - delta);
      this.editorView.setViewport(viewport.offsetX, newOffsetY, viewport.width, viewport.height, true);
      this.requestRender();
    } else if (direction === "down") {
      const totalVirtualLines = this.editorView.getTotalVirtualLineCount();
      const maxOffsetY = Math.max(0, totalVirtualLines - viewport.height);
      const newOffsetY = Math.min(viewport.offsetY + delta, maxOffsetY);
      this.editorView.setViewport(viewport.offsetX, newOffsetY, viewport.width, viewport.height, true);
      this.requestRender();
    }
    if (this._wrapMode === "none") {
      if (direction === "left") {
        const newOffsetX = Math.max(0, viewport.offsetX - delta);
        this.editorView.setViewport(newOffsetX, viewport.offsetY, viewport.width, viewport.height, true);
        this.requestRender();
      } else if (direction === "right") {
        const newOffsetX = viewport.offsetX + delta;
        this.editorView.setViewport(newOffsetX, viewport.offsetY, viewport.width, viewport.height, true);
        this.requestRender();
      }
    }
  }
  onResize(width, height) {
    this.editorView.setViewportSize(width, height);
  }
  refreshLocalSelection() {
    if (this.lastLocalSelection) {
      return this.updateLocalSelection(this.lastLocalSelection);
    }
    return false;
  }
  updateLocalSelection(localSelection) {
    if (!localSelection?.isActive) {
      this.editorView.resetLocalSelection();
      return true;
    }
    return this.editorView.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg, false, false, localSelection.behavior);
  }
  shouldStartSelection(x, y) {
    if (!this.selectable)
      return false;
    const localX = x - this.x;
    const localY = y - this.y;
    return localX >= 0 && localX < this.width && localY >= 0 && localY < this.height;
  }
  onSelectionChanged(selection) {
    const localSelection = convertGlobalToLocalSelection(selection, this.x, this.y);
    this.lastLocalSelection = localSelection;
    const updateCursor = true;
    const followCursor = this._keyboardSelectionActive;
    let changed;
    if (!localSelection?.isActive) {
      this._keyboardSelectionActive = false;
      this.editorView.resetLocalSelection();
      changed = true;
    } else if (selection?.isStart) {
      changed = this.editorView.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg, updateCursor, followCursor, localSelection.behavior);
    } else {
      changed = this.editorView.updateLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg, updateCursor, followCursor, localSelection.behavior);
    }
    if (changed && localSelection?.isActive && selection?.isDragging) {
      const viewport = this.editorView.getViewport();
      const focusY = localSelection.focusY;
      const scrollMargin = Math.max(1, Math.floor(viewport.height * this._scrollMargin));
      if (focusY < scrollMargin) {
        this._autoScrollVelocity = -this._scrollSpeed;
      } else if (focusY >= viewport.height - scrollMargin) {
        this._autoScrollVelocity = this._scrollSpeed;
      } else {
        this._autoScrollVelocity = 0;
      }
    } else {
      this._keyboardSelectionActive = false;
      this._autoScrollVelocity = 0;
      this._autoScrollAccumulator = 0;
    }
    if (changed) {
      this.requestRender();
    }
    return this.hasSelection();
  }
  onUpdate(deltaTime) {
    super.onUpdate(deltaTime);
    if (this._autoScrollVelocity !== 0 && this.hasSelection()) {
      const deltaSeconds = deltaTime / 1000;
      this._autoScrollAccumulator += this._autoScrollVelocity * deltaSeconds;
      const linesToScroll = Math.floor(Math.abs(this._autoScrollAccumulator));
      if (linesToScroll > 0) {
        const direction = this._autoScrollVelocity > 0 ? 1 : -1;
        const viewport = this.editorView.getViewport();
        const totalVirtualLines = this.editorView.getTotalVirtualLineCount();
        const maxOffsetY = Math.max(0, totalVirtualLines - viewport.height);
        const newOffsetY = Math.max(0, Math.min(viewport.offsetY + direction * linesToScroll, maxOffsetY));
        if (newOffsetY !== viewport.offsetY) {
          this.editorView.setViewport(viewport.offsetX, newOffsetY, viewport.width, viewport.height, false);
          this._ctx.requestSelectionUpdate();
        }
        this._autoScrollAccumulator -= direction * linesToScroll;
      }
    }
  }
  getSelectedText() {
    return this.editorView.getSelectedText();
  }
  hasSelection() {
    return this.editorView.hasSelection();
  }
  getSelection() {
    return this.editorView.getSelection();
  }
  refreshSelectionStyle() {
    this.editorView.setSelectionColors(this._selectionBg, this._selectionFg);
  }
  deleteSelectedText() {
    this.editorView.deleteSelectedText();
    this._ctx.clearSelection();
    this.requestRender();
  }
  setSelection(start, end) {
    this.lastLocalSelection = null;
    this.editorView.resetLocalSelection();
    this._ctx.clearSelection();
    this.editorView.setSelection(start, end, this._selectionBg, this._selectionFg);
    this.requestRender();
  }
  setSelectionInclusive(start, end) {
    this.lastLocalSelection = null;
    this.editorView.resetLocalSelection();
    this._ctx.clearSelection();
    this.editorView.setSelectionInclusive(start, end, this._selectionBg, this._selectionFg);
    this.requestRender();
  }
  clearSelection() {
    const had = this.hasSelection();
    this.lastLocalSelection = null;
    this.editorView.resetLocalSelection();
    this._ctx.clearSelection();
    if (had) {
      this.requestRender();
    }
    return had;
  }
  deleteSelection() {
    if (!this.hasSelection())
      return false;
    this.lastLocalSelection = null;
    this.deleteSelectedText();
    return true;
  }
  setCursor(row, col) {
    this.clearSelection();
    this.editBuffer.setCursor(row, col);
    this.requestRender();
  }
  insertChar(char) {
    if (this.hasSelection()) {
      this.deleteSelectedText();
    }
    this.editBuffer.insertChar(char);
    this.requestRender();
  }
  insertText(text) {
    if (this.hasSelection()) {
      this.deleteSelectedText();
    }
    this.editBuffer.insertText(text);
    this.requestRender();
  }
  deleteChar() {
    if (this.hasSelection()) {
      this.deleteSelectedText();
      return true;
    }
    this._ctx.clearSelection();
    this.editBuffer.deleteChar();
    this.requestRender();
    return true;
  }
  deleteCharBackward() {
    if (this.hasSelection()) {
      this.deleteSelectedText();
      return true;
    }
    this._ctx.clearSelection();
    this.editBuffer.deleteCharBackward();
    this.requestRender();
    return true;
  }
  newLine() {
    this._ctx.clearSelection();
    this.editBuffer.newLine();
    this.requestRender();
    return true;
  }
  deleteLine() {
    this._ctx.clearSelection();
    this.editBuffer.deleteLine();
    this.requestRender();
    return true;
  }
  collapseSelectionToEdge(edge) {
    const selection = this.getSelection();
    if (!selection)
      return false;
    this.editBuffer.setCursorByOffset(edge === "start" ? selection.start : selection.end);
    this.clearSelection();
    return true;
  }
  moveCursorLeft(options) {
    const select = options?.select ?? false;
    if (!select && this.collapseSelectionToEdge("start"))
      return true;
    this.updateSelectionForMovement(select, true);
    this.editBuffer.moveCursorLeft();
    this.updateSelectionForMovement(select, false);
    this.requestRender();
    return true;
  }
  moveCursorRight(options) {
    const select = options?.select ?? false;
    if (!select && this.collapseSelectionToEdge("end"))
      return true;
    this.updateSelectionForMovement(select, true);
    this.editBuffer.moveCursorRight();
    this.updateSelectionForMovement(select, false);
    this.requestRender();
    return true;
  }
  moveCursorUp(options) {
    const select = options?.select ?? false;
    this.updateSelectionForMovement(select, true);
    this.editorView.moveUpVisual();
    this.updateSelectionForMovement(select, false);
    this.requestRender();
    return true;
  }
  moveCursorDown(options) {
    const select = options?.select ?? false;
    this.updateSelectionForMovement(select, true);
    this.editorView.moveDownVisual();
    this.updateSelectionForMovement(select, false);
    this.requestRender();
    return true;
  }
  gotoLine(line) {
    this.clearSelection();
    this.editBuffer.gotoLine(line);
    this.requestRender();
  }
  gotoLineStart() {
    this.setCursor(this.logicalCursor.row, 0);
  }
  gotoLineTextEnd() {
    const eol = this.editBuffer.getEOL();
    this.setCursor(eol.row, eol.col);
  }
  gotoLineHome(options) {
    const select = options?.select ?? false;
    if (!select && this.collapseSelectionToEdge("start"))
      return true;
    this.updateSelectionForMovement(select, true);
    const cursor = this.editorView.getCursor();
    if (cursor.col === 0 && cursor.row > 0) {
      this.editBuffer.setCursor(cursor.row - 1, 0);
      const prevLineEol = this.editBuffer.getEOL();
      this.editBuffer.setCursor(prevLineEol.row, prevLineEol.col);
    } else {
      this.editBuffer.setCursor(cursor.row, 0);
    }
    this.updateSelectionForMovement(select, false);
    this.requestRender();
    return true;
  }
  gotoLineEnd(options) {
    const select = options?.select ?? false;
    if (!select && this.collapseSelectionToEdge("end"))
      return true;
    this.updateSelectionForMovement(select, true);
    const cursor = this.editorView.getCursor();
    const eol = this.editBuffer.getEOL();
    const lineCount = this.editBuffer.getLineCount();
    if (cursor.col === eol.col && cursor.row < lineCount - 1) {
      this.editBuffer.setCursor(cursor.row + 1, 0);
    } else {
      this.editBuffer.setCursor(eol.row, eol.col);
    }
    this.updateSelectionForMovement(select, false);
    this.requestRender();
    return true;
  }
  gotoVisualLineHome(options) {
    const select = options?.select ?? false;
    if (!select && this.collapseSelectionToEdge("start"))
      return true;
    this.updateSelectionForMovement(select, true);
    const sol = this.editorView.getVisualSOL();
    this.editBuffer.setCursor(sol.logicalRow, sol.logicalCol);
    this.updateSelectionForMovement(select, false);
    this.requestRender();
    return true;
  }
  gotoVisualLineEnd(options) {
    const select = options?.select ?? false;
    if (!select && this.collapseSelectionToEdge("end"))
      return true;
    this.updateSelectionForMovement(select, true);
    this.editorView.gotoVisualLineEnd();
    this.updateSelectionForMovement(select, false);
    this.requestRender();
    return true;
  }
  gotoBufferHome(options) {
    const select = options?.select ?? false;
    if (!select && this.collapseSelectionToEdge("start"))
      return true;
    this.updateSelectionForMovement(select, true);
    this.editBuffer.setCursor(0, 0);
    this.updateSelectionForMovement(select, false);
    this.requestRender();
    return true;
  }
  gotoBufferEnd(options) {
    const select = options?.select ?? false;
    if (!select && this.collapseSelectionToEdge("end"))
      return true;
    this.updateSelectionForMovement(select, true);
    this.editBuffer.gotoLine(999999);
    this.updateSelectionForMovement(select, false);
    this.requestRender();
    return true;
  }
  selectAll() {
    this.updateSelectionForMovement(false, true);
    this.editBuffer.setCursor(0, 0);
    return this.gotoBufferEnd({ select: true });
  }
  deleteToLineEnd() {
    const cursor = this.editorView.getCursor();
    const eol = this.editBuffer.getEOL();
    if (eol.col > cursor.col) {
      this.editBuffer.deleteRange(cursor.row, cursor.col, eol.row, eol.col);
    }
    this.requestRender();
    return true;
  }
  deleteToLineStart() {
    const cursor = this.editorView.getCursor();
    if (cursor.col > 0) {
      this.editBuffer.deleteRange(cursor.row, 0, cursor.row, cursor.col);
    } else if (cursor.row > 0) {
      this.editBuffer.deleteCharBackward();
    }
    this.requestRender();
    return true;
  }
  undo() {
    this._ctx.clearSelection();
    this.editBuffer.undo();
    this.requestRender();
    return true;
  }
  redo() {
    this._ctx.clearSelection();
    this.editBuffer.redo();
    this.requestRender();
    return true;
  }
  moveWordForward(options) {
    const select = options?.select ?? false;
    if (!select && this.collapseSelectionToEdge("end"))
      return true;
    this.updateSelectionForMovement(select, true);
    const nextWord = this.editBuffer.getNextWordBoundary();
    this.editBuffer.setCursorByOffset(nextWord.offset);
    this.updateSelectionForMovement(select, false);
    this.requestRender();
    return true;
  }
  moveWordBackward(options) {
    const select = options?.select ?? false;
    if (!select && this.collapseSelectionToEdge("start"))
      return true;
    this.updateSelectionForMovement(select, true);
    const prevWord = this.editBuffer.getPrevWordBoundary();
    this.editBuffer.setCursorByOffset(prevWord.offset);
    this.updateSelectionForMovement(select, false);
    this.requestRender();
    return true;
  }
  deleteWordForward() {
    if (this.hasSelection()) {
      this.deleteSelectedText();
      return true;
    }
    const currentCursor = this.editBuffer.getCursorPosition();
    const nextWord = this.editBuffer.getNextWordBoundary();
    if (nextWord.offset > currentCursor.offset) {
      this.editBuffer.deleteRange(currentCursor.row, currentCursor.col, nextWord.row, nextWord.col);
    }
    this._ctx.clearSelection();
    this.requestRender();
    return true;
  }
  deleteWordBackward() {
    if (this.hasSelection()) {
      this.deleteSelectedText();
      return true;
    }
    const currentCursor = this.editBuffer.getCursorPosition();
    const prevWord = this.editBuffer.getPrevWordBoundary();
    if (prevWord.offset < currentCursor.offset) {
      this.editBuffer.deleteRange(prevWord.row, prevWord.col, currentCursor.row, currentCursor.col);
    }
    this._ctx.clearSelection();
    this.requestRender();
    return true;
  }
  setupNativeRenderable() {
    const lib = resolveRenderLib();
    const nativeRenderable = lib.createNativeRenderable();
    if (!lib.nativeRenderableAttachYogaNode(nativeRenderable, this.yogaNode.ptr)) {
      lib.destroyNativeRenderable(nativeRenderable);
      throw new Error("Failed to attach native renderable Yoga node");
    }
    if (!lib.nativeRenderableSetMeasureTarget(nativeRenderable, NativeMeasureTargetKind.EditorView, this.editorView.ptr)) {
      lib.destroyNativeRenderable(nativeRenderable);
      throw new Error("Failed to attach editor native measure target");
    }
    this.nativeRenderable = nativeRenderable;
  }
  render(buffer, deltaTime) {
    if (!this.visible)
      return;
    if (this.isDestroyed)
      return;
    const screenX = this._screenX;
    const screenY = this._screenY;
    this.markClean();
    this._ctx.addToHitGrid(screenX, screenY, this.width, this.height, this.num);
    this.renderSelf(buffer);
    this.renderCursor(buffer);
  }
  renderSelf(buffer) {
    buffer.drawEditorView(this.editorView, this._screenX, this._screenY);
  }
  renderCursor(buffer) {
    if (!this._showCursor || !this._focused)
      return;
    const visualCursor = this.editorView.getVisualCursor();
    const screenX = this._screenX;
    const screenY = this._screenY;
    const cursorX = screenX + visualCursor.visualCol + 1;
    const cursorY = screenY + visualCursor.visualRow + 1;
    this._ctx.setCursorPosition(cursorX, cursorY, true);
    this._ctx.setCursorStyle({ ...this._cursorStyle, color: this._cursorColor });
  }
  focus() {
    super.focus();
    this._ctx.setCursorStyle({ ...this._cursorStyle, color: this._cursorColor });
    this.requestRender();
  }
  blur() {
    super.blur();
    this._ctx.setCursorPosition(0, 0, false);
    this.requestRender();
  }
  onRemove() {
    if (this._focused) {
      this._ctx.setCursorPosition(0, 0, false);
    }
  }
  destroy() {
    if (this.isDestroyed)
      return;
    this.traits = {};
    if (this._focused) {
      this._ctx.setCursorPosition(0, 0, false);
      this.blur();
    }
    if (this.nativeRenderable) {
      resolveRenderLib().destroyNativeRenderable(this.nativeRenderable);
      this.nativeRenderable = null;
    }
    this.editorView.destroy();
    this.editBuffer.destroy();
    super.destroy();
  }
  set onCursorChange(handler) {
    this._cursorChangeListener = handler;
  }
  get onCursorChange() {
    return this._cursorChangeListener;
  }
  set onContentChange(handler) {
    this._contentChangeListener = handler;
  }
  get onContentChange() {
    return this._contentChangeListener;
  }
  get syntaxStyle() {
    return this.editBuffer.getSyntaxStyle();
  }
  set syntaxStyle(style) {
    this.editBuffer.setSyntaxStyle(style);
    this.requestRender();
  }
  addHighlight(lineIdx, highlight) {
    this.editBuffer.addHighlight(lineIdx, highlight);
    this.requestRender();
  }
  addHighlightByCharRange(highlight) {
    this.editBuffer.addHighlightByCharRange(highlight);
    this.requestRender();
  }
  removeHighlightsByRef(hlRef) {
    this.editBuffer.removeHighlightsByRef(hlRef);
    this.requestRender();
  }
  clearLineHighlights(lineIdx) {
    this.editBuffer.clearLineHighlights(lineIdx);
    this.requestRender();
  }
  clearAllHighlights() {
    this.editBuffer.clearAllHighlights();
    this.requestRender();
  }
  getLineHighlights(lineIdx) {
    return this.editBuffer.getLineHighlights(lineIdx);
  }
  setText(text) {
    this.editBuffer.setText(text);
    this.yogaNode.markDirty();
    this.requestRender();
  }
  replaceText(text) {
    this.editBuffer.replaceText(text);
    this.yogaNode.markDirty();
    this.requestRender();
  }
  clear() {
    this.editBuffer.clear();
    this.editBuffer.clearAllHighlights();
    this.yogaNode.markDirty();
    this.requestRender();
  }
  deleteRange(startLine, startCol, endLine, endCol) {
    this.editBuffer.deleteRange(startLine, startCol, endLine, endCol);
    this.yogaNode.markDirty();
    this.requestRender();
  }
  getTextRange(startOffset, endOffset) {
    return this.editBuffer.getTextRange(startOffset, endOffset);
  }
  getTextRangeByCoords(startRow, startCol, endRow, endCol) {
    return this.editBuffer.getTextRangeByCoords(startRow, startCol, endRow, endCol);
  }
  updateSelectionForMovement(shiftPressed, isBeforeMovement) {
    if (!shiftPressed) {
      this._keyboardSelectionActive = false;
      this.clearSelection();
      return;
    }
    if (!this.selectable)
      return;
    this._keyboardSelectionActive = true;
    const visualCursor = this.editorView.getVisualCursor();
    const cursorX = this.x + visualCursor.visualCol;
    const cursorY = this.y + visualCursor.visualRow;
    if (isBeforeMovement) {
      if (!this._ctx.hasSelection || !this.hasSelection()) {
        this._ctx.startSelection(this, cursorX, cursorY);
      } else if (this._ctx.getSelection()?.behavior !== "cell") {
        if (this.editorView.convertSelectionToCell()) {
          const selection = this._ctx.getSelection();
          if (selection)
            selection.behavior = "cell";
        }
      }
      return;
    }
    this._ctx.updateSelection(this, cursorX, cursorY, { finishDragging: true });
  }
}

// src/renderer.ts
import { appendFileSync, writeFileSync } from "fs";

// src/ansi.ts
var ANSI = {
  switchToAlternateScreen: "\x1B[?1049h",
  switchToMainScreen: "\x1B[?1049l",
  reset: "\x1B[0m",
  resetScrollRegion: "\x1B[r",
  home: "\x1B[H",
  clearScreen: "\x1B[2J",
  clearSavedLines: "\x1B[3J",
  scrollDown: (lines) => `\x1B[${lines}T`,
  scrollUp: (lines) => `\x1B[${lines}S`,
  moveCursor: (row, col) => `\x1B[${row};${col}H`,
  moveCursorAndClear: (row, col) => `\x1B[${row};${col}H\x1B[J`,
  setRgbBackground: (r, g, b) => `\x1B[48;2;${r};${g};${b}m`,
  resetBackground: "\x1B[49m",
  bracketedPasteStart: "\x1B[200~",
  bracketedPasteEnd: "\x1B[201~"
};

// src/renderer.ts
import { EventEmitter as EventEmitter5 } from "events";

// src/lib/objects-in-viewport.ts
function getObjectsInViewport(viewport, objects, direction = "column", padding = 10, minTriggerSize = 16) {
  if (viewport.width <= 0 || viewport.height <= 0) {
    return [];
  }
  if (objects.length === 0) {
    return [];
  }
  if (objects.length < minTriggerSize) {
    return objects;
  }
  const viewportTop = viewport.y - padding;
  const viewportBottom = viewport.y + viewport.height + padding;
  const viewportLeft = viewport.x - padding;
  const viewportRight = viewport.x + viewport.width + padding;
  const isRow = direction === "row";
  const children = objects;
  const totalChildren = children.length;
  if (totalChildren === 0)
    return [];
  const vpStart = isRow ? viewportLeft : viewportTop;
  const vpEnd = isRow ? viewportRight : viewportBottom;
  let lo = 0;
  let hi = totalChildren - 1;
  let candidate = -1;
  while (lo <= hi) {
    const mid = lo + hi >> 1;
    const c = children[mid];
    const start = isRow ? c.screenX : c.screenY;
    const end = isRow ? c.screenX + c.width : c.screenY + c.height;
    if (end < vpStart) {
      lo = mid + 1;
    } else if (start > vpEnd) {
      hi = mid - 1;
    } else {
      candidate = mid;
      break;
    }
  }
  const visibleChildren = [];
  if (candidate === -1) {
    candidate = lo > 0 ? lo - 1 : 0;
  }
  const maxLookBehind = 50;
  let left = candidate;
  let gapCount = 0;
  while (left - 1 >= 0) {
    const prev = children[left - 1];
    const prevEnd = isRow ? prev.screenX + prev.width : prev.screenY + prev.height;
    if (prevEnd <= vpStart) {
      gapCount++;
      if (gapCount >= maxLookBehind) {
        break;
      }
    } else {
      gapCount = 0;
    }
    left--;
  }
  let right = candidate + 1;
  while (right < totalChildren) {
    const next = children[right];
    if ((isRow ? next.screenX : next.screenY) >= vpEnd)
      break;
    right++;
  }
  for (let i = left;i < right; i++) {
    const child = children[i];
    const start = isRow ? child.screenX : child.screenY;
    const end = isRow ? child.screenX + child.width : child.screenY + child.height;
    if (end <= vpStart)
      continue;
    if (start >= vpEnd)
      break;
    if (isRow) {
      const childBottom = child.screenY + child.height;
      if (childBottom < viewportTop)
        continue;
      const childTop = child.screenY;
      if (childTop > viewportBottom)
        continue;
    } else {
      const childRight = child.screenX + child.width;
      if (childRight < viewportLeft)
        continue;
      const childLeft = child.screenX;
      if (childLeft > viewportRight)
        continue;
    }
    visibleChildren.push(child);
  }
  if (visibleChildren.length > 1) {
    visibleChildren.sort((a, b) => a.zIndex > b.zIndex ? 1 : a.zIndex < b.zIndex ? -1 : 0);
  }
  return visibleChildren;
}

// src/lib/render-geometry.ts
function calculateRenderGeometry(screenMode, terminalWidth, terminalHeight, footerHeight) {
  const safeTerminalWidth = Math.max(terminalWidth, 0);
  const safeTerminalHeight = Math.max(terminalHeight, 0);
  if (screenMode !== "split-footer") {
    return {
      effectiveFooterHeight: 0,
      renderOffset: 0,
      renderWidth: safeTerminalWidth,
      renderHeight: safeTerminalHeight
    };
  }
  const effectiveFooterHeight = Math.min(footerHeight, safeTerminalHeight);
  return {
    effectiveFooterHeight,
    renderOffset: safeTerminalHeight - effectiveFooterHeight,
    renderWidth: safeTerminalWidth,
    renderHeight: effectiveFooterHeight
  };
}

// src/lib/terminal-capability-detection.ts
function isCapabilityResponse(sequence) {
  if (/\x1b\[\?\d+(?:;\d+)*\$y/.test(sequence)) {
    return true;
  }
  if (/\x1b\[1;(?!1R)\d+R/.test(sequence)) {
    return true;
  }
  if (/\x1bP>\|[\s\S]*?\x1b\\/.test(sequence)) {
    return true;
  }
  if (/\x1bP(?:1\+r4d73(?:=[^\x1b]*)?|0\+r(?:4d73)?)\x1b\\/i.test(sequence)) {
    return true;
  }
  if (/\x1b_G[\s\S]*?\x1b\\/.test(sequence)) {
    return true;
  }
  if (/\x1b\[\?\d+(?:;\d+)?u/.test(sequence)) {
    return true;
  }
  if (/\x1b\[\?[0-9;]*c/.test(sequence)) {
    return true;
  }
  if (/\x1b\]99;[^\x07\x1b]*i=opentui-notifications[^\x07\x1b]*p=\?[\s\S]*?(?:\x07|\x1b\\)/.test(sequence)) {
    return true;
  }
  if (/\x1b\]1337;Capabilities=[\s\S]*?(?:\x07|\x1b\\)/.test(sequence)) {
    return true;
  }
  return false;
}
function isPixelResolutionResponse(sequence) {
  return /\x1b\[4;\d+;\d+t/.test(sequence);
}
function parsePixelResolution(sequence) {
  const match = sequence.match(/\x1b\[4;(\d+);(\d+)t/);
  if (match) {
    const width = Number(match[2]);
    const height = Number(match[1]);
    if (!Number.isSafeInteger(width) || !Number.isSafeInteger(height) || width > 2147483647 || height > 2147483647)
      return null;
    return { width, height };
  }
  return null;
}

// src/renderer-theme-mode.ts
var OSC_THEME_RESPONSE = /\x1b](10|11);(?:(?:rgb:)([0-9a-fA-F]+)\/([0-9a-fA-F]+)\/([0-9a-fA-F]+)|#([0-9a-fA-F]{6}))(?:\x07|\x1b\\)/g;
function scaleOscThemeComponent(component) {
  const value = parseInt(component, 16);
  const maxValue = (1 << 4 * component.length) - 1;
  return Math.round(value / maxValue * 255).toString(16).padStart(2, "0");
}
function oscThemeColorToHex(r, g, b, hex6) {
  if (hex6) {
    return `#${hex6.toLowerCase()}`;
  }
  if (r && g && b) {
    return `#${scaleOscThemeComponent(r)}${scaleOscThemeComponent(g)}${scaleOscThemeComponent(b)}`;
  }
  return "#000000";
}
function inferThemeModeFromBackgroundColor(color) {
  const [r, g, b] = parseColor(color).toInts();
  const brightness = (r * 299 + g * 587 + b * 114) / 1000;
  return brightness > 128 ? "light" : "dark";
}

class RendererThemeMode {
  host;
  clock;
  static QUERY_TIMEOUT_MS = 250;
  _themeMode = null;
  themeQueryPending = true;
  themeOscForeground = null;
  themeOscBackground = null;
  themeRefreshTimeoutId = null;
  waiters = new Set;
  constructor(host, clock) {
    this.host = host;
    this.clock = clock;
  }
  get themeMode() {
    return this._themeMode;
  }
  waitForThemeMode(timeoutMs, isDestroyed) {
    if (this._themeMode !== null || isDestroyed || timeoutMs === 0) {
      return Promise.resolve(this._themeMode);
    }
    return new Promise((resolve) => {
      const waiter = {
        resolve,
        timeoutHandle: null
      };
      if (timeoutMs > 0) {
        waiter.timeoutHandle = this.clock.setTimeout(() => {
          this.waiters.delete(waiter);
          waiter.timeoutHandle = null;
          resolve(this._themeMode);
        }, timeoutMs);
      }
      this.waiters.add(waiter);
    });
  }
  cancelRefresh() {
    if (this.themeRefreshTimeoutId === null) {
      return;
    }
    this.clock.clearTimeout(this.themeRefreshTimeoutId);
    this.themeRefreshTimeoutId = null;
    this.themeQueryPending = false;
  }
  dispose() {
    this.cancelRefresh();
    for (const waiter of this.waiters) {
      if (waiter.timeoutHandle !== null) {
        this.clock.clearTimeout(waiter.timeoutHandle);
      }
      waiter.resolve(this._themeMode);
    }
    this.waiters.clear();
  }
  handleSequence(sequence) {
    if (sequence === "\x1B[?997;1n" || sequence === "\x1B[?997;2n") {
      this.requestThemeOscColors();
      return { handled: true, changedMode: null };
    }
    let handledOscThemeResponse = false;
    let match;
    OSC_THEME_RESPONSE.lastIndex = 0;
    while (match = OSC_THEME_RESPONSE.exec(sequence)) {
      handledOscThemeResponse = true;
      const color = oscThemeColorToHex(match[2], match[3], match[4], match[5]);
      if (match[1] === "10") {
        this.themeOscForeground = color;
      } else {
        this.themeOscBackground = color;
      }
    }
    if (!handledOscThemeResponse) {
      return { handled: false, changedMode: null };
    }
    if (!this.themeQueryPending) {
      return { handled: true, changedMode: null };
    }
    if (!this.themeOscForeground || !this.themeOscBackground) {
      return { handled: true, changedMode: null };
    }
    const nextMode = inferThemeModeFromBackgroundColor(this.themeOscBackground);
    const changedMode = this.applyThemeMode(nextMode);
    this.completeThemeQuery();
    return { handled: true, changedMode };
  }
  clearThemeRefreshTimeout() {
    if (this.themeRefreshTimeoutId === null) {
      return;
    }
    this.clock.clearTimeout(this.themeRefreshTimeoutId);
    this.themeRefreshTimeoutId = null;
  }
  completeThemeQuery() {
    this.clearThemeRefreshTimeout();
    this.themeQueryPending = false;
  }
  requestThemeOscColors() {
    if (this.themeRefreshTimeoutId !== null) {
      return;
    }
    this.themeQueryPending = true;
    this.themeOscForeground = null;
    this.themeOscBackground = null;
    this.host.queryThemeColors();
    this.clearThemeRefreshTimeout();
    this.themeRefreshTimeoutId = this.clock.setTimeout(() => {
      this.completeThemeQuery();
    }, RendererThemeMode.QUERY_TIMEOUT_MS);
  }
  applyThemeMode(mode) {
    const changed = this._themeMode !== mode;
    this._themeMode = mode;
    if (!changed) {
      return null;
    }
    for (const waiter of this.waiters) {
      if (waiter.timeoutHandle !== null) {
        this.clock.clearTimeout(waiter.timeoutHandle);
      }
      waiter.resolve(mode);
    }
    this.waiters.clear();
    return mode;
  }
}

// src/renderer.ts
registerEnvVar({
  name: "OTUI_DUMP_CAPTURES",
  description: "Dump captured stdout and console caches when the renderer exit handler runs.",
  type: "boolean",
  default: false
});
registerEnvVar({
  name: "OTUI_NO_NATIVE_RENDER",
  description: "Skip the Zig/native frame renderer. Useful for debugging the render loop; split-footer stdout flushing may still write ANSI.",
  type: "boolean",
  default: false
});
registerEnvVar({
  name: "OTUI_USE_ALTERNATE_SCREEN",
  description: "When explicitly set, force screen mode selection: true=alternate-screen, false=main-screen.",
  type: "boolean",
  default: true
});
registerEnvVar({
  name: "OTUI_OVERRIDE_STDOUT",
  description: "When explicitly set, force stdout routing: false=passthrough, true=capture in split-footer mode.",
  type: "boolean",
  default: true
});
registerEnvVar({
  name: "OTUI_DEBUG",
  description: "Enable debug mode to capture all raw input for debugging purposes.",
  type: "boolean",
  default: false
});
registerEnvVar({
  name: "OTUI_STDIN_LOG",
  description: "Write the raw stdin byte stream to this file for debugging.",
  type: "string",
  default: ""
});
registerEnvVar({
  name: "OTUI_SHOW_STATS",
  description: "Show the debug overlay at startup.",
  type: "boolean",
  default: false
});
var KITTY_IMAGE_TRANSPORTS = ["raw", "zlib", "file"];
var DEFAULT_FOOTER_HEIGHT = 12;
var MAX_SCROLLBACK_SURFACE_HEIGHT_PASSES = 4;
var TRANSPARENT_RGBA = RGBA.fromValues(0, 0, 0, 0);
var scrollbackSurfaceCounter = 0;
function normalizeFooterHeight(footerHeight) {
  if (footerHeight === undefined) {
    return DEFAULT_FOOTER_HEIGHT;
  }
  if (!Number.isFinite(footerHeight)) {
    throw new Error("footerHeight must be a finite number");
  }
  const normalizedFooterHeight = Math.trunc(footerHeight);
  if (normalizedFooterHeight <= 0) {
    throw new Error("footerHeight must be greater than 0");
  }
  return normalizedFooterHeight;
}
function resolveModes(config) {
  let screenMode = config.screenMode ?? "alternate-screen";
  if (process.env.OTUI_USE_ALTERNATE_SCREEN !== undefined) {
    screenMode = env.OTUI_USE_ALTERNATE_SCREEN ? "alternate-screen" : "main-screen";
  }
  const footerHeight = screenMode === "split-footer" ? normalizeFooterHeight(config.footerHeight) : DEFAULT_FOOTER_HEIGHT;
  let externalOutputMode = config.externalOutputMode ?? (screenMode === "split-footer" ? "capture-stdout" : "passthrough");
  if (process.env.OTUI_OVERRIDE_STDOUT !== undefined) {
    externalOutputMode = env.OTUI_OVERRIDE_STDOUT && screenMode === "split-footer" ? "capture-stdout" : "passthrough";
  }
  if (externalOutputMode === "capture-stdout" && screenMode !== "split-footer") {
    throw new Error('externalOutputMode "capture-stdout" requires screenMode "split-footer"');
  }
  return {
    screenMode,
    footerHeight,
    externalOutputMode
  };
}

class ExternalOutputQueue {
  commits = [];
  get size() {
    return this.commits.length;
  }
  writeSnapshot(commit) {
    this.commits.push(commit);
  }
  peek(limit = Number.POSITIVE_INFINITY) {
    const clampedLimit = Number.isFinite(limit) ? Math.max(1, Math.trunc(limit)) : this.commits.length;
    return this.commits.slice(0, clampedLimit);
  }
  claim(limit = Number.POSITIVE_INFINITY) {
    if (this.commits.length === 0) {
      return [];
    }
    const clampedLimit = Number.isFinite(limit) ? Math.max(1, Math.trunc(limit)) : this.commits.length;
    if (clampedLimit >= this.commits.length) {
      const output2 = this.commits;
      this.commits = [];
      return output2;
    }
    const output = this.commits.slice(0, clampedLimit);
    this.commits = this.commits.slice(clampedLimit);
    return output;
  }
  drop(count) {
    for (const commit of this.commits.splice(0, count)) {
      commit.snapshot.destroy();
    }
  }
  clear() {
    this.drop(this.commits.length);
  }
}
var CHAR_FLAG_CONTINUATION = 3221225472 >>> 0;
var CHAR_FLAG_MASK = 3221225472 >>> 0;

class ScrollbackSnapshotRenderContext extends EventEmitter5 {
  width;
  height;
  terminalWidth;
  terminalHeight;
  resolution;
  frameId = 0;
  widthMethod;
  capabilities;
  hasSelection = false;
  currentFocusedRenderable = null;
  keyInput;
  _internalKeyInput;
  lifecyclePasses = new Set;
  constructor(width, height, widthMethod, terminalWidth = width, terminalHeight = height, resolution = null, capabilities = null) {
    super();
    this.width = width;
    this.height = height;
    this.terminalWidth = terminalWidth;
    this.terminalHeight = terminalHeight;
    this.resolution = resolution;
    this.capabilities = capabilities;
    this.widthMethod = widthMethod;
    this.keyInput = new KeyHandler;
    this._internalKeyInput = new InternalKeyHandler;
  }
  addToHitGrid(_x, _y, _width, _height, _id) {}
  pushHitGridScissorRect(_x, _y, _width, _height) {}
  popHitGridScissorRect() {}
  clearHitGridScissorRects() {}
  requestRender() {}
  setCursorPosition(_x, _y, _visible) {}
  setCursorStyle(_options) {}
  setCursorColor(_color) {}
  setMousePointer(_shape) {}
  requestLive() {}
  dropLive() {}
  getSelection() {
    return null;
  }
  get currentFocusedEditor() {
    if (!this.currentFocusedRenderable)
      return null;
    if (!isEditBufferRenderable(this.currentFocusedRenderable))
      return null;
    return this.currentFocusedRenderable;
  }
  requestSelectionUpdate() {}
  focusRenderable(renderable) {
    this.currentFocusedRenderable = renderable;
  }
  blurRenderable(renderable) {
    if (this.currentFocusedRenderable === renderable) {
      this.currentFocusedRenderable = null;
    }
  }
  registerLifecyclePass(renderable) {
    this.lifecyclePasses.add(renderable);
  }
  unregisterLifecyclePass(renderable) {
    this.lifecyclePasses.delete(renderable);
  }
  getLifecyclePasses() {
    return this.lifecyclePasses;
  }
  clearSelection() {}
  startSelection(_renderable, _x, _y, _behavior) {}
  updateSelection(_currentRenderable, _x, _y, _options) {}
}
var DEFAULT_FORWARDED_ENV_KEYS = [
  "TMPDIR",
  "SSH_CONNECTION",
  "SSH_CLIENT",
  "SSH_TTY",
  "MOSH_CONNECTION",
  "TMUX",
  "ZELLIJ",
  "ZELLIJ_SESSION_NAME",
  "ZELLIJ_PANE_ID",
  "TERM",
  "OPENTUI_GRAPHICS",
  "OPENTUI_IMAGE_PROTOCOL",
  "TERM_PROGRAM",
  "TERM_PROGRAM_VERSION",
  "TERM_FEATURES",
  "ALACRITTY_SOCKET",
  "ALACRITTY_LOG",
  "COLORTERM",
  "TERMUX_VERSION",
  "VHS_RECORD",
  "OPENTUI_FORCE_WCWIDTH",
  "OPENTUI_FORCE_UNICODE",
  "OPENTUI_FORCE_NOZWJ",
  "OPENTUI_FORCE_EXPLICIT_WIDTH",
  "OPENTUI_NOTIFICATION_PROTOCOL",
  "OPENTUI_NOTIFICATIONS",
  "WT_SESSION",
  "STY",
  "WSL_DISTRO_NAME",
  "WSL_INTEROP"
];
var NATIVE_RENDER_STATUS_SKIPPED = 1;
var NATIVE_RENDER_STATUS_FAILED = 2;
var KITTY_FLAG_DISAMBIGUATE = 1;
var KITTY_FLAG_EVENT_TYPES = 2;
var KITTY_FLAG_ALTERNATE_KEYS = 4;
var KITTY_FLAG_ALL_KEYS_AS_ESCAPES = 8;
var KITTY_FLAG_REPORT_TEXT = 16;
var DEFAULT_STDIN_PARSER_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
var NATIVE_PALETTE_QUERY_SIZE = 16;
function buildKittyKeyboardFlags(config) {
  if (!config) {
    return 0;
  }
  let flags = 0;
  if (config.disambiguate !== false) {
    flags |= KITTY_FLAG_DISAMBIGUATE;
  }
  if (config.alternateKeys !== false) {
    flags |= KITTY_FLAG_ALTERNATE_KEYS;
  }
  if (config.events === true) {
    flags |= KITTY_FLAG_EVENT_TYPES;
  }
  if (config.allKeysAsEscapes === true) {
    flags |= KITTY_FLAG_ALL_KEYS_AS_ESCAPES;
  }
  if (config.reportText === true) {
    flags |= KITTY_FLAG_REPORT_TEXT;
  }
  return flags;
}

class MouseEvent {
  type;
  button;
  x;
  y;
  source;
  modifiers;
  scroll;
  target;
  currentTarget = null;
  isDragging;
  _propagationStopped = false;
  _defaultPrevented = false;
  get propagationStopped() {
    return this._propagationStopped;
  }
  get defaultPrevented() {
    return this._defaultPrevented;
  }
  constructor(target, attributes) {
    this.target = target;
    this.type = attributes.type;
    this.button = attributes.button;
    this.x = attributes.x;
    this.y = attributes.y;
    this.modifiers = attributes.modifiers;
    this.scroll = attributes.scroll;
    this.source = attributes.source;
    this.isDragging = attributes.isDragging;
  }
  stopPropagation() {
    this._propagationStopped = true;
  }
  preventDefault() {
    this._defaultPrevented = true;
  }
}
var MouseButton;
((MouseButton2) => {
  MouseButton2[MouseButton2["LEFT"] = 0] = "LEFT";
  MouseButton2[MouseButton2["MIDDLE"] = 1] = "MIDDLE";
  MouseButton2[MouseButton2["RIGHT"] = 2] = "RIGHT";
  MouseButton2[MouseButton2["WHEEL_UP"] = 4] = "WHEEL_UP";
  MouseButton2[MouseButton2["WHEEL_DOWN"] = 5] = "WHEEL_DOWN";
})(MouseButton ||= {});
var rendererTracker = singleton("RendererTracker", () => ({
  renderers: new Set,
  streamOwners: new WeakMap
}));
async function createCliRenderer(config = {}) {
  if (process.argv.includes("--delay-start")) {
    await new Promise((resolve) => setTimeout(resolve, 5000));
  }
  const stdin = config.stdin ?? process.stdin;
  const stdout = config.stdout ?? process.stdout;
  const width = stdout.columns || config.width || 80;
  const height = stdout.rows || config.height || 24;
  const renderer = new CliRenderer(stdin, stdout, width, height, config);
  try {
    await renderer.setupTerminal();
    return renderer;
  } catch (error) {
    try {
      renderer.destroy();
    } catch (destroyError) {
      console.error("Error destroying partially-set-up renderer:", destroyError);
    }
    throw error;
  }
}
var CliRenderEvents;
((CliRenderEvents2) => {
  CliRenderEvents2["RESIZE"] = "resize";
  CliRenderEvents2["FRAME"] = "frame";
  CliRenderEvents2["RENDER_ERROR"] = "render:error";
  CliRenderEvents2["HANDLER_ERROR"] = "handler:error";
  CliRenderEvents2["EXTERNAL_OUTPUT"] = "external_output";
  CliRenderEvents2["FOCUS"] = "focus";
  CliRenderEvents2["BLUR"] = "blur";
  CliRenderEvents2["FOCUSED_RENDERABLE"] = "focused_renderable";
  CliRenderEvents2["FOCUSED_EDITOR"] = "focused_editor";
  CliRenderEvents2["THEME_MODE"] = "theme_mode";
  CliRenderEvents2["PALETTE"] = "palette";
  CliRenderEvents2["CAPABILITIES"] = "capabilities";
  CliRenderEvents2["SELECTION"] = "selection";
  CliRenderEvents2["DEBUG_OVERLAY_TOGGLE"] = "debugOverlay:toggle";
  CliRenderEvents2["DESTROY"] = "destroy";
  CliRenderEvents2["MEMORY_SNAPSHOT"] = "memory:snapshot";
})(CliRenderEvents ||= {});
var RendererControlState;
((RendererControlState2) => {
  RendererControlState2["IDLE"] = "idle";
  RendererControlState2["AUTO_STARTED"] = "auto_started";
  RendererControlState2["EXPLICIT_STARTED"] = "explicit_started";
  RendererControlState2["EXPLICIT_PAUSED"] = "explicit_paused";
  RendererControlState2["EXPLICIT_SUSPENDED"] = "explicit_suspended";
  RendererControlState2["EXPLICIT_STOPPED"] = "explicit_stopped";
})(RendererControlState ||= {});
var CLICK_REPEAT_INTERVAL_MS = 500;

class CliRenderer extends EventEmitter5 {
  static animationFrameId = 0;
  lib;
  rendererPtr;
  stdin;
  stdout;
  exitOnCtrlC;
  exitSignals;
  _exitListenersAdded = false;
  _isDestroyed = false;
  _destroyPending = false;
  _destroyFinalized = false;
  _destroyCleanupPrepared = false;
  _streamLeaseAcquired = false;
  nextRenderBuffer;
  currentRenderBuffer;
  _isRunning = false;
  _targetFps = 30;
  _maxFps = 60;
  automaticMemorySnapshot = false;
  memorySnapshotInterval;
  memorySnapshotTimer = null;
  lastMemorySnapshot = {
    heapUsed: 0,
    heapTotal: 0,
    arrayBuffers: 0
  };
  root;
  width;
  height;
  _useThread = false;
  gatherStats = false;
  frameTimes = [];
  maxStatSamples = 300;
  postProcessFns = [];
  backgroundColor = RGBA.fromInts(0, 0, 0, 0);
  waitingForPixelResolution = false;
  pixelResolutionRequeryPending = false;
  clock;
  rendering = false;
  renderingNative = false;
  renderTimeout = null;
  lastTime = 0;
  frameCount = 0;
  _frameId = 0;
  lastFpsTime = 0;
  currentFps = 0;
  targetFrameTime = 1000 / this._targetFps;
  minTargetFrameTime = 1000 / this._maxFps;
  immediateRerenderRequested = false;
  updateScheduled = false;
  updateGeneration = 0;
  liveRequestCounter = 0;
  _controlState = "idle" /* IDLE */;
  frameCallbacks = [];
  renderStats = {
    frameCount: 0,
    fps: 0,
    renderTime: 0,
    frameCallbackTime: 0
  };
  debugOverlay = {
    enabled: env.OTUI_SHOW_STATS,
    corner: 3 /* bottomRight */
  };
  _console;
  _resolution = null;
  _keyHandler;
  stdinParser = null;
  oscSubscribers = new Set;
  hasLoggedStdinParserError = false;
  animationRequest = new Map;
  resizeTimeoutId = null;
  capabilityTimeoutId = null;
  kittyTransportTimer = null;
  kittyTransportMode;
  terminalKeepAliveTimer = null;
  xtVersionWaiters = new Set;
  splitStartupSeedTimeoutId = null;
  pendingSplitStartupCursorSeed = false;
  resizeDebounceDelay = 100;
  enableMouseMovement = false;
  _useMouse = true;
  autoFocus = true;
  _screenMode = "alternate-screen";
  _footerHeight = DEFAULT_FOOTER_HEIGHT;
  _externalOutputMode = "passthrough";
  clearOnShutdown = true;
  _suspendedMouseEnabled = false;
  _previousControlState = "idle" /* IDLE */;
  pendingSuspendedTerminalSetup = false;
  suspendedNonAltSurfacePreserved = false;
  capturedRenderable;
  lastOverRenderableNum = 0;
  lastOverRenderable;
  currentSelection = null;
  selectionContainers = [];
  lastClick = null;
  clipboard;
  _splitHeight = 0;
  renderOffset = 0;
  splitTailColumn = 0;
  pendingSplitFooterTransition = null;
  forceFullRepaintRequested = false;
  maxSplitCommitsPerFrame = 8;
  _terminalWidth = 0;
  _terminalHeight = 0;
  _terminalIsSetup = false;
  externalOutputQueue = new ExternalOutputQueue;
  pendingExternalOutputMode = null;
  realStdoutWrite;
  _useConsole = true;
  sigwinchHandler = (() => {
    const width = this.stdout.columns;
    const height = this.stdout.rows;
    if (width > 0 && height > 0)
      this.handleResize(width, height);
  }).bind(this);
  _capabilities = null;
  _latestPointer = { x: 0, y: 0 };
  _hasPointer = false;
  _lastPointerModifiers = {
    shift: false,
    alt: false,
    ctrl: false
  };
  _currentMousePointerStyle = undefined;
  _currentFocusedRenderable = null;
  lifecyclePasses = new Set;
  _openConsoleOnError = true;
  _paletteDetector = null;
  _paletteCache = new Map;
  _paletteDetectionPromise = null;
  _paletteDetectionSize = 0;
  _paletteEpoch = 0;
  _nativePaletteSignature = null;
  _emittedPaletteSignature = null;
  _palettePublishGeneration = 0;
  _onDestroy;
  themeModeState;
  _terminalFocusState = null;
  sequenceHandlers = [];
  prependedInputHandlers = [];
  shouldRestoreModesOnNextFocus = false;
  themeModeHandler;
  idleResolvers = [];
  _debugInputs = [];
  _debugModeEnabled = env.OTUI_DEBUG;
  stdinLogPath = env.OTUI_STDIN_LOG;
  handleError = ((error) => {
    console.error(error);
    if (this._openConsoleOnError) {
      this.console.show();
    }
  }).bind(this);
  dumpOutputCache(optionalMessage = "") {
    const cachedLogs = this.console.getCachedLogs();
    const capturedConsoleOutput = capture.claimOutput();
    const capturedExternalOutputCommits = this.externalOutputQueue.claim();
    let capturedExternalOutput = "";
    for (const commit of capturedExternalOutputCommits) {
      capturedExternalOutput += `[snapshot ${commit.snapshot.width}x${commit.snapshot.height}]
`;
      commit.snapshot.destroy();
    }
    if (capturedConsoleOutput.length > 0 || capturedExternalOutput.length > 0 || cachedLogs.length > 0) {
      this.realStdoutWrite.call(this.stdout, optionalMessage);
    }
    if (cachedLogs.length > 0) {
      this.realStdoutWrite.call(this.stdout, `Console cache:
`);
      this.realStdoutWrite.call(this.stdout, cachedLogs);
    }
    if (capturedConsoleOutput.length > 0) {
      this.realStdoutWrite.call(this.stdout, `
Captured console output:
`);
      this.realStdoutWrite.call(this.stdout, capturedConsoleOutput + `
`);
    }
    if (capturedExternalOutput.length > 0) {
      this.realStdoutWrite.call(this.stdout, `
Captured external output:
`);
      this.realStdoutWrite.call(this.stdout, capturedExternalOutput + `
`);
    }
    this.realStdoutWrite.call(this.stdout, ANSI.reset);
  }
  exitHandler = (() => {
    this.destroy();
    if (env.OTUI_DUMP_CAPTURES) {
      sleep(100).then(() => {
        this.dumpOutputCache(`=== CAPTURED OUTPUT ===
`);
      });
    }
  }).bind(this);
  warningHandler = ((warning) => {
    console.warn(JSON.stringify(warning.message, null, 2));
  }).bind(this);
  _usesProcessStdout;
  _feed = null;
  _detachFeed = null;
  _detachFeedError = null;
  feedIdleRenderScheduled = false;
  feedIdleWaitPending = false;
  get controlState() {
    return this._controlState;
  }
  constructor(stdin, stdout, width, height, config = {}) {
    super();
    this.stdin = stdin;
    this.stdout = stdout;
    this._usesProcessStdout = stdout === process.stdout;
    this.realStdoutWrite = stdout.write;
    const lib = resolveRenderLib();
    const useMemoryBufferedOutput = config.bufferedOutput === "memory";
    const useFeedOutput = !this._usesProcessStdout && !useMemoryBufferedOutput;
    const { screenMode, footerHeight, externalOutputMode } = resolveModes(config);
    const initialGeometry = calculateRenderGeometry(screenMode, width, height, footerHeight);
    const remoteMode = config.remote ?? (useFeedOutput ? true : undefined);
    this.kittyTransportMode = config.kittyImageTransport ?? "raw";
    const transportCode = KITTY_IMAGE_TRANSPORTS.indexOf(this.kittyTransportMode);
    if (transportCode < 0)
      throw new TypeError("Invalid kittyImageTransport");
    if (rendererTracker.streamOwners.get(stdin)) {
      throw new Error("Cannot create CliRenderer: stdin is already used by another CliRenderer");
    }
    if (rendererTracker.streamOwners.get(stdout)) {
      throw new Error("Cannot create CliRenderer: stdout is already used by another CliRenderer");
    }
    let feed = null;
    if (useFeedOutput) {
      try {
        feed = NativeSpanFeed.create();
      } catch (error) {
        throw new Error(`Failed to allocate NativeSpanFeed for custom stdout: ${error instanceof Error ? error.message : String(error)}`);
      }
    }
    let rendererPtr;
    try {
      rendererPtr = lib.createRenderer(initialGeometry.renderWidth, initialGeometry.renderHeight, {
        remote: remoteMode,
        feedPtr: feed?.streamPtr ?? null,
        bufferedOutput: config.bufferedOutput
      });
    } catch (error) {
      feed?.close();
      throw error;
    }
    if (!rendererPtr) {
      feed?.close();
      throw new Error("Failed to create renderer");
    }
    lib.setKittyImageTransport(rendererPtr, transportCode);
    if (config.useThread === undefined)
      config.useThread = true;
    if (process.platform === "linux")
      config.useThread = false;
    lib.setUseThread(rendererPtr, config.useThread);
    const kittyConfig = config.useKittyKeyboard ?? {};
    const kittyFlags = buildKittyKeyboardFlags(kittyConfig);
    lib.setKittyKeyboardFlags(rendererPtr, kittyFlags);
    this._feed = feed;
    if (feed) {
      this._detachFeed = feed.onData((bytes) => {
        return new Promise((resolve) => {
          this.realStdoutWrite.call(this.stdout, bytes, () => resolve());
        });
      });
      this._detachFeedError = feed.onError((code) => {
        if (this.kittyTransportTimer !== null)
          this.kittyOutputErrorHandler();
        console.error(`[CliRenderer] NativeSpanFeed error: code=${code}`);
      });
    }
    this.lib = lib;
    this._terminalWidth = width;
    this._terminalHeight = height;
    this._useThread = config.useThread;
    this._externalOutputMode = externalOutputMode;
    this.width = initialGeometry.renderWidth;
    this.height = initialGeometry.renderHeight;
    this._splitHeight = initialGeometry.effectiveFooterHeight;
    this.renderOffset = screenMode === "split-footer" ? 0 : initialGeometry.renderOffset;
    this._footerHeight = footerHeight;
    this.rendererPtr = rendererPtr;
    this.clearOnShutdown = config.clearOnShutdown ?? true;
    this.lib.setClearOnShutdown(this.rendererPtr, this.clearOnShutdown);
    const forwardEnvKeys = config.forwardEnvKeys ?? (remoteMode === true ? [] : [...DEFAULT_FORWARDED_ENV_KEYS]);
    for (const key of forwardEnvKeys) {
      const value = process.env[key];
      if (value === undefined)
        continue;
      this.lib.setTerminalEnvVar(this.rendererPtr, key, value);
    }
    this.exitOnCtrlC = config.exitOnCtrlC === undefined ? true : config.exitOnCtrlC;
    this.exitSignals = config.exitSignals || [
      "SIGINT",
      "SIGTERM",
      "SIGQUIT",
      "SIGABRT",
      "SIGHUP",
      "SIGPIPE",
      "SIGBREAK",
      "SIGBUS"
    ];
    this.clipboard = new Clipboard(this.lib, this.rendererPtr);
    this.resizeDebounceDelay = config.debounceDelay || 100;
    this.targetFps = config.targetFps || 30;
    this.maxFps = config.maxFps || 60;
    this.clock = config.clock ?? new SystemClock;
    this.themeModeState = new RendererThemeMode({
      queryThemeColors: () => {
        this.lib.queryThemeColors(this.rendererPtr);
      }
    }, this.clock);
    this.themeModeHandler = (sequence) => {
      const result = this.themeModeState.handleSequence(sequence);
      if (result.changedMode) {
        this.clearPaletteCache();
        if (this.shouldSyncNativePaletteState() || this.listenerCount("palette" /* PALETTE */) > 0) {
          this.refreshPalette();
        }
        this.emit("theme_mode" /* THEME_MODE */, result.changedMode);
      }
      return result.handled;
    };
    this.memorySnapshotInterval = config.memorySnapshotInterval ?? 0;
    this.gatherStats = config.gatherStats || false;
    this.maxStatSamples = config.maxStatSamples || 300;
    this.enableMouseMovement = config.enableMouseMovement ?? true;
    this._useMouse = config.useMouse ?? true;
    this.autoFocus = config.autoFocus ?? true;
    this.nextRenderBuffer = this.lib.getNextBuffer(this.rendererPtr);
    this.currentRenderBuffer = this.lib.getCurrentBuffer(this.rendererPtr);
    this.postProcessFns = config.postProcessFns || [];
    this.prependedInputHandlers = config.prependInputHandlers || [];
    this.root = new RootRenderable(this);
    if (this.memorySnapshotInterval > 0) {
      this.startMemorySnapshotTimer();
    }
    if (this._usesProcessStdout) {
      process.on("SIGWINCH", this.sigwinchHandler);
    }
    process.on("warning", this.warningHandler);
    process.on("uncaughtException", this.handleError);
    process.on("unhandledRejection", this.handleError);
    const useKittyForParsing = kittyConfig !== null;
    this._keyHandler = new InternalKeyHandler;
    this._keyHandler.on("keypress", (event) => {
      if (this.exitOnCtrlC && matchesKeyBinding(event, { name: "c", ctrl: true })) {
        process.nextTick(() => {
          this.destroy();
        });
        return;
      }
    });
    this.addExitListeners();
    const stdinParserMaxBufferBytes = config.stdinParserMaxBufferBytes ?? DEFAULT_STDIN_PARSER_MAX_BUFFER_BYTES;
    this.stdinParser = new StdinParser({
      timeoutMs: 20,
      maxPendingBytes: stdinParserMaxBufferBytes,
      armTimeouts: true,
      onTimeoutFlush: () => {
        this.drainStdinParser();
      },
      useKittyKeyboard: useKittyForParsing,
      protocolContext: {
        kittyKeyboardEnabled: useKittyForParsing,
        privateCapabilityRepliesActive: false,
        pixelResolutionQueryActive: false,
        explicitWidthCprActive: false,
        startupCursorCprActive: false
      },
      clock: this.clock
    });
    this._console = new TerminalConsole(this, {
      ...config.consoleOptions ?? {},
      clock: this.clock
    });
    this.consoleMode = config.consoleMode ?? "console-overlay";
    this.applyScreenMode(screenMode, false, false);
    rendererTracker.streamOwners.set(stdin, this);
    rendererTracker.streamOwners.set(stdout, this);
    this._streamLeaseAcquired = true;
    rendererTracker.renderers.add(this);
    this.stdout.write = externalOutputMode === "capture-stdout" ? this.interceptStdoutWrite : this.realStdoutWrite;
    this._openConsoleOnError = config.openConsoleOnError ?? true;
    this._onDestroy = config.onDestroy;
    global.requestAnimationFrame = (callback) => {
      const id = CliRenderer.animationFrameId++;
      this.animationRequest.set(id, callback);
      this.requestLive();
      return id;
    };
    global.cancelAnimationFrame = (handle) => {
      if (this.animationRequest.delete(handle))
        this.dropLive();
    };
    const window = global.window;
    if (!window) {
      global.window = {};
    }
    global.window.requestAnimationFrame = requestAnimationFrame;
    if (env.OTUI_NO_NATIVE_RENDER) {
      this.renderNative = () => {
        if (this._splitHeight > 0) {
          this.flushStdoutCache(this._splitHeight);
        }
        return "rendered";
      };
    }
    try {
      this.setupInput();
    } catch (error) {
      try {
        this.destroy();
      } catch (destroyError) {
        console.error("Error destroying renderer after input setup failure:", destroyError);
      }
      throw error;
    }
  }
  addExitListeners() {
    if (this._exitListenersAdded || this.exitSignals.length === 0)
      return;
    this.exitSignals.forEach((signal) => {
      process.addListener(signal, this.exitHandler);
    });
    this._exitListenersAdded = true;
  }
  startTerminalKeepAlive() {
    if (this.stdin !== process.stdin || this.terminalKeepAliveTimer !== null)
      return;
    this.terminalKeepAliveTimer = setInterval(() => {}, 60000);
  }
  stopTerminalKeepAlive() {
    if (this.terminalKeepAliveTimer === null)
      return;
    clearInterval(this.terminalKeepAliveTimer);
    this.terminalKeepAliveTimer = null;
  }
  removeExitListeners() {
    if (!this._exitListenersAdded || this.exitSignals.length === 0)
      return;
    this.exitSignals.forEach((signal) => {
      process.removeListener(signal, this.exitHandler);
    });
    this._exitListenersAdded = false;
  }
  get isDestroyed() {
    return this._isDestroyed;
  }
  registerLifecyclePass(renderable) {
    this.lifecyclePasses.add(renderable);
  }
  unregisterLifecyclePass(renderable) {
    this.lifecyclePasses.delete(renderable);
  }
  getLifecyclePasses() {
    return this.lifecyclePasses;
  }
  get currentFocusedRenderable() {
    return this._currentFocusedRenderable;
  }
  get currentFocusedEditor() {
    if (!this._currentFocusedRenderable)
      return null;
    if (!isEditBufferRenderable(this._currentFocusedRenderable))
      return null;
    return this._currentFocusedRenderable;
  }
  normalizeClockTime(now, fallback) {
    if (Number.isFinite(now)) {
      return now;
    }
    return Number.isFinite(fallback) ? fallback : 0;
  }
  getElapsedMs(now, then) {
    if (!Number.isFinite(now) || !Number.isFinite(then)) {
      return 0;
    }
    return Math.max(now - then, 0);
  }
  focusRenderable(renderable) {
    if (this._currentFocusedRenderable === renderable) {
      return;
    }
    const previousRenderable = this._currentFocusedRenderable;
    const previousEditor = this.currentFocusedEditor;
    this._currentFocusedRenderable = renderable;
    previousRenderable?.blur();
    const currentEditor = this.currentFocusedEditor;
    if (previousEditor !== currentEditor) {
      this.emit("focused_editor" /* FOCUSED_EDITOR */, currentEditor, previousEditor);
    }
    this.emit("focused_renderable" /* FOCUSED_RENDERABLE */, renderable, previousRenderable);
  }
  blurRenderable(renderable) {
    if (this._currentFocusedRenderable !== renderable) {
      return;
    }
    const previousEditor = this.currentFocusedEditor;
    this._currentFocusedRenderable = null;
    if (previousEditor !== null) {
      this.emit("focused_editor" /* FOCUSED_EDITOR */, null, previousEditor);
    }
    this.emit("focused_renderable" /* FOCUSED_RENDERABLE */, null, renderable);
  }
  setCapturedRenderable(renderable) {
    if (this.capturedRenderable === renderable) {
      return;
    }
    this.capturedRenderable = renderable;
  }
  addToHitGrid(x, y, width, height, id) {
    if (!this._useMouse)
      return;
    if (id !== this.capturedRenderable?.num) {
      this.lib.addToHitGrid(this.rendererPtr, x, y, width, height, id);
    }
  }
  pushHitGridScissorRect(x, y, width, height) {
    this.lib.hitGridPushScissorRect(this.rendererPtr, x, y, width, height);
  }
  popHitGridScissorRect() {
    this.lib.hitGridPopScissorRect(this.rendererPtr);
  }
  clearHitGridScissorRects() {
    this.lib.hitGridClearScissorRects(this.rendererPtr);
  }
  get widthMethod() {
    return this.capabilities?.unicode ?? this.nextRenderBuffer.widthMethod;
  }
  get frameId() {
    return this._frameId;
  }
  writeOut(chunk, encoding, callback) {
    if (this.rendererPtr && (this._useThread || this._feed !== null)) {
      const data = typeof chunk === "string" ? chunk : chunk?.toString() ?? "";
      this.lib.writeOut(this.rendererPtr, data);
      if (typeof callback === "function") {
        process.nextTick(callback);
      }
      return true;
    }
    return this.realStdoutWrite.call(this.stdout, chunk, encoding, callback);
  }
  scheduleRenderAfterFeedIdle() {
    const feed = this._feed;
    if (!feed || this._isDestroyed || this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */)
      return;
    this.feedIdleRenderScheduled = true;
    if (this.feedIdleWaitPending)
      return;
    this.feedIdleWaitPending = true;
    feed.idle().then(() => {
      this.feedIdleWaitPending = false;
      if (!this.feedIdleRenderScheduled)
        return;
      if (feed.isBackpressured()) {
        this.scheduleRenderAfterFeedIdle();
        return;
      }
      this.feedIdleRenderScheduled = false;
      this.scheduleRenderTimer();
      this.resolveIdleIfNeeded();
    });
  }
  cancelRenderAfterFeedIdle() {
    if (!this.feedIdleRenderScheduled)
      return;
    this.feedIdleRenderScheduled = false;
    this.immediateRerenderRequested = false;
  }
  handleNativeRenderRejection(status) {
    if (status === NATIVE_RENDER_STATUS_SKIPPED && this._feed) {
      this.scheduleRenderAfterFeedIdle();
      return "retryable-skip";
    }
    if (status === NATIVE_RENDER_STATUS_SKIPPED) {
      if (this._useThread && this._usesProcessStdout)
        return "backpressured";
      console.error("[CliRenderer] Native frame render unexpectedly skipped without a feed");
      return "failed";
    }
    return this.reportNativeRenderFailure();
  }
  reportNativeRenderFailure() {
    console.error("[CliRenderer] Native frame render failed; waiting for the next render request to force repaint");
    return "failed";
  }
  scheduleRenderTimer() {
    if (this.renderTimeout || this._isDestroyed || this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */)
      return;
    const now = this.normalizeClockTime(this.clock.now(), this.lastTime);
    const elapsed = this.getElapsedMs(now, this.lastTime);
    const delay = Math.max(this.minTargetFrameTime - elapsed, 0);
    this.renderTimeout = this.clock.setTimeout(() => {
      this.renderTimeout = null;
      this.loop();
    }, delay);
  }
  scheduleRenderAfterBackpressure() {
    if (this._feed) {
      this.scheduleRenderAfterFeedIdle();
      return;
    }
    this.scheduleRenderTimer();
  }
  requestRender() {
    if (this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
      return;
    }
    if (this.feedIdleRenderScheduled) {
      return;
    }
    if (this._isRunning) {
      if (!this.rendering && !this.renderTimeout) {
        this.scheduleRenderTimer();
      }
      return;
    }
    if (this.rendering) {
      this.immediateRerenderRequested = true;
      return;
    }
    if (!this.updateScheduled && !this.renderTimeout) {
      this.updateScheduled = true;
      const generation = ++this.updateGeneration;
      const now = this.normalizeClockTime(this.clock.now(), this.lastTime);
      const elapsed = this.getElapsedMs(now, this.lastTime);
      const delay = Math.max(this.minTargetFrameTime - elapsed, 0);
      if (delay === 0) {
        process.nextTick(() => this.activateFrame(generation));
        return;
      }
      this.clock.setTimeout(() => this.activateFrame(generation), delay);
    }
  }
  async activateFrame(generation) {
    if (generation !== this.updateGeneration || !this.updateScheduled) {
      this.resolveIdleIfNeeded();
      return;
    }
    try {
      await this.loop();
    } finally {
      if (generation === this.updateGeneration)
        this.updateScheduled = false;
      this.resolveIdleIfNeeded();
    }
  }
  get consoleMode() {
    return this._useConsole ? "console-overlay" : "disabled";
  }
  set consoleMode(mode) {
    this._useConsole = mode === "console-overlay";
    if (this._useConsole) {
      this.console.activate();
    } else {
      this.console.deactivate();
    }
  }
  get isRunning() {
    return this._isRunning;
  }
  isIdleNow() {
    if (this._isDestroyed)
      return true;
    return !this._isRunning && !this.rendering && !this.renderTimeout && !this.updateScheduled && !this.feedIdleRenderScheduled && !this.immediateRerenderRequested;
  }
  resolveIdleIfNeeded() {
    if (!this.isIdleNow())
      return;
    const resolvers = this.idleResolvers.splice(0);
    for (const resolve of resolvers) {
      resolve();
    }
  }
  idle() {
    if (this._isDestroyed)
      return Promise.resolve();
    if (this.isIdleNow())
      return Promise.resolve();
    return new Promise((resolve) => {
      this.idleResolvers.push(resolve);
    });
  }
  getSchedulerState() {
    return {
      isRunning: this._isRunning,
      isRendering: this.rendering,
      hasScheduledRender: Boolean(this.renderTimeout || this.updateScheduled || this.immediateRerenderRequested)
    };
  }
  get resolution() {
    return this._resolution;
  }
  get console() {
    return this._console;
  }
  get keyInput() {
    return this._keyHandler;
  }
  get _internalKeyInput() {
    return this._keyHandler;
  }
  get terminalWidth() {
    return this._terminalWidth;
  }
  get terminalHeight() {
    return this._terminalHeight;
  }
  get useThread() {
    return this._useThread;
  }
  get targetFps() {
    return this._targetFps;
  }
  set targetFps(targetFps) {
    this._targetFps = targetFps;
    this.targetFrameTime = 1000 / this._targetFps;
  }
  get maxFps() {
    return this._maxFps;
  }
  set maxFps(maxFps) {
    this._maxFps = maxFps;
    this.minTargetFrameTime = 1000 / this._maxFps;
  }
  get useMouse() {
    return this._useMouse;
  }
  set useMouse(useMouse) {
    if (this._useMouse === useMouse)
      return;
    this._useMouse = useMouse;
    if (useMouse) {
      this.enableMouse();
      this.requestRender();
    } else {
      this.disableMouse();
    }
  }
  get screenMode() {
    return this._screenMode;
  }
  set screenMode(mode) {
    if (this.externalOutputMode === "capture-stdout" && mode !== "split-footer") {
      if (this.pendingExternalOutputMode === "passthrough") {
        this.flushPendingSplitOutputBeforeLeavingSplitFooter();
      }
      if (this.externalOutputMode !== "capture-stdout") {
        this.applyScreenMode(mode);
        return;
      }
      throw new Error('externalOutputMode "capture-stdout" requires screenMode "split-footer"');
    }
    this.applyScreenMode(mode);
  }
  get footerHeight() {
    return this._footerHeight;
  }
  set footerHeight(footerHeight) {
    const normalizedFooterHeight = normalizeFooterHeight(footerHeight);
    if (normalizedFooterHeight === this._footerHeight) {
      return;
    }
    this._footerHeight = normalizedFooterHeight;
    if (this.screenMode === "split-footer") {
      this.applyScreenMode("split-footer");
    }
  }
  get externalOutputMode() {
    return this._externalOutputMode;
  }
  set externalOutputMode(mode) {
    if (mode === "capture-stdout" && this.screenMode !== "split-footer") {
      throw new Error('externalOutputMode "capture-stdout" requires screenMode "split-footer"');
    }
    const previousMode = this._externalOutputMode;
    if (previousMode === mode) {
      if (this.pendingExternalOutputMode !== null && this.pendingExternalOutputMode !== mode) {
        this.pendingExternalOutputMode = null;
      }
      return;
    }
    const canFlushSplitOutputBeforeTransition = this.canFlushSplitOutputBeforeTransition();
    const isSplitCaptureToPassthrough = previousMode === "capture-stdout" && mode === "passthrough" && this._screenMode === "split-footer" && this._splitHeight > 0;
    if (isSplitCaptureToPassthrough && this.externalOutputQueue.size > 0 && !canFlushSplitOutputBeforeTransition) {
      this.pendingExternalOutputMode = "passthrough";
      return;
    }
    if (isSplitCaptureToPassthrough && canFlushSplitOutputBeforeTransition) {
      this.flushPendingSplitOutputBeforeTransition();
    }
    this.pendingExternalOutputMode = null;
    this.applyExternalOutputMode(mode);
    this.afterExternalOutputModeChanged(previousMode, mode);
  }
  applyExternalOutputMode(mode) {
    this._externalOutputMode = mode;
    this.stdout.write = mode === "capture-stdout" ? this.interceptStdoutWrite : this.realStdoutWrite;
  }
  afterExternalOutputModeChanged(previousMode, mode) {
    if (this._screenMode === "split-footer" && this._splitHeight > 0 && mode === "capture-stdout") {
      const previousSurfaceTopLine = this.renderOffset + 1;
      const previousSurfaceHeight = this._splitHeight;
      this.clearPendingSplitFooterTransition();
      this.resetSplitScrollback(this.getSplitCursorSeedRows());
      if (previousMode === "passthrough" && this._terminalIsSetup) {
        const nextSurfaceTopLine = this.renderOffset + 1;
        if (previousSurfaceTopLine !== nextSurfaceTopLine) {
          this.setPendingSplitFooterTransition({
            mode: "clear-stale-rows",
            sourceTopLine: previousSurfaceTopLine,
            sourceHeight: previousSurfaceHeight,
            targetTopLine: nextSurfaceTopLine,
            targetHeight: this._splitHeight,
            scrollLines: 0
          });
          this.forceFullRepaintRequested = true;
        }
      }
      this.requestRender();
      return;
    }
    if (this._screenMode === "split-footer" && this._splitHeight > 0 && previousMode === "capture-stdout" && mode === "passthrough") {
      this.clearPendingSplitFooterTransition();
      return;
    }
    this.syncSplitFooterState();
  }
  applyPendingExternalOutputModeIfReady() {
    const pendingMode = this.pendingExternalOutputMode;
    if (pendingMode === null || this.externalOutputQueue.size > 0) {
      return;
    }
    const previousMode = this._externalOutputMode;
    this.pendingExternalOutputMode = null;
    if (previousMode === pendingMode) {
      return;
    }
    this.applyExternalOutputMode(pendingMode);
    this.afterExternalOutputModeChanged(previousMode, pendingMode);
  }
  flushPendingSplitOutputBeforeLeavingSplitFooter() {
    if (this.pendingExternalOutputMode !== "passthrough") {
      return;
    }
    if (this.isSplitCursorSeedFrameBlocked() && this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
      this.abortSplitStartupCursorSeed();
    }
    this.flushPendingSplitOutputBeforeTransition();
    if (this.pendingExternalOutputMode !== null) {
      throw new Error("Cannot leave split-footer while captured output is pending");
    }
  }
  get liveRequestCount() {
    return this.liveRequestCounter;
  }
  get currentControlState() {
    return this._controlState;
  }
  get capabilities() {
    return this._capabilities;
  }
  get kittyImageTransport() {
    return this.kittyTransportMode;
  }
  set kittyImageTransport(mode) {
    const code = KITTY_IMAGE_TRANSPORTS.indexOf(mode);
    if (code < 0)
      throw new TypeError("Invalid kittyImageTransport");
    if (this._isDestroyed || mode === this.kittyTransportMode)
      return;
    this.kittyTransportMode = mode;
    this.startKittyTransportPolling();
    this.lib.setKittyImageTransport(this.rendererPtr, code);
    this.requestRender();
  }
  startKittyTransportPolling() {
    if (!this._terminalIsSetup || this.kittyTransportMode !== "file" || this.kittyTransportTimer !== null)
      return;
    this.stdout.on("error", this.kittyOutputErrorHandler);
    this.kittyTransportTimer = this.clock.setInterval(() => {
      if (!this._isDestroyed && this.lib.pollKittyImageTransport(this.rendererPtr))
        this.requestRender();
    }, 1000);
  }
  get kittyImageTransportStatus() {
    const [mode, effective, fileState, fallback, pendingFiles, pendingBytes] = this.lib.getKittyImageTransport(this.rendererPtr);
    return {
      requested: KITTY_IMAGE_TRANSPORTS[mode],
      effective: ["raw", "zlib", "png", "file"][effective],
      fileState: ["disabled", "probing", "ready", "unsupported", "timeout", "io-error", "cancelled"][fileState],
      fallback: ["none", "not-ready", "unavailable", "budget", "busy", "preparation", "compression"][fallback],
      pendingFiles,
      pendingBytes
    };
  }
  cancelKittyImageTransport() {
    if (this._isDestroyed)
      return;
    this.lib.cancelKittyImageTransport(this.rendererPtr, false);
    this.requestRender();
  }
  kittyOutputErrorHandler = () => {
    if (!this._isDestroyed)
      this.lib.cancelKittyImageTransport(this.rendererPtr, true);
  };
  triggerNotification(message, title) {
    if (this._isDestroyed)
      return false;
    return this.lib.triggerNotification(this.rendererPtr, message, title);
  }
  get themeMode() {
    return this.themeModeState.themeMode;
  }
  waitForThemeMode(timeoutMs = 1000) {
    if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
      throw new Error("timeoutMs must be a non-negative finite number");
    }
    return this.themeModeState.waitForThemeMode(timeoutMs, this._isDestroyed);
  }
  getDebugInputs() {
    return [...this._debugInputs];
  }
  get useKittyKeyboard() {
    return this.lib.getKittyKeyboardFlags(this.rendererPtr) > 0;
  }
  set useKittyKeyboard(use) {
    const flags = use ? KITTY_FLAG_DISAMBIGUATE | KITTY_FLAG_ALTERNATE_KEYS : 0;
    this.lib.setKittyKeyboardFlags(this.rendererPtr, flags);
  }
  createScrollbackSurface(options = {}) {
    if (this._screenMode !== "split-footer" || this._externalOutputMode !== "capture-stdout") {
      throw new Error('createScrollbackSurface requires screenMode "split-footer" and externalOutputMode "capture-stdout"');
    }
    const renderer = this;
    const surfaceId = scrollbackSurfaceCounter++;
    const startOnNewLine = options.startOnNewLine ?? true;
    const tailColumn = renderer.getPendingSplitTailColumn();
    const firstLineOffset = !startOnNewLine && tailColumn > 0 && tailColumn < renderer.width ? tailColumn : 0;
    const snapshotContext = new ScrollbackSnapshotRenderContext(renderer.width, 1, renderer.widthMethod, renderer._terminalWidth, renderer._terminalHeight, renderer.resolution, renderer.capabilities);
    let firstLineOffsetOwner = null;
    const renderContext = Object.create(snapshotContext);
    Object.defineProperty(renderContext, "claimFirstLineOffset", {
      value: (renderable) => {
        if (firstLineOffsetOwner?.isDestroyed) {
          firstLineOffsetOwner = null;
        }
        if (firstLineOffsetOwner) {
          return 0;
        }
        firstLineOffsetOwner = renderable ?? null;
        return firstLineOffset;
      },
      enumerable: true,
      configurable: true
    });
    const internalRoot = new RootRenderable(renderContext);
    const publicRoot = new BoxRenderable(renderContext, {
      id: `scrollback-surface-root-${surfaceId}`,
      position: "absolute",
      left: 0,
      top: 0,
      width: renderer.width,
      height: "auto",
      border: false,
      backgroundColor: "transparent",
      shouldFill: false,
      flexDirection: "column"
    });
    internalRoot.add(publicRoot);
    let surfaceWidth = renderer.width;
    let surfaceHeight = 1;
    let surfaceWidthMethod = renderer.widthMethod;
    let surfaceTerminalWidth = renderer._terminalWidth;
    let surfaceTerminalHeight = renderer._terminalHeight;
    let surfaceResolutionWidth = renderer.resolution?.width ?? null;
    let surfaceResolutionHeight = renderer.resolution?.height ?? null;
    let surfaceDestroyed = false;
    let hasRendered = false;
    let nextCommitStartOnNewLine = startOnNewLine;
    let backingBuffer = OptimizedBuffer.create(surfaceWidth, surfaceHeight, surfaceWidthMethod, {
      id: `scrollback-surface-buffer-${surfaceId}`
    });
    const destroyListener = () => {
      destroySurface();
    };
    const assertNotDestroyed = () => {
      if (surfaceDestroyed) {
        throw new Error("ScrollbackSurface is destroyed");
      }
    };
    const assertRendered = () => {
      if (!hasRendered) {
        throw new Error("ScrollbackSurface.commitRows requires render() before commitRows()");
      }
    };
    const assertGeometryStillCurrent = () => {
      if (renderer.width !== surfaceWidth || renderer.widthMethod !== surfaceWidthMethod || renderer._terminalWidth !== surfaceTerminalWidth || renderer._terminalHeight !== surfaceTerminalHeight || (renderer.resolution?.width ?? null) !== surfaceResolutionWidth || (renderer.resolution?.height ?? null) !== surfaceResolutionHeight) {
        throw new Error("ScrollbackSurface.commitRows requires render() after renderer geometry changes");
      }
    };
    const assertRowRange = (startRow, endRowExclusive) => {
      if (!Number.isInteger(startRow) || !Number.isInteger(endRowExclusive)) {
        throw new Error("ScrollbackSurface.commitRows requires finite integer row bounds");
      }
      if (startRow < 0) {
        throw new Error("ScrollbackSurface.commitRows requires startRow >= 0");
      }
      if (endRowExclusive < startRow) {
        throw new Error("ScrollbackSurface.commitRows requires endRowExclusive >= startRow");
      }
      if (endRowExclusive > surfaceHeight) {
        throw new Error("ScrollbackSurface.commitRows row range exceeds rendered surface height");
      }
    };
    const collectPendingCodeRenderables = (node) => {
      const pending = [];
      if (node instanceof CodeRenderable && node.isHighlighting) {
        pending.push(node);
      }
      for (const child of node.getChildren()) {
        pending.push(...collectPendingCodeRenderables(child));
      }
      return pending;
    };
    const waitForPendingHighlights = async (pending, timeoutMs) => {
      await new Promise((resolve, reject) => {
        let settled = false;
        const timeoutHandle = renderer.clock.setTimeout(() => {
          if (settled) {
            return;
          }
          settled = true;
          reject(new Error("ScrollbackSurface.settle timed out waiting for CodeRenderable highlighting"));
        }, timeoutMs);
        Promise.all(pending.map((renderable) => renderable.highlightingDone)).then(() => {
          if (settled) {
            return;
          }
          settled = true;
          renderer.clock.clearTimeout(timeoutHandle);
          resolve();
        }, (error) => {
          if (settled) {
            return;
          }
          settled = true;
          renderer.clock.clearTimeout(timeoutHandle);
          reject(error);
        });
      });
    };
    const renderSurface = () => {
      assertNotDestroyed();
      const width = renderer.width;
      const widthMethod = renderer.widthMethod;
      snapshotContext.width = width;
      snapshotContext.widthMethod = widthMethod;
      snapshotContext.terminalWidth = renderer._terminalWidth;
      snapshotContext.terminalHeight = renderer._terminalHeight;
      snapshotContext.resolution = renderer.resolution;
      snapshotContext.capabilities = renderer.capabilities;
      publicRoot.width = width;
      const renderPass = (height) => {
        snapshotContext.height = height;
        internalRoot.resize(width, height);
        backingBuffer.resize(width, height);
        backingBuffer.clear(TRANSPARENT_RGBA);
        snapshotContext.frameId += 1;
        internalRoot.render(backingBuffer, 0);
      };
      let targetHeight = Math.max(1, surfaceHeight);
      if (surfaceWidthMethod !== widthMethod) {
        backingBuffer.destroy();
        backingBuffer = OptimizedBuffer.create(width, targetHeight, widthMethod, {
          id: `scrollback-surface-buffer-${surfaceId}`
        });
      } else {
        backingBuffer.resize(width, targetHeight);
      }
      for (let pass = 0;pass < MAX_SCROLLBACK_SURFACE_HEIGHT_PASSES; pass += 1) {
        renderPass(targetHeight);
        const measuredHeight = Math.max(1, publicRoot.height);
        if (measuredHeight === targetHeight) {
          surfaceWidth = width;
          surfaceHeight = measuredHeight;
          surfaceWidthMethod = widthMethod;
          surfaceTerminalWidth = renderer._terminalWidth;
          surfaceTerminalHeight = renderer._terminalHeight;
          surfaceResolutionWidth = renderer.resolution?.width ?? null;
          surfaceResolutionHeight = renderer.resolution?.height ?? null;
          hasRendered = true;
          return;
        }
        targetHeight = measuredHeight;
      }
      renderPass(targetHeight);
      surfaceWidth = width;
      surfaceHeight = targetHeight;
      surfaceWidthMethod = widthMethod;
      surfaceTerminalWidth = renderer._terminalWidth;
      surfaceTerminalHeight = renderer._terminalHeight;
      surfaceResolutionWidth = renderer.resolution?.width ?? null;
      surfaceResolutionHeight = renderer.resolution?.height ?? null;
      hasRendered = true;
    };
    const settleSurface = async (timeoutMs = 2000) => {
      assertNotDestroyed();
      const startedAt = renderer.clock.now();
      renderSurface();
      while (true) {
        assertNotDestroyed();
        const pending = collectPendingCodeRenderables(publicRoot);
        if (pending.length === 0) {
          return;
        }
        const remainingMs = timeoutMs - (renderer.clock.now() - startedAt);
        if (remainingMs <= 0) {
          throw new Error("ScrollbackSurface.settle timed out waiting for CodeRenderable highlighting");
        }
        await waitForPendingHighlights(pending, remainingMs);
        assertNotDestroyed();
        renderSurface();
      }
    };
    const commitRows = (startRow, endRowExclusive, commitOptions = {}) => {
      assertNotDestroyed();
      assertRendered();
      assertGeometryStillCurrent();
      assertRowRange(startRow, endRowExclusive);
      if (startRow === endRowExclusive) {
        return;
      }
      const rowCount = endRowExclusive - startRow;
      const commitBuffer = OptimizedBuffer.create(surfaceWidth, rowCount, surfaceWidthMethod, {
        id: `scrollback-surface-commit-${surfaceId}`
      });
      try {
        commitBuffer.drawFrameBuffer(0, 0, backingBuffer, 0, startRow, surfaceWidth, rowCount);
        renderer.enqueueRenderedScrollbackCommit({
          snapshot: commitBuffer,
          rowColumns: commitOptions.rowColumns,
          startOnNewLine: nextCommitStartOnNewLine,
          trailingNewline: commitOptions.trailingNewline ?? true
        });
        nextCommitStartOnNewLine = false;
      } catch (error) {
        commitBuffer.destroy();
        throw error;
      }
    };
    const destroySurface = () => {
      if (surfaceDestroyed) {
        return;
      }
      surfaceDestroyed = true;
      renderer.off("destroy" /* DESTROY */, destroyListener);
      let destroyError = null;
      try {
        internalRoot.destroyRecursively();
      } catch (error) {
        destroyError = error;
      }
      try {
        backingBuffer.destroy();
      } catch (error) {
        if (destroyError === null) {
          destroyError = error;
        }
      }
      renderContext.removeAllListeners();
      snapshotContext.removeAllListeners();
      if (destroyError !== null) {
        throw destroyError;
      }
    };
    renderer.on("destroy" /* DESTROY */, destroyListener);
    return {
      get renderContext() {
        return renderContext;
      },
      get root() {
        return publicRoot;
      },
      get width() {
        return surfaceWidth;
      },
      get height() {
        return surfaceHeight;
      },
      get isDestroyed() {
        return surfaceDestroyed;
      },
      render: renderSurface,
      settle: settleSurface,
      commitRows,
      destroy: destroySurface
    };
  }
  writeToScrollback(write) {
    if (this._screenMode !== "split-footer" || this._externalOutputMode !== "capture-stdout") {
      throw new Error('writeToScrollback requires screenMode "split-footer" and externalOutputMode "capture-stdout"');
    }
    const snapshotContext = new ScrollbackSnapshotRenderContext(this.width, this.height, this.widthMethod, this._terminalWidth, this._terminalHeight, this.resolution, this.capabilities);
    const snapshot = write({
      width: this.width,
      widthMethod: this.widthMethod,
      tailColumn: this.getPendingSplitTailColumn(),
      renderContext: snapshotContext
    });
    if (!snapshot || !snapshot.root) {
      throw new Error("writeToScrollback must return a snapshot root renderable");
    }
    let renderFailed = false;
    let snapshotRoot = null;
    let snapshotBuffer = null;
    try {
      const rootRenderable = snapshot.root;
      const snapshotWidth = this.getSnapshotWidth(snapshot.width, rootRenderable.width);
      const snapshotHeight = this.getSnapshotHeight(snapshot.height, rootRenderable.height);
      snapshotContext.width = snapshotWidth;
      snapshotContext.height = snapshotHeight;
      snapshotContext.widthMethod = this.widthMethod;
      snapshotRoot = new RootRenderable(snapshotContext);
      snapshotBuffer = OptimizedBuffer.create(snapshotWidth, snapshotHeight, this.widthMethod, {
        id: "scrollback-snapshot-commit"
      });
      snapshotRoot.add(rootRenderable);
      snapshotRoot.render(snapshotBuffer, 0);
      this.enqueueRenderedScrollbackCommit({
        snapshot: snapshotBuffer,
        rowColumns: snapshot.rowColumns,
        startOnNewLine: snapshot.startOnNewLine,
        trailingNewline: snapshot.trailingNewline
      });
    } catch (error) {
      renderFailed = true;
      snapshotBuffer?.destroy();
      throw error;
    } finally {
      let cleanupError = null;
      try {
        if (snapshotRoot) {
          snapshotRoot.destroyRecursively();
        } else {
          snapshot.root.destroyRecursively();
        }
      } catch (error) {
        cleanupError = error;
      }
      try {
        snapshot.teardown?.();
      } catch (error) {
        if (cleanupError === null) {
          cleanupError = error;
        }
      }
      if (!renderFailed && cleanupError) {
        throw cleanupError;
      }
    }
  }
  resetSplitFooterForReplay(options = {}) {
    if (this._isDestroyed)
      return;
    if (this._screenMode !== "split-footer" || this._externalOutputMode !== "capture-stdout") {
      throw new Error('resetSplitFooterForReplay requires screenMode "split-footer" and externalOutputMode "capture-stdout"');
    }
    if (!this._terminalIsSetup || this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
      throw new Error("resetSplitFooterForReplay requires an active terminal");
    }
    this.flushPendingSplitOutputBeforeTransition(true);
    this.externalOutputQueue.clear();
    this.abortSplitStartupCursorSeed();
    this.clearPendingSplitFooterTransition();
    this.resetSplitScrollback();
    this.currentRenderBuffer.clear(this.backgroundColor);
    this.nextRenderBuffer.clear(this.backgroundColor);
    this.forceFullRepaintRequested = true;
    this.writeOut(ANSI.resetScrollRegion + ANSI.reset + ANSI.home + ANSI.clearScreen + (options.clearSavedLines ? ANSI.clearSavedLines : "") + ANSI.home);
    this.requestRender();
  }
  getSnapshotWidth(value, fallback) {
    const rawValue = value ?? fallback;
    if (!Number.isFinite(rawValue)) {
      throw new Error("writeToScrollback produced a non-finite width");
    }
    return Math.min(Math.max(Math.trunc(rawValue), 1), Math.max(this.width, 1));
  }
  getSnapshotHeight(value, fallback) {
    const rawValue = value ?? fallback;
    if (!Number.isFinite(rawValue)) {
      throw new Error("writeToScrollback produced a non-finite height");
    }
    return Math.max(Math.trunc(rawValue), 1);
  }
  getSnapshotRowWidths(snapshot, rowColumns) {
    const widths = [];
    const limit = Math.min(Math.max(Math.trunc(rowColumns), 0), snapshot.width);
    const chars = snapshot.buffers.char;
    for (let y = 0;y < snapshot.height; y += 1) {
      let x = limit;
      while (x > 0) {
        const cp = chars[y * snapshot.width + x - 1];
        if (cp === 0 || (cp & CHAR_FLAG_MASK) === CHAR_FLAG_CONTINUATION) {
          x -= 1;
          continue;
        }
        break;
      }
      widths.push(x);
    }
    return widths;
  }
  advanceSplitTailColumn(tailColumn, columns, width) {
    if (columns <= 0) {
      return tailColumn;
    }
    let tail = tailColumn;
    let remaining = columns;
    while (remaining > 0) {
      if (tail >= width) {
        tail = 0;
      }
      const step = Math.min(remaining, width - tail);
      tail += step;
      remaining -= step;
      if (remaining > 0 && tail >= width) {
        tail = 0;
      }
    }
    return tail;
  }
  getSplitTailColumnAfterCommit(commit, initialTailColumn, width) {
    let tailColumn = initialTailColumn;
    if (commit.startOnNewLine && tailColumn > 0) {
      tailColumn = 0;
    }
    const rowWidths = this.getSnapshotRowWidths(commit.snapshot, commit.rowColumns);
    for (const [index, rowWidth] of rowWidths.entries()) {
      tailColumn = this.advanceSplitTailColumn(tailColumn, rowWidth, width);
      if (index < rowWidths.length - 1 || commit.trailingNewline) {
        tailColumn = 0;
      }
    }
    return tailColumn;
  }
  recordSplitCommit(commit) {
    this.splitTailColumn = this.getSplitTailColumnAfterCommit(commit, this.splitTailColumn, Math.max(this.width, 1));
  }
  getPendingSplitTailColumn() {
    const width = Math.max(this.width, 1);
    let tailColumn = this.splitTailColumn;
    for (const commit of this.externalOutputQueue.peek()) {
      tailColumn = this.getSplitTailColumnAfterCommit(commit, tailColumn, width);
    }
    return tailColumn;
  }
  enqueueRenderedScrollbackCommit(options) {
    if (this._screenMode !== "split-footer" || this._externalOutputMode !== "capture-stdout") {
      throw new Error('scrollback commit requires screenMode "split-footer" and externalOutputMode "capture-stdout"');
    }
    const rowColumns = Math.min(Math.max(Math.trunc(options.rowColumns ?? options.snapshot.width), 0), options.snapshot.width);
    this.enqueueSplitCommit({
      snapshot: options.snapshot,
      rowColumns,
      startOnNewLine: options.startOnNewLine ?? true,
      trailingNewline: options.trailingNewline ?? true
    });
    this.requestRender();
  }
  enqueueSplitCommit(commit) {
    this.externalOutputQueue.writeSnapshot(commit);
    if (this.listenerCount("external_output" /* EXTERNAL_OUTPUT */) > 0) {
      this.emit("external_output" /* EXTERNAL_OUTPUT */, commit);
    }
  }
  createStdoutSnapshotCommit(line, trailingNewline) {
    const snapshotContext = new ScrollbackSnapshotRenderContext(this.width, 1, this.widthMethod, this._terminalWidth, this._terminalHeight, this.resolution, this.capabilities);
    const maxWidth = Math.max(1, this.width);
    const lineCells = [...line];
    const rowColumns = Math.min(lineCells.length, maxWidth);
    const renderedLine = lineCells.slice(0, maxWidth).join("");
    const snapshotRoot = new RootRenderable(snapshotContext);
    const snapshotRenderable = new TextRenderable(snapshotContext, {
      id: "captured-stdout-snapshot",
      position: "absolute",
      left: 0,
      top: 0,
      width: Math.max(1, rowColumns),
      height: 1,
      content: renderedLine
    });
    const snapshotBuffer = OptimizedBuffer.create(Math.max(1, rowColumns), 1, this.widthMethod, {
      id: "captured-stdout-snapshot"
    });
    try {
      snapshotRoot.add(snapshotRenderable);
      snapshotRoot.render(snapshotBuffer, 0);
      return {
        snapshot: snapshotBuffer,
        rowColumns,
        startOnNewLine: false,
        trailingNewline
      };
    } catch (error) {
      snapshotBuffer.destroy();
      throw error;
    } finally {
      snapshotRoot.destroyRecursively();
    }
  }
  splitStdoutRows(text) {
    const rows = [];
    let current = "";
    for (const char of text) {
      if (char === "\r") {
        current = "";
        continue;
      }
      if (char === `
`) {
        rows.push({ line: current, trailingNewline: true });
        current = "";
        continue;
      }
      current += char;
    }
    if (current.length > 0) {
      rows.push({ line: current, trailingNewline: false });
    }
    return rows;
  }
  createStdoutSnapshotCommits(text) {
    if (text.length === 0) {
      return [];
    }
    const commits = [];
    const chunkWidth = Math.max(1, this.width);
    for (const row of this.splitStdoutRows(text)) {
      const rowCells = [...row.line];
      if (rowCells.length === 0) {
        commits.push(this.createStdoutSnapshotCommit("", row.trailingNewline));
        continue;
      }
      let offset = 0;
      while (offset < rowCells.length) {
        const chunk = rowCells.slice(offset, offset + chunkWidth).join("");
        offset += chunkWidth;
        const isLastChunk = offset >= rowCells.length;
        commits.push(this.createStdoutSnapshotCommit(chunk, isLastChunk ? row.trailingNewline : false));
      }
    }
    return commits;
  }
  flushPendingSplitCommits(forceFooterRepaint = false, drainAll = false) {
    const commits = this.externalOutputQueue.peek(drainAll ? Number.POSITIVE_INFINITY : this.maxSplitCommitsPerFrame);
    let hasCommittedOutput = false;
    const lastCommitIndex = commits.length - 1;
    let acceptedCommits = 0;
    let nativeBackpressured = false;
    let nativeFailed = false;
    let nextRenderOffset = this.renderOffset;
    for (const [index, commit] of commits.entries()) {
      const forceCommit = forceFooterRepaint && index === lastCommitIndex;
      const beginFrame = index === 0;
      const finalizeFrame = index === lastCommitIndex;
      const nativeResult = this.lib.commitSplitFooterSnapshot(this.rendererPtr, commit.snapshot, commit.rowColumns, commit.startOnNewLine, commit.trailingNewline, this.getSplitPinnedRenderOffset(), forceCommit, beginFrame, finalizeFrame, drainAll);
      if (nativeResult.status === NATIVE_RENDER_STATUS_SKIPPED) {
        nativeBackpressured = true;
        break;
      }
      if (nativeResult.status === NATIVE_RENDER_STATUS_FAILED) {
        nativeFailed = true;
        break;
      }
      nextRenderOffset = nativeResult.renderOffset;
      hasCommittedOutput = true;
      acceptedCommits++;
    }
    if (nativeFailed) {
      return this.reportNativeRenderFailure();
    }
    if (nativeBackpressured) {
      this.scheduleRenderAfterFeedIdle();
      return "backpressured";
    }
    if (acceptedCommits > 0) {
      this.renderOffset = nextRenderOffset;
      for (const commit of commits.slice(0, acceptedCommits))
        this.recordSplitCommit(commit);
      this.externalOutputQueue.drop(acceptedCommits);
    }
    if (!hasCommittedOutput) {
      const nativeResult = this.lib.repaintSplitFooter(this.rendererPtr, this.getSplitPinnedRenderOffset(), forceFooterRepaint);
      if (nativeResult.status === NATIVE_RENDER_STATUS_SKIPPED) {
        this.scheduleRenderAfterFeedIdle();
        return "backpressured";
      }
      if (nativeResult.status === NATIVE_RENDER_STATUS_FAILED) {
        return this.reportNativeRenderFailure();
      }
      this.renderOffset = nativeResult.renderOffset;
    }
    this.pendingSplitFooterTransition = null;
    if (this.externalOutputQueue.size > 0) {
      this.requestRender();
    } else {
      this.applyPendingExternalOutputModeIfReady();
    }
    return "rendered";
  }
  interceptStdoutWrite = (chunk, encoding, callback) => {
    const resolvedCallback = typeof encoding === "function" ? encoding : callback;
    const resolvedEncoding = typeof encoding === "string" ? encoding : undefined;
    const text = typeof chunk === "string" ? chunk : chunk?.toString(resolvedEncoding) ?? "";
    if (this._externalOutputMode === "capture-stdout" && this._screenMode === "split-footer" && this._splitHeight > 0) {
      const commits = this.createStdoutSnapshotCommits(text);
      for (const commit of commits) {
        this.enqueueSplitCommit(commit);
      }
      if (commits.length > 0) {
        this.requestRender();
      }
    }
    if (typeof resolvedCallback === "function") {
      process.nextTick(resolvedCallback);
    }
    return true;
  };
  getSplitPinnedRenderOffset() {
    return this._screenMode === "split-footer" ? Math.max(this._terminalHeight - this._splitHeight, 0) : 0;
  }
  getSplitCursorSeedRows() {
    const cursorState = this.lib.getCursorState(this.rendererPtr);
    const cursorRow = Number.isFinite(cursorState.y) ? Math.max(Math.trunc(cursorState.y), 1) : 1;
    return Math.min(cursorRow, Math.max(this._terminalHeight, 1));
  }
  isSplitCursorSeedFrameBlocked() {
    return this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout" && this._splitHeight > 0 && this.pendingSplitStartupCursorSeed && this.splitStartupSeedTimeoutId !== null;
  }
  canFlushSplitOutputBeforeTransition(allowSuspended = false, allowUnsetup = false) {
    return (this._terminalIsSetup || allowUnsetup) && (allowSuspended || this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */) && !this.isSplitCursorSeedFrameBlocked();
  }
  clearSplitStartupCursorSeed() {
    this.pendingSplitStartupCursorSeed = false;
    if (this.splitStartupSeedTimeoutId !== null) {
      this.clock.clearTimeout(this.splitStartupSeedTimeoutId);
      this.splitStartupSeedTimeoutId = null;
    }
  }
  abortSplitStartupCursorSeed() {
    this.clearSplitStartupCursorSeed();
    this.stdinParser?.abortPendingStartupCursorCpr();
    this.updateStdinParserProtocolContext({ startupCursorCprActive: false });
  }
  flushPendingSplitOutputBeforeTransition(forceFooterRepaint = false, options = {}) {
    const hasDeferredCapturedOutput = this.externalOutputQueue.size > 0 || this.pendingExternalOutputMode !== null;
    if (this._screenMode !== "split-footer" || this._splitHeight <= 0 || this._externalOutputMode !== "capture-stdout" && !(options.allowPassthrough && hasDeferredCapturedOutput)) {
      return;
    }
    if (!this.canFlushSplitOutputBeforeTransition(options.allowSuspended ?? false, options.allowUnsetup ?? false)) {
      return;
    }
    if (this.externalOutputQueue.size === 0 && !forceFooterRepaint) {
      this.applyPendingExternalOutputModeIfReady();
      return;
    }
    this.flushPendingSplitCommits(this._externalOutputMode === "capture-stdout" ? forceFooterRepaint : false, true);
  }
  resetSplitScrollback(seedRows = 0) {
    this.splitTailColumn = 0;
    this.renderOffset = this.lib.resetSplitScrollback(this.rendererPtr, seedRows, this.getSplitPinnedRenderOffset());
  }
  syncSplitScrollback() {
    this.renderOffset = this.lib.syncSplitScrollback(this.rendererPtr, this.getSplitPinnedRenderOffset());
  }
  getSplitOutputOffset(surfaceOffset = this.renderOffset) {
    return this.lib.getSplitOutputOffset(this.rendererPtr, surfaceOffset);
  }
  clearPendingSplitFooterTransition() {
    if (this.pendingSplitFooterTransition === null) {
      return;
    }
    this.pendingSplitFooterTransition = null;
    this.lib.clearPendingSplitFooterTransition(this.rendererPtr);
  }
  setPendingSplitFooterTransition(transition) {
    this.pendingSplitFooterTransition = transition;
    this.lib.setPendingSplitFooterTransition(this.rendererPtr, transition.mode === "viewport-scroll" ? 1 : 2, transition.sourceTopLine, transition.sourceHeight, transition.targetTopLine, transition.targetHeight, transition.scrollLines ?? 0);
  }
  syncSplitFooterState() {
    const splitActive = this._screenMode === "split-footer" && this._splitHeight > 0;
    if (!splitActive) {
      this.clearPendingSplitFooterTransition();
      this.splitTailColumn = 0;
      this.lib.resetSplitScrollback(this.rendererPtr, 0, 0);
      this.renderOffset = 0;
      this.lib.setRenderOffset(this.rendererPtr, this.renderOffset);
      return;
    }
    if (this._externalOutputMode === "capture-stdout") {
      this.syncSplitScrollback();
    } else {
      this.clearPendingSplitFooterTransition();
      this.splitTailColumn = 0;
      this.lib.resetSplitScrollback(this.rendererPtr, 0, 0);
      this.renderOffset = this.getSplitPinnedRenderOffset();
      this.lib.setRenderOffset(this.rendererPtr, this.renderOffset);
    }
  }
  clearStaleSplitSurfaceRows(previousTopLine, previousHeight, nextTopLine, nextHeight) {
    if (!this._terminalIsSetup || previousHeight <= 0 || this._terminalHeight <= 0) {
      return;
    }
    const terminalBottom = this._terminalHeight;
    const previousStart = Math.max(1, previousTopLine);
    const previousEnd = Math.min(terminalBottom, previousTopLine + previousHeight - 1);
    if (previousEnd < previousStart) {
      return;
    }
    const nextStart = Math.max(1, nextTopLine);
    const nextEnd = Math.min(terminalBottom, nextTopLine + Math.max(nextHeight, 0) - 1);
    let clear = "";
    for (let line = previousStart;line <= previousEnd; line += 1) {
      if (line >= nextStart && line <= nextEnd) {
        continue;
      }
      clear += `${ANSI.moveCursor(line, 1)}\x1B[2K`;
    }
    if (clear.length > 0) {
      this.writeOut(clear);
    }
  }
  applyScreenMode(screenMode, emitResize = true, requestRender = true) {
    const prevScreenMode = this._screenMode;
    const prevSplitHeight = this._splitHeight;
    const nextGeometry = calculateRenderGeometry(screenMode, this._terminalWidth, this._terminalHeight, this._footerHeight);
    const nextSplitHeight = nextGeometry.effectiveFooterHeight;
    if (prevScreenMode === screenMode && prevSplitHeight === nextSplitHeight) {
      return;
    }
    const terminalWritable = this._terminalIsSetup && this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */;
    const prevUseAlternateScreen = prevScreenMode === "alternate-screen";
    const nextUseAlternateScreen = screenMode === "alternate-screen";
    const terminalScreenModeChanged = this._terminalIsSetup && prevUseAlternateScreen !== nextUseAlternateScreen;
    const leavingSplitFooter = prevSplitHeight > 0 && nextSplitHeight === 0;
    if (terminalWritable && prevSplitHeight > 0) {
      this.flushPendingSplitOutputBeforeTransition();
    }
    const previousSurfaceTopLine = this.renderOffset + 1;
    const shouldDeferSplitFooterResizeTransition = this._terminalIsSetup && prevScreenMode === "split-footer" && screenMode === "split-footer" && this._externalOutputMode === "capture-stdout" && prevSplitHeight > 0 && nextSplitHeight > 0 && !terminalScreenModeChanged;
    const splitStartupSeedBlocksFirstNativeFrame = this.pendingSplitStartupCursorSeed && this.splitStartupSeedTimeoutId !== null;
    const splitTransitionSourceTopLine = this.pendingSplitFooterTransition?.sourceTopLine ?? previousSurfaceTopLine;
    const splitTransitionSourceHeight = this.pendingSplitFooterTransition?.sourceHeight ?? prevSplitHeight;
    const splitTransitionSourceSurfaceOffset = Math.max(splitTransitionSourceTopLine - 1, 0);
    const splitTransitionSourceOutputOffset = prevScreenMode === "split-footer" && prevSplitHeight > 0 && this._externalOutputMode === "capture-stdout" ? this.getSplitOutputOffset(splitTransitionSourceSurfaceOffset) : splitTransitionSourceSurfaceOffset;
    const nextPinnedRenderOffset = nextGeometry.renderOffset;
    const nextSplitOutputOffset = screenMode === "split-footer" && nextSplitHeight > 0 && this._externalOutputMode === "capture-stdout" ? this.getSplitOutputOffset(nextPinnedRenderOffset) : nextPinnedRenderOffset;
    const pendingSplitFooterTransition = this.pendingSplitFooterTransition;
    const pendingSplitFooterReturn = pendingSplitFooterTransition !== null && nextSplitHeight === splitTransitionSourceHeight;
    const pendingSplitFooterViewportReturn = pendingSplitFooterReturn && pendingSplitFooterTransition.mode === "viewport-scroll" && (pendingSplitFooterTransition.scrollLines ?? 0) > 0;
    const shrinkingSplitFooter = nextSplitHeight > 0 && nextSplitHeight < splitTransitionSourceHeight;
    const growingSplitFooter = nextSplitHeight > splitTransitionSourceHeight && splitTransitionSourceHeight > 0;
    const nextSplitSurfaceOffset = screenMode !== "split-footer" || nextSplitHeight === 0 ? 0 : pendingSplitFooterViewportReturn ? pendingSplitFooterTransition.targetTopLine - 1 : pendingSplitFooterReturn ? splitTransitionSourceSurfaceOffset : shrinkingSplitFooter && splitTransitionSourceSurfaceOffset > 0 ? splitTransitionSourceSurfaceOffset : shrinkingSplitFooter ? nextSplitOutputOffset : growingSplitFooter ? Math.max(nextSplitOutputOffset, Math.min(splitTransitionSourceSurfaceOffset, nextPinnedRenderOffset)) : nextPinnedRenderOffset;
    const splitTransitionTargetTopLine = nextSplitSurfaceOffset + 1;
    const splitViewportScrollLines = pendingSplitFooterViewportReturn ? pendingSplitFooterTransition.scrollLines ?? 0 : nextSplitHeight > 0 && !pendingSplitFooterReturn ? Math.max(splitTransitionSourceOutputOffset - nextSplitOutputOffset, 0) : 0;
    const splitTransitionMode = (!shrinkingSplitFooter || pendingSplitFooterViewportReturn) && splitViewportScrollLines > 0 ? "viewport-scroll" : "clear-stale-rows";
    const splitFooterSurfaceMovesDown = nextSplitSurfaceOffset > splitTransitionSourceSurfaceOffset;
    const splitFooterSurfaceLeavesStaleRows = splitFooterSurfaceMovesDown || shrinkingSplitFooter;
    const shouldClearSplitSurfaceRowsImmediately = terminalWritable && !terminalScreenModeChanged && !shouldDeferSplitFooterResizeTransition && splitFooterSurfaceLeavesStaleRows && nextSplitHeight > 0;
    if (terminalWritable && leavingSplitFooter) {
      this.clearPendingSplitFooterTransition();
      this.renderOffset = 0;
      this.lib.setRenderOffset(this.rendererPtr, 0);
    }
    if (terminalWritable && !terminalScreenModeChanged && !shouldDeferSplitFooterResizeTransition) {
      if (prevSplitHeight === 0 && nextSplitHeight > 0) {
        const freedLines = this._terminalHeight - nextSplitHeight;
        const scrollDown = ANSI.scrollDown(freedLines);
        this.writeOut(scrollDown);
      } else if (splitViewportScrollLines > 0) {
        const additionalLines = splitViewportScrollLines;
        const scrollUp = ANSI.scrollUp(additionalLines);
        this.writeOut(scrollUp);
      }
    }
    this._screenMode = screenMode;
    this._splitHeight = nextSplitHeight;
    this.width = nextGeometry.renderWidth;
    this.height = nextGeometry.renderHeight;
    this.lib.resizeRenderer(this.rendererPtr, this.width, this.height);
    if (this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout") {
      if (prevScreenMode !== "split-footer") {
        this.resetSplitScrollback(this.getSplitCursorSeedRows());
      } else {
        this.renderOffset = nextSplitSurfaceOffset;
        this.lib.setRenderOffset(this.rendererPtr, this.renderOffset);
      }
      if (shouldDeferSplitFooterResizeTransition) {
        if (splitStartupSeedBlocksFirstNativeFrame) {
          this.clearPendingSplitFooterTransition();
        } else {
          this.setPendingSplitFooterTransition({
            mode: splitTransitionMode,
            sourceTopLine: splitTransitionSourceTopLine,
            sourceHeight: splitTransitionSourceHeight,
            targetTopLine: splitTransitionTargetTopLine,
            targetHeight: nextSplitHeight,
            scrollLines: splitViewportScrollLines
          });
        }
        this.forceFullRepaintRequested = true;
      } else if (shouldClearSplitSurfaceRowsImmediately) {
        this.clearPendingSplitFooterTransition();
        this.clearStaleSplitSurfaceRows(splitTransitionSourceTopLine, splitTransitionSourceHeight, splitTransitionTargetTopLine, nextSplitHeight);
      } else {
        this.clearPendingSplitFooterTransition();
      }
    } else {
      this.syncSplitFooterState();
      if (shouldClearSplitSurfaceRowsImmediately) {
        this.clearStaleSplitSurfaceRows(splitTransitionSourceTopLine, splitTransitionSourceHeight, this.renderOffset + 1, nextSplitHeight);
      }
    }
    this.nextRenderBuffer = this.lib.getNextBuffer(this.rendererPtr);
    this.currentRenderBuffer = this.lib.getCurrentBuffer(this.rendererPtr);
    this._console.resize(this.width, this.height);
    this.root.resize(this.width, this.height);
    if (terminalScreenModeChanged) {
      if (terminalWritable) {
        this.lib.suspendRenderer(this.rendererPtr);
        this.lib.setupTerminal(this.rendererPtr, nextUseAlternateScreen);
        this.pendingSuspendedTerminalSetup = false;
      } else {
        this.pendingSuspendedTerminalSetup = true;
      }
      if (terminalWritable && this._useMouse) {
        this.enableMouse();
      }
    }
    if (emitResize) {
      this.emit("resize" /* RESIZE */, this.width, this.height);
    }
    if (requestRender) {
      this.requestRender();
    }
  }
  flushStdoutCache(space, force = false) {
    if (this.externalOutputQueue.size === 0 && !force)
      return false;
    const outputCommits = this.externalOutputQueue.claim();
    let output = "";
    for (const commit of outputCommits) {
      output += `[snapshot ${commit.snapshot.width}x${commit.snapshot.height}]
`;
      commit.snapshot.destroy();
    }
    const rendererStartLine = this.renderOffset + 1;
    const flush = ANSI.moveCursorAndClear(rendererStartLine, 1);
    const outputLine = this.renderOffset + 1;
    const move = ANSI.moveCursor(outputLine, 1);
    let clear = "";
    if (space > 0) {
      const backgroundColor = this.backgroundColor.toInts();
      const newlines = " ".repeat(this.width) + `
`.repeat(space);
      if (backgroundColor[3] === 0) {
        clear = newlines;
      } else {
        clear = ANSI.setRgbBackground(backgroundColor[0], backgroundColor[1], backgroundColor[2]) + newlines + ANSI.resetBackground;
      }
    }
    this.writeOut(flush + move + output + clear);
    return true;
  }
  enableMouse() {
    this._useMouse = true;
    this.lib.enableMouse(this.rendererPtr, this.enableMouseMovement);
  }
  disableMouse() {
    this._useMouse = false;
    this.setCapturedRenderable(undefined);
    this.stdinParser?.resetMouseState();
    this.lib.disableMouse(this.rendererPtr);
  }
  enableKittyKeyboard(flags = 3) {
    this.lib.enableKittyKeyboard(this.rendererPtr, flags);
    this.updateStdinParserProtocolContext({ kittyKeyboardEnabled: true });
  }
  disableKittyKeyboard() {
    this.lib.disableKittyKeyboard(this.rendererPtr);
    this.updateStdinParserProtocolContext({ kittyKeyboardEnabled: false }, true);
  }
  set useThread(useThread) {
    this._useThread = useThread;
    this.lib.setUseThread(this.rendererPtr, useThread);
  }
  async setupTerminal() {
    if (this._terminalIsSetup)
      return;
    this._terminalIsSetup = true;
    const startupCursorCprActive = this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout";
    this.updateStdinParserProtocolContext({
      privateCapabilityRepliesActive: true,
      explicitWidthCprActive: true,
      startupCursorCprActive
    });
    this.startKittyTransportPolling();
    this.lib.setupTerminal(this.rendererPtr, this._screenMode === "alternate-screen");
    this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
    if (this.debugOverlay.enabled) {
      this.lib.setDebugOverlay(this.rendererPtr, true, this.debugOverlay.corner);
      if (!this.memorySnapshotInterval) {
        this.memorySnapshotInterval = 3000;
        this.startMemorySnapshotTimer();
        this.automaticMemorySnapshot = true;
      }
    }
    this.capabilityTimeoutId = this.clock.setTimeout(() => {
      this.capabilityTimeoutId = null;
      this.clearSplitStartupCursorSeed();
      if (this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout") {
        this.requestRender();
      }
      this.removeInputHandler(this.capabilityHandler);
      this.updateStdinParserProtocolContext({
        privateCapabilityRepliesActive: false,
        explicitWidthCprActive: false,
        startupCursorCprActive: false
      }, true);
      this.resolveXtVersionWaiters();
    }, 5000);
    if (this._useMouse) {
      this.enableMouse();
    }
    if (this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout") {
      this.pendingSplitStartupCursorSeed = true;
      if (this.splitStartupSeedTimeoutId !== null) {
        this.clock.clearTimeout(this.splitStartupSeedTimeoutId);
      }
      this.splitStartupSeedTimeoutId = this.clock.setTimeout(() => {
        this.splitStartupSeedTimeoutId = null;
        if (!this.pendingSplitStartupCursorSeed) {
          return;
        }
        this.updateStdinParserProtocolContext({ startupCursorCprActive: false });
        if (this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout") {
          this.requestRender();
        }
        this.flushPendingSplitOutputBeforeTransition(false, { allowPassthrough: true });
      }, 120);
    }
    this.queryPixelResolution();
    if (this.shouldSyncNativePaletteState()) {
      this.refreshPalette();
    }
    if (this._feed?.isBackpressured()) {
      await this._feed.idle();
    }
  }
  stdinListener = ((chunk) => {
    const data = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
    if (!this.stdinParser)
      return;
    if (this.stdinLogPath) {
      appendFileSync(this.stdinLogPath, data);
    }
    try {
      this.stdinParser.push(data);
      this.drainStdinParser();
    } catch (error) {
      this.handleStdinParserFailure(error);
    }
  }).bind(this);
  addInputHandler(handler) {
    this.sequenceHandlers.push(handler);
  }
  prependInputHandler(handler) {
    this.sequenceHandlers.unshift(handler);
  }
  removeInputHandler(handler) {
    this.sequenceHandlers = this.sequenceHandlers.filter((candidate) => candidate !== handler);
  }
  updateStdinParserProtocolContext(patch, drain = false) {
    if (!this.stdinParser)
      return;
    this.stdinParser.updateProtocolContext(patch);
    if (drain)
      this.drainStdinParser();
  }
  subscribeOsc(handler) {
    this.oscSubscribers.add(handler);
    return () => {
      this.oscSubscribers.delete(handler);
    };
  }
  processCapabilitySequence(sequence, hasCursorReport) {
    const hasStandardCapabilitySignature = isCapabilityResponse(sequence);
    const shouldProcessAsCapability = hasStandardCapabilitySignature || hasCursorReport && this.capabilityTimeoutId !== null;
    if (!shouldProcessAsCapability) {
      return false;
    }
    this.lib.processCapabilityResponse(this.rendererPtr, sequence);
    this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
    if (this._capabilities?.terminal?.from_xtversion) {
      this.resolveXtVersionWaiters();
    }
    if (hasStandardCapabilitySignature) {
      this.forceFullRepaintRequested = true;
      this.requestRender();
    }
    this.emit("capabilities" /* CAPABILITIES */, this._capabilities);
    const hadPendingSplitStartupCursorSeed = this.pendingSplitStartupCursorSeed;
    if (hadPendingSplitStartupCursorSeed && hasCursorReport && this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout") {
      this.resetSplitScrollback(this.getSplitCursorSeedRows());
      this.clearPendingSplitFooterTransition();
      this.clearSplitStartupCursorSeed();
      this.updateStdinParserProtocolContext({ startupCursorCprActive: false });
      this.requestRender();
      if (this.pendingExternalOutputMode === "passthrough") {
        this.flushPendingSplitOutputBeforeTransition();
      }
    }
    const consumeStartupCursorReport = hadPendingSplitStartupCursorSeed && hasCursorReport && this.splitStartupSeedTimeoutId !== null;
    return hasStandardCapabilitySignature || consumeStartupCursorReport;
  }
  capabilityHandler = ((sequence) => {
    return this.processCapabilitySequence(sequence, false);
  }).bind(this);
  focusHandler = ((sequence) => {
    if (sequence === "\x1B[I") {
      if (this.shouldRestoreModesOnNextFocus) {
        this.lib.restoreTerminalModes(this.rendererPtr);
        this.shouldRestoreModesOnNextFocus = false;
      }
      if (this._terminalFocusState !== true) {
        this._terminalFocusState = true;
        this.emit("focus" /* FOCUS */);
      }
      return true;
    }
    if (sequence === "\x1B[O") {
      this.shouldRestoreModesOnNextFocus = true;
      if (this._terminalFocusState !== false) {
        this._terminalFocusState = false;
        this.emit("blur" /* BLUR */);
      }
      return true;
    }
    return false;
  }).bind(this);
  dispatchSequenceHandlers(sequence) {
    if (this._debugModeEnabled) {
      this._debugInputs.push({
        timestamp: new Date().toISOString(),
        sequence
      });
    }
    for (const handler of this.sequenceHandlers) {
      if (handler(sequence)) {
        return true;
      }
    }
    return false;
  }
  drainStdinParser() {
    if (!this.stdinParser)
      return;
    this.stdinParser.drain((event) => {
      this.handleStdinEvent(event);
    });
  }
  handleStdinEvent(event) {
    if (event.type === "response" && event.sequence.startsWith("\x1B_G")) {
      const result = this.lib.processKittyImageReply(this.rendererPtr, event.sequence);
      if (result !== 0) {
        if (result === 2)
          this.requestRender();
        return;
      }
    }
    if (this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
      if (event.type === "response" && isPixelResolutionResponse(event.sequence)) {
        this.dispatchSequenceHandlers(event.sequence);
      }
      return;
    }
    switch (event.type) {
      case "key":
        if (this.dispatchSequenceHandlers(event.raw)) {
          return;
        }
        this._keyHandler.processParsedKey(event.key);
        return;
      case "mouse":
        if (this._useMouse && this.processSingleMouseEvent(event.event)) {
          return;
        }
        this.dispatchSequenceHandlers(event.raw);
        return;
      case "paste":
        this._keyHandler.processPaste(event.bytes, event.metadata);
        return;
      case "response":
        if (event.protocol === "osc") {
          for (const subscriber of this.oscSubscribers) {
            subscriber(event.sequence);
          }
        }
        if (event.protocol === "cpr" && this.processCapabilitySequence(event.sequence, true)) {
          return;
        }
        this.dispatchSequenceHandlers(event.sequence);
        return;
    }
  }
  handleStdinParserFailure(error) {
    if (!this.hasLoggedStdinParserError) {
      this.hasLoggedStdinParserError = true;
      if (true) {
        console.error("[stdin-parser-error] parser failure, resetting parser", error);
      }
    }
    try {
      this.stdinParser?.reset();
    } catch (resetError) {
      console.error("stdin parser reset failed after parser error", resetError);
    }
  }
  setupInput() {
    if (this.stdinLogPath) {
      writeFileSync(this.stdinLogPath, Buffer.alloc(0), { mode: 384 });
    }
    for (const handler of this.prependedInputHandlers) {
      this.addInputHandler(handler);
    }
    this.addInputHandler((sequence) => {
      if (isPixelResolutionResponse(sequence) && this.waitingForPixelResolution) {
        this.waitingForPixelResolution = false;
        if (this.pixelResolutionRequeryPending) {
          this.updateStdinParserProtocolContext({ pixelResolutionQueryActive: false });
          this.queryPixelResolution();
          return true;
        }
        const resolution = parsePixelResolution(sequence);
        if (resolution) {
          this._resolution = resolution;
          this.requestRender();
        }
        this.updateStdinParserProtocolContext({ pixelResolutionQueryActive: false }, true);
        return true;
      }
      return false;
    });
    this.addInputHandler(this.capabilityHandler);
    this.addInputHandler(this.focusHandler);
    this.addInputHandler(this.themeModeHandler);
    if (this.stdin.setRawMode) {
      this.stdin.setRawMode(true);
    }
    this.stdin.on("data", this.stdinListener);
    this.stdin.resume();
    this.startTerminalKeepAlive();
  }
  dispatchMouseEvent(target, attributes) {
    const event = new MouseEvent(target, attributes);
    this.sendMouseEvent(target, event);
    if (this.autoFocus && event.type === "down" && event.button === 0 /* LEFT */ && !event.defaultPrevented) {
      let current = target;
      while (current) {
        if (current.focusable) {
          current.focus();
          break;
        }
        current = current.parent;
      }
    }
    return event;
  }
  sendMouseEvent(target, event) {
    try {
      target.processMouseEvent(event);
    } catch (error) {
      const handled = this.emit("handler:error" /* HANDLER_ERROR */, { error, event });
      if (!handled)
        console.error("Error in mouse handler:", error);
    }
  }
  processSingleMouseEvent(mouseEvent) {
    if (this._splitHeight > 0) {
      if (mouseEvent.y < this.renderOffset) {
        return false;
      }
      mouseEvent.y -= this.renderOffset;
    }
    this._latestPointer.x = mouseEvent.x;
    this._latestPointer.y = mouseEvent.y;
    this._hasPointer = true;
    this._lastPointerModifiers = mouseEvent.modifiers;
    if (this._console.visible) {
      const consoleBounds = this._console.bounds;
      if (mouseEvent.x >= consoleBounds.x && mouseEvent.x < consoleBounds.x + consoleBounds.width && mouseEvent.y >= consoleBounds.y && mouseEvent.y < consoleBounds.y + consoleBounds.height) {
        const event2 = new MouseEvent(null, mouseEvent);
        const handled = this._console.handleMouse(event2);
        if (handled)
          return true;
      }
    }
    if (mouseEvent.type === "scroll") {
      const maybeRenderableId2 = this.hitTest(mouseEvent.x, mouseEvent.y);
      const maybeRenderable2 = Renderable.renderablesByNumber.get(maybeRenderableId2);
      const fallbackTarget = this._currentFocusedRenderable && !this._currentFocusedRenderable.isDestroyed && this._currentFocusedRenderable.focused ? this._currentFocusedRenderable : null;
      const scrollTarget = maybeRenderable2 ?? fallbackTarget;
      if (scrollTarget) {
        const event2 = new MouseEvent(scrollTarget, mouseEvent);
        this.sendMouseEvent(scrollTarget, event2);
      }
      return true;
    }
    const maybeRenderableId = this.hitTest(mouseEvent.x, mouseEvent.y);
    const sameElement = maybeRenderableId === this.lastOverRenderableNum;
    this.lastOverRenderableNum = maybeRenderableId;
    const maybeRenderable = Renderable.renderablesByNumber.get(maybeRenderableId);
    if (mouseEvent.type === "down" && mouseEvent.button === 0 /* LEFT */ && !this.currentSelection?.isDragging && !mouseEvent.modifiers.ctrl) {
      const canStartSelection = Boolean(maybeRenderable && maybeRenderable.selectable && !maybeRenderable.isDestroyed && maybeRenderable.shouldStartSelection(mouseEvent.x, mouseEvent.y));
      if (canStartSelection && maybeRenderable) {
        this.startSelection(maybeRenderable, mouseEvent.x, mouseEvent.y, this.nextClickBehavior(maybeRenderable, mouseEvent.x, mouseEvent.y));
        this.dispatchMouseEvent(maybeRenderable, mouseEvent);
        return true;
      }
    }
    if (mouseEvent.type === "drag" && this.currentSelection?.isDragging) {
      this.updateSelection(maybeRenderable, mouseEvent.x, mouseEvent.y);
      if (maybeRenderable) {
        const event2 = new MouseEvent(maybeRenderable, {
          ...mouseEvent,
          isDragging: true
        });
        this.sendMouseEvent(maybeRenderable, event2);
      }
      return true;
    }
    if (mouseEvent.type === "up" && mouseEvent.button === 0 /* LEFT */ && this.currentSelection?.isDragging) {
      if (maybeRenderable) {
        const event2 = new MouseEvent(maybeRenderable, {
          ...mouseEvent,
          isDragging: true
        });
        this.sendMouseEvent(maybeRenderable, event2);
      }
      this.finishSelection();
      return true;
    }
    if (mouseEvent.type === "down" && mouseEvent.button === 0 /* LEFT */ && this.currentSelection) {
      if (mouseEvent.modifiers.ctrl) {
        this.currentSelection.isDragging = true;
        this.updateSelection(maybeRenderable, mouseEvent.x, mouseEvent.y);
        return true;
      }
    }
    if (!sameElement && (mouseEvent.type === "drag" || mouseEvent.type === "move")) {
      if (this.lastOverRenderable && this.lastOverRenderable !== this.capturedRenderable && !this.lastOverRenderable.isDestroyed) {
        const event2 = new MouseEvent(this.lastOverRenderable, {
          ...mouseEvent,
          type: "out"
        });
        this.sendMouseEvent(this.lastOverRenderable, event2);
      }
      this.lastOverRenderable = maybeRenderable;
      if (maybeRenderable) {
        const event2 = new MouseEvent(maybeRenderable, {
          ...mouseEvent,
          type: "over",
          source: this.capturedRenderable
        });
        this.sendMouseEvent(maybeRenderable, event2);
      }
    }
    if (this.capturedRenderable && mouseEvent.type !== "up") {
      const event2 = new MouseEvent(this.capturedRenderable, mouseEvent);
      this.sendMouseEvent(this.capturedRenderable, event2);
      return true;
    }
    if (this.capturedRenderable && mouseEvent.type === "up") {
      const event2 = new MouseEvent(this.capturedRenderable, {
        ...mouseEvent,
        type: "drag-end"
      });
      this.sendMouseEvent(this.capturedRenderable, event2);
      this.sendMouseEvent(this.capturedRenderable, new MouseEvent(this.capturedRenderable, mouseEvent));
      if (maybeRenderable) {
        const event3 = new MouseEvent(maybeRenderable, {
          ...mouseEvent,
          type: "drop",
          source: this.capturedRenderable
        });
        this.sendMouseEvent(maybeRenderable, event3);
      }
      this.lastOverRenderable = this.capturedRenderable;
      this.lastOverRenderableNum = this.capturedRenderable.num;
      this.setCapturedRenderable(undefined);
      this.requestRender();
    }
    let event;
    if (maybeRenderable) {
      if (mouseEvent.type === "drag" && mouseEvent.button === 0 /* LEFT */) {
        this.setCapturedRenderable(maybeRenderable);
      } else {
        this.setCapturedRenderable(undefined);
      }
      event = this.dispatchMouseEvent(maybeRenderable, mouseEvent);
    } else {
      this.setCapturedRenderable(undefined);
      this.lastOverRenderable = undefined;
    }
    if (!event?.defaultPrevented && mouseEvent.type === "down" && mouseEvent.button === 0 /* LEFT */ && this.currentSelection) {
      this.clearSelection();
    }
    return true;
  }
  recheckHoverState() {
    if (this._isDestroyed || !this._hasPointer)
      return;
    if (this.capturedRenderable)
      return;
    const hitId = this.hitTest(this._latestPointer.x, this._latestPointer.y);
    const hitRenderable = Renderable.renderablesByNumber.get(hitId);
    const lastOver = this.lastOverRenderable;
    if (lastOver?.num === hitId) {
      this.lastOverRenderableNum = hitId;
      return;
    }
    const baseEvent = {
      type: "move",
      button: 0,
      x: this._latestPointer.x,
      y: this._latestPointer.y,
      modifiers: this._lastPointerModifiers
    };
    if (lastOver && !lastOver.isDestroyed) {
      const event = new MouseEvent(lastOver, { ...baseEvent, type: "out" });
      this.sendMouseEvent(lastOver, event);
    }
    this.lastOverRenderable = hitRenderable;
    this.lastOverRenderableNum = hitId;
    if (hitRenderable) {
      const event = new MouseEvent(hitRenderable, {
        ...baseEvent,
        type: "over"
      });
      this.sendMouseEvent(hitRenderable, event);
    }
  }
  setMousePointer(style) {
    this._currentMousePointerStyle = style;
    this.lib.setCursorStyleOptions(this.rendererPtr, { cursor: style });
  }
  hitTest(x, y) {
    return this.lib.checkHit(this.rendererPtr, x, y);
  }
  takeMemorySnapshot() {
    if (this._isDestroyed)
      return;
    const memoryUsage = process.memoryUsage();
    this.lastMemorySnapshot = {
      heapUsed: memoryUsage.heapUsed,
      heapTotal: memoryUsage.heapTotal,
      arrayBuffers: memoryUsage.arrayBuffers
    };
    this.lib.updateMemoryStats(this.rendererPtr, this.lastMemorySnapshot.heapUsed, this.lastMemorySnapshot.heapTotal, this.lastMemorySnapshot.arrayBuffers);
    this.emit("memory:snapshot" /* MEMORY_SNAPSHOT */, this.lastMemorySnapshot);
  }
  startMemorySnapshotTimer() {
    this.stopMemorySnapshotTimer();
    this.memorySnapshotTimer = this.clock.setInterval(() => {
      this.takeMemorySnapshot();
    }, this.memorySnapshotInterval);
  }
  stopMemorySnapshotTimer() {
    if (this.memorySnapshotTimer) {
      this.clock.clearInterval(this.memorySnapshotTimer);
      this.memorySnapshotTimer = null;
    }
  }
  setMemorySnapshotInterval(interval) {
    this.memorySnapshotInterval = interval;
    if (this._isRunning && interval > 0) {
      this.startMemorySnapshotTimer();
    } else if (interval <= 0 && this.memorySnapshotTimer) {
      this.clock.clearInterval(this.memorySnapshotTimer);
      this.memorySnapshotTimer = null;
    }
  }
  handleResize(width, height) {
    if (this._isDestroyed)
      return;
    if (this._splitHeight > 0) {
      this.processResize(width, height);
      return;
    }
    if (this.resizeTimeoutId !== null) {
      this.clock.clearTimeout(this.resizeTimeoutId);
      this.resizeTimeoutId = null;
    }
    this.resizeTimeoutId = this.clock.setTimeout(() => {
      this.resizeTimeoutId = null;
      this.processResize(width, height);
    }, this.resizeDebounceDelay);
  }
  queryPixelResolution() {
    this.pixelResolutionRequeryPending = true;
    if (this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */ || this.waitingForPixelResolution)
      return;
    this.pixelResolutionRequeryPending = false;
    this.waitingForPixelResolution = true;
    this.updateStdinParserProtocolContext({ pixelResolutionQueryActive: true });
    this.lib.queryPixelResolution(this.rendererPtr);
  }
  processResize(width, height) {
    if (width === this._terminalWidth && height === this._terminalHeight)
      return;
    if (this._terminalIsSetup && this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */ && !this.isSplitCursorSeedFrameBlocked()) {
      this.flushPendingSplitOutputBeforeTransition();
    }
    const pendingSplitFooterTransition = this.pendingSplitFooterTransition;
    const previousGeometry = calculateRenderGeometry(this._screenMode, this._terminalWidth, this._terminalHeight, this._footerHeight);
    const prevWidth = this._terminalWidth;
    const previousTerminalHeight = this._terminalHeight;
    const visiblePreviousSplitHeight = pendingSplitFooterTransition?.sourceHeight ?? previousGeometry.effectiveFooterHeight;
    this._terminalWidth = width;
    this._terminalHeight = height;
    this._resolution = null;
    this.queryPixelResolution();
    this.setCapturedRenderable(undefined);
    this.stdinParser?.resetMouseState();
    const nextGeometry = calculateRenderGeometry(this._screenMode, this._terminalWidth, this._terminalHeight, this._footerHeight);
    const splitFooterActive = this._screenMode === "split-footer";
    if (splitFooterActive) {
      let clearStart = null;
      if (width < prevWidth && visiblePreviousSplitHeight > 0) {
        clearStart = Math.max(previousTerminalHeight - visiblePreviousSplitHeight * 2, 1);
      }
      if (pendingSplitFooterTransition !== null) {
        clearStart = clearStart === null ? pendingSplitFooterTransition.sourceTopLine : Math.min(clearStart, pendingSplitFooterTransition.sourceTopLine);
      }
      if (clearStart !== null) {
        const flush = ANSI.moveCursorAndClear(clearStart, 1);
        this.writeOut(flush);
      }
      this.currentRenderBuffer.clear(this.backgroundColor);
    }
    this.clearPendingSplitFooterTransition();
    this._splitHeight = nextGeometry.effectiveFooterHeight;
    this.width = nextGeometry.renderWidth;
    this.height = nextGeometry.renderHeight;
    this.lib.resizeRenderer(this.rendererPtr, this.width, this.height);
    if (this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout") {
      this.syncSplitScrollback();
    } else {
      this.syncSplitFooterState();
    }
    this.nextRenderBuffer = this.lib.getNextBuffer(this.rendererPtr);
    this.currentRenderBuffer = this.lib.getCurrentBuffer(this.rendererPtr);
    this._console.resize(this.width, this.height);
    this.root.resize(this.width, this.height);
    this.emit("resize" /* RESIZE */, this.width, this.height);
    this.requestRender();
  }
  resize(width, height) {
    if (this._isDestroyed)
      return;
    this.processResize(width, height);
  }
  setBackgroundColor(color) {
    const parsedColor = parseColor(color);
    this.lib.setBackgroundColor(this.rendererPtr, parsedColor);
    this.backgroundColor = parsedColor;
    this.nextRenderBuffer.clear(parsedColor);
    this.requestRender();
  }
  toggleDebugOverlay() {
    const willBeEnabled = !this.debugOverlay.enabled;
    if (willBeEnabled && !this.memorySnapshotInterval) {
      this.memorySnapshotInterval = 3000;
      this.startMemorySnapshotTimer();
      this.automaticMemorySnapshot = true;
    } else if (!willBeEnabled && this.automaticMemorySnapshot) {
      this.stopMemorySnapshotTimer();
      this.memorySnapshotInterval = 0;
      this.automaticMemorySnapshot = false;
    }
    this.debugOverlay.enabled = !this.debugOverlay.enabled;
    this.lib.setDebugOverlay(this.rendererPtr, this.debugOverlay.enabled, this.debugOverlay.corner);
    this.emit("debugOverlay:toggle" /* DEBUG_OVERLAY_TOGGLE */, this.debugOverlay.enabled);
    this.requestRender();
  }
  configureDebugOverlay(options) {
    this.debugOverlay.enabled = options.enabled ?? this.debugOverlay.enabled;
    this.debugOverlay.corner = options.corner ?? this.debugOverlay.corner;
    this.lib.setDebugOverlay(this.rendererPtr, this.debugOverlay.enabled, this.debugOverlay.corner);
    this.requestRender();
  }
  setTerminalTitle(title) {
    this.lib.setTerminalTitle(this.rendererPtr, title);
  }
  resetTerminalBgColor() {
    this.writeOut("\x1B]111\x07");
  }
  copyToClipboardOSC52(text, target) {
    return this.clipboard.copyToClipboardOSC52(text, target);
  }
  clearClipboardOSC52(target) {
    return this.clipboard.clearClipboardOSC52(target);
  }
  isOsc52Supported() {
    return this._capabilities ? this._capabilities.osc52_support !== "unsupported" : this.clipboard.isOsc52Supported();
  }
  dumpHitGrid() {
    this.lib.dumpHitGrid(this.rendererPtr);
  }
  dumpBuffers(timestamp) {
    this.lib.dumpBuffers(this.rendererPtr, timestamp);
  }
  dumpOutputBuffer(timestamp) {
    this.lib.dumpOutputBuffer(this.rendererPtr, timestamp);
  }
  static setCursorPosition(renderer, x, y, visible = true) {
    const lib = resolveRenderLib();
    lib.setCursorPosition(renderer.rendererPtr, x, y, visible);
  }
  static setCursorStyle(renderer, options) {
    const lib = resolveRenderLib();
    lib.setCursorStyleOptions(renderer.rendererPtr, options);
    if (options.cursor !== undefined) {
      renderer._currentMousePointerStyle = options.cursor;
    }
  }
  static setCursorColor(renderer, color) {
    const lib = resolveRenderLib();
    lib.setCursorColor(renderer.rendererPtr, color);
  }
  setCursorPosition(x, y, visible = true) {
    this.lib.setCursorPosition(this.rendererPtr, x, y, visible);
  }
  setCursorStyle(options) {
    this.lib.setCursorStyleOptions(this.rendererPtr, options);
    if (options.cursor !== undefined) {
      this._currentMousePointerStyle = options.cursor;
    }
  }
  setCursorColor(color) {
    this.lib.setCursorColor(this.rendererPtr, color);
  }
  getCursorState() {
    return this.lib.getCursorState(this.rendererPtr);
  }
  addPostProcessFn(processFn) {
    this.postProcessFns.push(processFn);
  }
  removePostProcessFn(processFn) {
    this.postProcessFns = this.postProcessFns.filter((fn) => fn !== processFn);
  }
  clearPostProcessFns() {
    this.postProcessFns = [];
  }
  setFrameCallback(callback) {
    this.frameCallbacks.push(callback);
  }
  removeFrameCallback(callback) {
    this.frameCallbacks = this.frameCallbacks.filter((cb) => cb !== callback);
  }
  clearFrameCallbacks() {
    this.frameCallbacks = [];
  }
  requestLive() {
    this.liveRequestCounter++;
    if (this._controlState === "idle" /* IDLE */ && this.liveRequestCounter > 0) {
      this._controlState = "auto_started" /* AUTO_STARTED */;
      this.internalStart();
    } else if (this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */ && this._previousControlState === "idle" /* IDLE */) {
      this._previousControlState = "auto_started" /* AUTO_STARTED */;
    }
  }
  dropLive() {
    if (this.liveRequestCounter === 0)
      return;
    this.liveRequestCounter--;
    if (this.liveRequestCounter === 0 && this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */ && this._previousControlState === "auto_started" /* AUTO_STARTED */) {
      this._previousControlState = "idle" /* IDLE */;
    }
    if (this._controlState === "auto_started" /* AUTO_STARTED */ && this.liveRequestCounter === 0) {
      this._controlState = "idle" /* IDLE */;
      this._isRunning = false;
      this.resolveIdleIfNeeded();
    }
  }
  start() {
    this._controlState = "explicit_started" /* EXPLICIT_STARTED */;
    this.internalStart();
  }
  auto() {
    this._controlState = this._isRunning ? "auto_started" /* AUTO_STARTED */ : "idle" /* IDLE */;
  }
  internalStart() {
    if (!this._isRunning && !this._isDestroyed) {
      this._isRunning = true;
      this.updateScheduled = false;
      this.updateGeneration++;
      if (this.memorySnapshotInterval > 0) {
        this.startMemorySnapshotTimer();
      }
      this.startRenderLoop();
    }
  }
  pause() {
    this._controlState = "explicit_paused" /* EXPLICIT_PAUSED */;
    this.internalPause();
  }
  suspend() {
    this._previousControlState = this._controlState;
    this._controlState = "explicit_suspended" /* EXPLICIT_SUSPENDED */;
    this.updateScheduled = false;
    this.updateGeneration++;
    this.internalPause();
    if (this._terminalIsSetup) {
      this.clearSplitStartupCursorSeed();
      this.flushPendingSplitOutputBeforeTransition(true, { allowSuspended: true });
      this.suspendedNonAltSurfacePreserved = this._screenMode !== "alternate-screen" && this.renderOffset > 0;
    } else {
      this.suspendedNonAltSurfacePreserved = false;
    }
    this._suspendedMouseEnabled = this._useMouse;
    this.disableMouse();
    this.removeExitListeners();
    this.updateStdinParserProtocolContext({
      privateCapabilityRepliesActive: false,
      pixelResolutionQueryActive: this.waitingForPixelResolution,
      explicitWidthCprActive: false,
      startupCursorCprActive: false
    });
    if (this.stdinParser?.hasPendingPixelResolutionResponse())
      this.stdinParser.pausePendingTimeout();
    else
      this.stdinParser?.reset();
    this.stdin.removeListener("data", this.stdinListener);
    this.stopTerminalKeepAlive();
    this.themeModeState.cancelRefresh();
    this.lib.suspendRenderer(this.rendererPtr);
    if (this.stdin.setRawMode) {
      this.stdin.setRawMode(false);
    }
    this.stdin.pause();
  }
  resume() {
    if (this.stdin.setRawMode) {
      this.stdin.setRawMode(true);
    }
    let drained;
    while ((drained = this.stdin.read()) !== null)
      this.stdinListener(drained);
    if (this.stdinParser?.hasPendingPixelResolutionResponse())
      this.stdinParser.pausePendingTimeout();
    else
      this.stdinParser?.reset();
    this.stdin.on("data", this.stdinListener);
    this.stdin.resume();
    this.startTerminalKeepAlive();
    this.addExitListeners();
    const resumePreservedNonAltSurface = this.pendingSuspendedTerminalSetup && this._screenMode !== "alternate-screen" && this.suspendedNonAltSurfacePreserved && this.renderOffset > 0;
    if (this.pendingSuspendedTerminalSetup) {
      this.pendingSuspendedTerminalSetup = false;
      if (resumePreservedNonAltSurface) {
        this.lib.resumeRenderer(this.rendererPtr);
      } else {
        this.lib.setupTerminal(this.rendererPtr, this._screenMode === "alternate-screen");
      }
    } else {
      this.lib.resumeRenderer(this.rendererPtr);
    }
    this.suspendedNonAltSurfacePreserved = false;
    this.flushPendingSplitOutputBeforeTransition(false, { allowSuspended: true, allowPassthrough: true });
    if (this._screenMode === "split-footer" && this._splitHeight > 0) {
      this.syncSplitFooterState();
    }
    if (this._suspendedMouseEnabled) {
      this.enableMouse();
    }
    this.forceFullRepaintRequested = true;
    this._controlState = this._previousControlState;
    if (this.pixelResolutionRequeryPending)
      this.queryPixelResolution();
    this.stdinParser?.resumePendingTimeout();
    if (this._previousControlState === "auto_started" /* AUTO_STARTED */ || this._previousControlState === "explicit_started" /* EXPLICIT_STARTED */) {
      this.internalStart();
    } else {
      this.requestRender();
    }
  }
  internalPause() {
    this._isRunning = false;
    this.cancelRenderAfterFeedIdle();
    if (this.renderTimeout) {
      this.clock.clearTimeout(this.renderTimeout);
      this.renderTimeout = null;
    }
    if (!this.rendering) {
      this.resolveIdleIfNeeded();
    }
  }
  stop() {
    this._controlState = "explicit_stopped" /* EXPLICIT_STOPPED */;
    this.internalStop();
  }
  internalStop() {
    this.updateScheduled = false;
    this.updateGeneration++;
    this.immediateRerenderRequested = false;
    if (this.memorySnapshotTimer) {
      this.clock.clearInterval(this.memorySnapshotTimer);
      this.memorySnapshotTimer = null;
    }
    this.internalPause();
  }
  destroy() {
    if (this._isDestroyed)
      return;
    this._isDestroyed = true;
    this._destroyPending = true;
    this._palettePublishGeneration++;
    if (this.rendering) {
      this.prepareDestroyDuringRender();
      return;
    }
    this.finalizeDestroy();
  }
  cleanupBeforeDestroy() {
    if (this._destroyCleanupPrepared)
      return;
    this._destroyCleanupPrepared = true;
    this.cancelRenderAfterFeedIdle();
    if (this.kittyTransportTimer !== null) {
      this.clock.clearInterval(this.kittyTransportTimer);
      this.kittyTransportTimer = null;
      this.stdout.off("error", this.kittyOutputErrorHandler);
      this.lib.cancelKittyImageTransport(this.rendererPtr, false);
    }
    if (this._usesProcessStdout) {
      process.removeListener("SIGWINCH", this.sigwinchHandler);
    }
    process.removeListener("uncaughtException", this.handleError);
    process.removeListener("unhandledRejection", this.handleError);
    process.removeListener("warning", this.warningHandler);
    this.removeExitListeners();
    if (this.resizeTimeoutId !== null) {
      this.clock.clearTimeout(this.resizeTimeoutId);
      this.resizeTimeoutId = null;
    }
    if (this.capabilityTimeoutId !== null) {
      this.clock.clearTimeout(this.capabilityTimeoutId);
      this.capabilityTimeoutId = null;
    }
    this.clearSplitStartupCursorSeed();
    if (this.memorySnapshotTimer) {
      this.clock.clearInterval(this.memorySnapshotTimer);
      this.memorySnapshotTimer = null;
    }
    if (this.renderTimeout) {
      this.clock.clearTimeout(this.renderTimeout);
      this.renderTimeout = null;
    }
    this.themeModeState.cancelRefresh();
    this._isRunning = false;
    this.waitingForPixelResolution = false;
    this.pixelResolutionRequeryPending = false;
    this.updateStdinParserProtocolContext({
      privateCapabilityRepliesActive: false,
      pixelResolutionQueryActive: false,
      explicitWidthCprActive: false,
      startupCursorCprActive: false
    }, true);
    if (this.stdin === process.stdin && this._usesProcessStdout)
      this.disableMouse();
    this._useMouse = false;
    this.setCapturedRenderable(undefined);
    this.stdin.removeListener("data", this.stdinListener);
    this.stopTerminalKeepAlive();
    if (this.stdin.setRawMode) {
      try {
        this.stdin.setRawMode(false);
      } catch (e) {
        console.error("Error disabling raw mode during destroy:", e);
      }
    }
    try {
      this.stdin.pause();
    } catch (e) {
      console.error("Error pausing stdin during destroy:", e);
    }
    if (this._feed !== null && this._splitHeight > 0 && !this._terminalIsSetup) {
      this.flushPendingSplitOutputBeforeTransition(false, { allowSuspended: true, allowUnsetup: true });
    }
    this.externalOutputMode = "passthrough";
    if (this._splitHeight > 0) {
      this.flushStdoutCache(this._splitHeight, true);
    }
  }
  prepareDestroyDuringRender() {
    this.cleanupBeforeDestroy();
    this.lib.suspendRenderer(this.rendererPtr);
  }
  finalizeDestroy() {
    if (this._destroyFinalized)
      return;
    this._destroyFinalized = true;
    this._destroyPending = false;
    this.cleanupBeforeDestroy();
    if (this._paletteDetector) {
      this._paletteDetector.cleanup();
      this._paletteDetector = null;
    }
    this._paletteCache.clear();
    this._paletteDetectionPromise = null;
    this._paletteDetectionSize = 0;
    this._nativePaletteSignature = null;
    this._emittedPaletteSignature = null;
    this._paletteEpoch = 0;
    this.resolveXtVersionWaiters();
    this.themeModeState.dispose();
    this.emit("destroy" /* DESTROY */);
    try {
      this.root.destroyRecursively();
    } catch (e) {
      console.error("Error destroying root renderable:", e instanceof Error ? e.stack : String(e));
    }
    this.stdinParser?.destroy();
    this.stdinParser = null;
    this.oscSubscribers.clear();
    this._console.destroy();
    if (this._splitHeight > 0 && this._terminalIsSetup && this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
      this.flushPendingSplitOutputBeforeTransition(true);
      this.renderOffset = 0;
      if (this.clearOnShutdown) {
        this.lib.setRenderOffset(this.rendererPtr, 0);
      }
    }
    this._externalOutputMode = "passthrough";
    this.pendingExternalOutputMode = null;
    this.stdout.write = this.realStdoutWrite;
    this.externalOutputQueue.clear();
    if (this._feed) {
      try {
        this._feed.drainAll();
      } catch (e) {
        console.error("Error draining NativeSpanFeed during destroy:", e);
      }
    }
    const discardInput = this._terminalIsSetup && this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */;
    try {
      this.lib.destroyRenderer(this.rendererPtr, discardInput && this.stdin === process.stdin);
    } catch (e) {
      console.error("Error in lib.destroyRenderer during destroy:", e);
    }
    if (discardInput) {
      const bufferedInput = this.stdin.readableLength;
      if (bufferedInput > 0)
        this.stdin.read(bufferedInput);
    }
    rendererTracker.renderers.delete(this);
    if (rendererTracker.renderers.size === 0) {
      destroyTreeSitterClient().catch((error) => {
        console.error("Failed to destroy tree-sitter client:", error);
      });
    }
    if (this._feed) {
      try {
        this._feed.drainAll();
      } catch (e) {
        console.error("Error draining NativeSpanFeed shutdown frames:", e);
      }
      this._detachFeed?.();
      this._detachFeed = null;
      this._detachFeedError?.();
      this._detachFeedError = null;
      this._feed.close();
      this._feed = null;
    }
    if (this._streamLeaseAcquired) {
      if (rendererTracker.streamOwners.get(this.stdin) === this)
        rendererTracker.streamOwners.delete(this.stdin);
      if (rendererTracker.streamOwners.get(this.stdout) === this)
        rendererTracker.streamOwners.delete(this.stdout);
      this._streamLeaseAcquired = false;
    }
    if (this._onDestroy) {
      try {
        this._onDestroy();
      } catch (e) {
        console.error("Error in onDestroy callback:", e instanceof Error ? e.stack : String(e));
      }
    }
    this.resolveIdleIfNeeded();
  }
  startRenderLoop() {
    if (!this._isRunning)
      return;
    this.lastTime = this.normalizeClockTime(this.clock.now(), 0);
    this.frameCount = 0;
    this.lastFpsTime = this.lastTime;
    this.currentFps = 0;
    this.renderStats.fps = 0;
    if (this.feedIdleRenderScheduled)
      return;
    this.loop();
  }
  async loop() {
    if (this.rendering || this._isDestroyed)
      return;
    const startedWhileRunning = this._isRunning;
    if (this.renderTimeout) {
      this.clock.clearTimeout(this.renderTimeout);
      this.renderTimeout = null;
    }
    this.rendering = true;
    let renderFailed = false;
    try {
      if (this._feed?.isBackpressured()) {
        this.handleNativeRenderRejection(NATIVE_RENDER_STATUS_SKIPPED);
        this.immediateRerenderRequested = false;
        return;
      }
      this._frameId++;
      const now = this.normalizeClockTime(this.clock.now(), this.lastTime);
      const elapsed = this.getElapsedMs(now, this.lastTime);
      const deltaTime = elapsed;
      this.lastTime = now;
      this.renderStats.frameCount++;
      const overallStart = performance.now();
      const frameRequests = Array.from(this.animationRequest.values());
      this.animationRequest.clear();
      const animationRequestStart = performance.now();
      for (const callback of frameRequests) {
        callback(deltaTime);
        this.dropLive();
      }
      const animationRequestEnd = performance.now();
      const animationRequestTime = animationRequestEnd - animationRequestStart;
      const start = performance.now();
      for (const frameCallback of this.frameCallbacks) {
        try {
          await frameCallback(deltaTime);
        } catch (error) {
          console.error("Error in frame callback:", error);
        }
      }
      const end = performance.now();
      this.renderStats.frameCallbackTime = end - start;
      this.root.render(this.nextRenderBuffer, deltaTime);
      for (const postProcessFn of this.postProcessFns) {
        postProcessFn(this.nextRenderBuffer, deltaTime);
      }
      this._console.renderToBuffer(this.nextRenderBuffer);
      if (!this._isDestroyed) {
        const nativeStatus = this.renderNative() ?? "rendered";
        if (nativeStatus === "rendered")
          this.frameCount++;
        if (this.getElapsedMs(now, this.lastFpsTime) >= 1000) {
          this.currentFps = this.frameCount;
          this.frameCount = 0;
          this.lastFpsTime = now;
        }
        this.renderStats.fps = this.currentFps;
        if (nativeStatus === "rendered") {
          if (this._useMouse && this.lib.getHitGridDirty(this.rendererPtr)) {
            this.recheckHoverState();
          }
          const overallFrameTime = performance.now() - overallStart;
          this.lib.updateStats(this.rendererPtr, overallFrameTime, this.renderStats.fps, this.renderStats.frameCallbackTime);
          if (this.listenerCount("frame" /* FRAME */) > 0) {
            this.emit("frame" /* FRAME */, {
              frameId: this.frameId
            });
          }
          if (this.gatherStats) {
            this.collectStatSample(overallFrameTime);
          }
          if (this._isRunning || this.immediateRerenderRequested) {
            const targetFrameTime = this.immediateRerenderRequested ? this.minTargetFrameTime : this.targetFrameTime;
            const delay = Math.max(1, targetFrameTime - Math.floor(overallFrameTime));
            this.immediateRerenderRequested = false;
            this.renderTimeout = this.clock.setTimeout(() => {
              this.renderTimeout = null;
              this.loop();
            }, delay);
          } else {
            this.clock.clearTimeout(this.renderTimeout);
            this.renderTimeout = null;
          }
        } else if (nativeStatus === "blocked") {
          const overallFrameTime = performance.now() - overallStart;
          if (this._isRunning || this.immediateRerenderRequested) {
            const targetFrameTime = this.immediateRerenderRequested ? this.minTargetFrameTime : this.targetFrameTime;
            const delay = Math.max(1, targetFrameTime - Math.floor(overallFrameTime));
            this.immediateRerenderRequested = false;
            this.renderTimeout = this.clock.setTimeout(() => {
              this.renderTimeout = null;
              this.loop();
            }, delay);
          } else {
            this.clock.clearTimeout(this.renderTimeout);
            this.renderTimeout = null;
          }
        } else if (nativeStatus === "backpressured") {
          if (!startedWhileRunning || this._isRunning || this.immediateRerenderRequested || this._controlState === "idle" /* IDLE */) {
            this.scheduleRenderAfterBackpressure();
          }
        } else if (nativeStatus === "retryable-skip") {
          this.immediateRerenderRequested = false;
          this.renderTimeout = null;
        } else if (nativeStatus === "failed") {
          this.immediateRerenderRequested = false;
          this.renderTimeout = null;
        }
      }
    } catch (error) {
      renderFailed = true;
      const renderError = error instanceof Error ? error : new Error(String(error));
      const event = { error: renderError, renderable: this.root.takeCurrentRenderable() };
      const handled = this.emit("render:error" /* RENDER_ERROR */, event);
      if (!handled)
        this.handleError(renderError);
    } finally {
      this.rendering = false;
      if (this._destroyPending) {
        this.finalizeDestroy();
      }
      if (renderFailed && (this._isRunning || this.immediateRerenderRequested) && !this._isDestroyed) {
        this.immediateRerenderRequested = false;
        this.scheduleRenderTimer();
      }
      this.resolveIdleIfNeeded();
    }
  }
  intermediateRender() {
    this.immediateRerenderRequested = true;
    this.loop();
  }
  renderNative() {
    if (this.renderingNative) {
      console.error("Rendering called concurrently");
      throw new Error("Rendering called concurrently");
    }
    this.renderingNative = true;
    try {
      if (this.isSplitCursorSeedFrameBlocked()) {
        return "blocked";
      }
      if (this._splitHeight > 0 && this._externalOutputMode === "capture-stdout") {
        const forceSplitRepaint = this.forceFullRepaintRequested;
        const status = this.flushPendingSplitCommits(forceSplitRepaint, this.pendingExternalOutputMode === "passthrough");
        if (status === "backpressured") {
          return "backpressured";
        }
        if (status === "failed") {
          return "failed";
        }
        this.forceFullRepaintRequested = false;
        this.pendingSplitFooterTransition = null;
        return "rendered";
      }
      const force = this.forceFullRepaintRequested;
      const nativeStatus = this.lib.render(this.rendererPtr, force);
      if (nativeStatus === NATIVE_RENDER_STATUS_SKIPPED || nativeStatus === NATIVE_RENDER_STATUS_FAILED) {
        return this.handleNativeRenderRejection(nativeStatus);
      }
      this.forceFullRepaintRequested = false;
      this.pendingSplitFooterTransition = null;
      return "rendered";
    } finally {
      this.renderingNative = false;
    }
  }
  collectStatSample(frameTime) {
    this.frameTimes.push(frameTime);
    if (this.frameTimes.length > this.maxStatSamples) {
      this.frameTimes.shift();
    }
  }
  getNativeStats() {
    return this.lib.getRenderStats(this.rendererPtr);
  }
  getStats() {
    const nativeStats = this.getNativeStats();
    const frameTimes = [...this.frameTimes];
    const sum = frameTimes.reduce((acc, time) => acc + time, 0);
    const avg = frameTimes.length ? sum / frameTimes.length : 0;
    const min = frameTimes.length ? Math.min(...frameTimes) : 0;
    const max = frameTimes.length ? Math.max(...frameTimes) : 0;
    return {
      ...nativeStats,
      fps: this.renderStats.fps,
      frameCount: this.renderStats.frameCount,
      frameTimes,
      averageFrameTime: avg,
      minFrameTime: min,
      maxFrameTime: max,
      frameCallbackTime: this.renderStats.frameCallbackTime
    };
  }
  resetStats() {
    this.frameTimes = [];
    this.renderStats.frameCount = 0;
  }
  setGatherStats(enabled) {
    this.gatherStats = enabled;
    if (!enabled) {
      this.frameTimes = [];
    }
  }
  getSelection() {
    return this.currentSelection;
  }
  get hasSelection() {
    return !!this.currentSelection;
  }
  getSelectionContainer() {
    return this.selectionContainers.length > 0 ? this.selectionContainers[this.selectionContainers.length - 1] : null;
  }
  clearSelection() {
    this.clearSelectionState();
    this.lastClick = null;
  }
  clearSelectionState() {
    if (this.currentSelection) {
      for (const renderable of this.currentSelection.touchedRenderables) {
        if (renderable.selectable && !renderable.isDestroyed) {
          renderable.onSelectionChanged(null);
        }
      }
      this.currentSelection = null;
    }
    this.selectionContainers = [];
  }
  startSelection(renderable, x, y, behavior = "cell") {
    if (!renderable.selectable)
      return;
    this.clearSelectionState();
    this.selectionContainers.push(renderable.parent || this.root);
    this.currentSelection = new Selection(renderable, { x, y }, { x, y }, behavior);
    this.currentSelection.isStart = true;
    this.notifySelectablesOfSelectionChange();
  }
  nextClickBehavior(renderable, x, y) {
    const now = this.clock.now();
    const last = this.lastClick;
    const continued = last !== null && renderable.num === last.renderableId && now - last.time <= CLICK_REPEAT_INTERVAL_MS && Math.max(Math.abs(x - last.x), Math.abs(y - last.y)) <= 1;
    const count = continued ? Math.min(last.count + 1, 3) : 1;
    this.lastClick = { count, time: now, x, y, renderableId: renderable.num };
    return count === 1 ? "cell" : count === 2 ? "word" : "line";
  }
  updateSelection(currentRenderable, x, y, options) {
    if (this.currentSelection) {
      this.currentSelection.isStart = false;
      this.currentSelection.focus = { x, y };
      if (options?.finishDragging) {
        this.currentSelection.isDragging = false;
      }
      if (this.selectionContainers.length > 0) {
        const currentContainer = this.selectionContainers[this.selectionContainers.length - 1];
        if (!currentRenderable || !this.isWithinContainer(currentRenderable, currentContainer)) {
          const parentContainer = currentContainer.parent || this.root;
          this.selectionContainers.push(parentContainer);
        } else if (currentRenderable && this.selectionContainers.length > 1) {
          let containerIndex = this.selectionContainers.indexOf(currentRenderable);
          if (containerIndex === -1) {
            const immediateParent = currentRenderable.parent || this.root;
            containerIndex = this.selectionContainers.indexOf(immediateParent);
          }
          if (containerIndex !== -1 && containerIndex < this.selectionContainers.length - 1) {
            this.selectionContainers = this.selectionContainers.slice(0, containerIndex + 1);
          }
        }
      }
      this.notifySelectablesOfSelectionChange();
    }
  }
  requestSelectionUpdate() {
    if (this.currentSelection?.isDragging) {
      const pointer = this._latestPointer;
      const maybeRenderableId = this.hitTest(pointer.x, pointer.y);
      const maybeRenderable = Renderable.renderablesByNumber.get(maybeRenderableId);
      this.updateSelection(maybeRenderable, pointer.x, pointer.y);
    }
  }
  isWithinContainer(renderable, container) {
    let current = renderable;
    while (current) {
      if (current === container)
        return true;
      current = current.parent;
    }
    return false;
  }
  finishSelection() {
    if (this.currentSelection) {
      this.currentSelection.isDragging = false;
      this.emit("selection" /* SELECTION */, this.currentSelection);
      this.notifySelectablesOfSelectionChange();
    }
  }
  notifySelectablesOfSelectionChange() {
    const selectedRenderables = [];
    const touchedRenderables = [];
    const currentContainer = this.selectionContainers.length > 0 ? this.selectionContainers[this.selectionContainers.length - 1] : this.root;
    if (this.currentSelection) {
      this.walkSelectableRenderables(currentContainer, this.currentSelection.bounds, selectedRenderables, touchedRenderables);
      for (const renderable of this.currentSelection.touchedRenderables) {
        if (!touchedRenderables.includes(renderable) && !renderable.isDestroyed) {
          renderable.onSelectionChanged(null);
        }
      }
      this.currentSelection.updateSelectedRenderables(selectedRenderables);
      this.currentSelection.updateTouchedRenderables(touchedRenderables);
    }
  }
  walkSelectableRenderables(container, selectionBounds, selectedRenderables, touchedRenderables) {
    const children = getObjectsInViewport(selectionBounds, container.getChildrenSortedByPrimaryAxis(), container.primaryAxis, 0, 0);
    for (const child of children) {
      if (child.selectable) {
        const hasSelection = child.onSelectionChanged(this.currentSelection);
        if (hasSelection) {
          selectedRenderables.push(child);
        }
        touchedRenderables.push(child);
      }
      if (child.getChildrenCount() > 0) {
        this.walkSelectableRenderables(child, selectionBounds, selectedRenderables, touchedRenderables);
      }
    }
  }
  get paletteDetectionStatus() {
    if (this._paletteDetectionPromise)
      return "detecting";
    if (this._paletteCache.size > 0)
      return "cached";
    return "idle";
  }
  getCachedPaletteBySize(size) {
    const exactMatch = this._paletteCache.get(size);
    if (exactMatch) {
      return exactMatch;
    }
    const largerSize = [...this._paletteCache.keys()].sort((a, b) => a - b).find((candidate) => candidate >= size);
    if (largerSize === undefined) {
      return null;
    }
    const source = this._paletteCache.get(largerSize);
    if (!source) {
      return null;
    }
    const projected = {
      ...source,
      palette: source.palette.slice(0, size)
    };
    this._paletteCache.set(size, projected);
    return projected;
  }
  ensurePaletteDetector() {
    if (!this._paletteDetector) {
      const isTmux = Boolean(this.capabilities?.multiplexer === "tmux" || this.capabilities?.terminal?.name?.toLowerCase()?.includes("tmux"));
      const isLegacyTmux = this.capabilities?.terminal?.name?.toLowerCase()?.includes("tmux") && this.capabilities?.terminal?.version?.localeCompare("3.6") < 0;
      this._paletteDetector = createTerminalPalette({
        stdin: this.stdin,
        stdout: this.stdout,
        writeFn: (data) => this._isDestroyed ? false : this.writeOut(data),
        isLegacyTmux,
        isTmux,
        oscSource: {
          subscribeOsc: this.subscribeOsc.bind(this)
        },
        clock: this.clock
      });
    }
    return this._paletteDetector;
  }
  syncNativePaletteState(colors) {
    const signature = buildTerminalPaletteSignature(colors);
    if (this._nativePaletteSignature !== signature) {
      this._paletteEpoch = this._paletteEpoch + 1 >>> 0;
    }
    this._nativePaletteSignature = signature;
    const normalized = normalizeTerminalPalette(colors);
    this.lib.rendererSetPaletteState(this.rendererPtr, normalized.palette, normalized.defaultForeground, normalized.defaultBackground, this._paletteEpoch);
  }
  emitPaletteChange(colors) {
    if (this.listenerCount("palette" /* PALETTE */) === 0)
      return;
    const signature = buildTerminalPaletteSignature(colors);
    if (this._emittedPaletteSignature === signature)
      return;
    this._emittedPaletteSignature = signature;
    this.emit("palette" /* PALETTE */, colors);
  }
  resolveXtVersionWaiters() {
    if (this.xtVersionWaiters.size === 0)
      return;
    const resolvers = [...this.xtVersionWaiters];
    this.xtVersionWaiters.clear();
    for (const resolve of resolvers) {
      resolve();
    }
  }
  waitForXtVersion() {
    if (this.capabilityTimeoutId === null || this._capabilities?.terminal?.from_xtversion) {
      return Promise.resolve();
    }
    return new Promise((resolve) => {
      this.xtVersionWaiters.add(resolve);
    });
  }
  shouldSyncNativePaletteState() {
    return Boolean(this._terminalIsSetup && !this._isDestroyed && this._capabilities?.ansi256 && !this._capabilities?.rgb);
  }
  refreshPalette() {
    const publishGeneration = this._palettePublishGeneration;
    this.getPalette({ size: NATIVE_PALETTE_QUERY_SIZE }).then(() => {
      if (this._isDestroyed)
        return;
      if (this._palettePublishGeneration === publishGeneration)
        this.requestRender();
    }).catch(() => {});
  }
  clearPaletteCache() {
    this._palettePublishGeneration++;
    this._paletteCache.clear();
  }
  async getPalette(options) {
    if (this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
      throw new Error("Cannot detect palette while renderer is suspended");
    }
    const requestedSize = options?.size ?? 16;
    const detectionTimeout = options?.timeout;
    const cachedPalette = this.getCachedPaletteBySize(requestedSize);
    if (cachedPalette) {
      return cachedPalette;
    }
    const terminal = this._capabilities?.terminal;
    const hasTmuxVersion = terminal?.name?.toLowerCase() === "tmux" && Boolean(terminal.version);
    if (this._capabilities?.multiplexer === "tmux" && !hasTmuxVersion) {
      await this.waitForXtVersion();
      const afterCapabilityWait = this.getCachedPaletteBySize(requestedSize);
      if (afterCapabilityWait) {
        return afterCapabilityWait;
      }
    }
    if (this._paletteDetectionPromise) {
      if (this._paletteDetectionSize >= requestedSize) {
        return this._paletteDetectionPromise.then((palette) => {
          const cached = this.getCachedPaletteBySize(requestedSize);
          if (cached) {
            return cached;
          }
          const projected = {
            ...palette,
            palette: palette.palette.slice(0, requestedSize)
          };
          this._paletteCache.set(requestedSize, projected);
          return projected;
        });
      }
      await this._paletteDetectionPromise;
      const afterWait = this.getCachedPaletteBySize(requestedSize);
      if (afterWait) {
        return afterWait;
      }
    }
    const detector = this.ensurePaletteDetector();
    const publishGeneration = this._palettePublishGeneration;
    this._paletteDetectionSize = requestedSize;
    this._paletteDetectionPromise = detector.detect({ ...options, timeout: detectionTimeout }).then((result) => {
      this._paletteCache.set(result.palette.length, result);
      this._paletteDetectionPromise = null;
      this._paletteDetectionSize = 0;
      if (!this._isDestroyed && this._palettePublishGeneration === publishGeneration) {
        this.emitPaletteChange(result);
        if (this.shouldSyncNativePaletteState() && result.palette.length >= NATIVE_PALETTE_QUERY_SIZE) {
          this.syncNativePaletteState(result);
        } else if (this.shouldSyncNativePaletteState() && !this._paletteCache.has(NATIVE_PALETTE_QUERY_SIZE)) {
          this.refreshPalette();
        }
      }
      return result;
    }).catch((error) => {
      this._paletteDetectionPromise = null;
      this._paletteDetectionSize = 0;
      throw error;
    });
    const detected = await this._paletteDetectionPromise;
    const finalPalette = this.getCachedPaletteBySize(requestedSize) ?? detected;
    return finalPalette;
  }
}

export { h, isVNode, maybeMakeRenderable, wrapWithDelegates, instantiate, delegate, LayoutEvents, RenderableEvents, isRenderable, BaseRenderable, Renderable, RootRenderable, TextBufferView, EditBuffer, EditorView, convertThemeToStyles, SyntaxStyle, ANSI, BoxRenderable, TextBufferRenderable, CodeRenderable, isTextNodeRenderable, TextNodeRenderable, RootTextNodeRenderable, TextRenderable, NativeSpanFeed, defaultKeyAliases, mergeKeyAliases, mergeKeyBindings, getKeyBindingAction, buildKeyBindingsMap, capture, ConsolePosition, TerminalConsole, getObjectsInViewport, EditBufferRenderableEvents, isEditBufferRenderable, EditBufferRenderable, buildKittyKeyboardFlags, MouseEvent, MouseButton, createCliRenderer, CliRenderEvents, RendererControlState, CliRenderer };

//# debugId=2464034E49CDB83B64756E2164756E21
//# sourceMappingURL=chunk-bun-bb3k0yt8.js.map