@opentui/core 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,4 +1,32 @@
1
1
  // @bun
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, {
22
+ get: all[name],
23
+ enumerable: true,
24
+ configurable: true,
25
+ set: (newValue) => all[name] = () => newValue
26
+ });
27
+ };
28
+ var __require = import.meta.require;
29
+
2
30
  // src/Renderable.ts
3
31
  import { EventEmitter as EventEmitter3 } from "events";
4
32
 
@@ -2014,6 +2042,74 @@ function parseAlign(value) {
2014
2042
  return Align.Auto;
2015
2043
  }
2016
2044
  }
2045
+ function parseBoxSizing(value) {
2046
+ switch (value.toLowerCase()) {
2047
+ case "border-box":
2048
+ return BoxSizing.BorderBox;
2049
+ case "content-box":
2050
+ return BoxSizing.ContentBox;
2051
+ default:
2052
+ return BoxSizing.BorderBox;
2053
+ }
2054
+ }
2055
+ function parseDimension(value) {
2056
+ switch (value.toLowerCase()) {
2057
+ case "width":
2058
+ return Dimension.Width;
2059
+ case "height":
2060
+ return Dimension.Height;
2061
+ default:
2062
+ return Dimension.Width;
2063
+ }
2064
+ }
2065
+ function parseDirection(value) {
2066
+ switch (value.toLowerCase()) {
2067
+ case "inherit":
2068
+ return Direction.Inherit;
2069
+ case "ltr":
2070
+ return Direction.LTR;
2071
+ case "rtl":
2072
+ return Direction.RTL;
2073
+ default:
2074
+ return Direction.LTR;
2075
+ }
2076
+ }
2077
+ function parseDisplay(value) {
2078
+ switch (value.toLowerCase()) {
2079
+ case "flex":
2080
+ return Display.Flex;
2081
+ case "none":
2082
+ return Display.None;
2083
+ case "contents":
2084
+ return Display.Contents;
2085
+ default:
2086
+ return Display.Flex;
2087
+ }
2088
+ }
2089
+ function parseEdge(value) {
2090
+ switch (value.toLowerCase()) {
2091
+ case "left":
2092
+ return Edge.Left;
2093
+ case "top":
2094
+ return Edge.Top;
2095
+ case "right":
2096
+ return Edge.Right;
2097
+ case "bottom":
2098
+ return Edge.Bottom;
2099
+ case "start":
2100
+ return Edge.Start;
2101
+ case "end":
2102
+ return Edge.End;
2103
+ case "horizontal":
2104
+ return Edge.Horizontal;
2105
+ case "vertical":
2106
+ return Edge.Vertical;
2107
+ case "all":
2108
+ return Edge.All;
2109
+ default:
2110
+ return Edge.All;
2111
+ }
2112
+ }
2017
2113
  function parseFlexDirection(value) {
2018
2114
  switch (value.toLowerCase()) {
2019
2115
  case "column":
@@ -2028,6 +2124,18 @@ function parseFlexDirection(value) {
2028
2124
  return FlexDirection.Column;
2029
2125
  }
2030
2126
  }
2127
+ function parseGutter(value) {
2128
+ switch (value.toLowerCase()) {
2129
+ case "column":
2130
+ return Gutter.Column;
2131
+ case "row":
2132
+ return Gutter.Row;
2133
+ case "all":
2134
+ return Gutter.All;
2135
+ default:
2136
+ return Gutter.All;
2137
+ }
2138
+ }
2031
2139
  function parseJustify(value) {
2032
2140
  switch (value.toLowerCase()) {
2033
2141
  case "flex-start":
@@ -2046,6 +2154,48 @@ function parseJustify(value) {
2046
2154
  return Justify.FlexStart;
2047
2155
  }
2048
2156
  }
2157
+ function parseLogLevel(value) {
2158
+ switch (value.toLowerCase()) {
2159
+ case "error":
2160
+ return LogLevel.Error;
2161
+ case "warn":
2162
+ return LogLevel.Warn;
2163
+ case "info":
2164
+ return LogLevel.Info;
2165
+ case "debug":
2166
+ return LogLevel.Debug;
2167
+ case "verbose":
2168
+ return LogLevel.Verbose;
2169
+ case "fatal":
2170
+ return LogLevel.Fatal;
2171
+ default:
2172
+ return LogLevel.Info;
2173
+ }
2174
+ }
2175
+ function parseMeasureMode(value) {
2176
+ switch (value.toLowerCase()) {
2177
+ case "undefined":
2178
+ return MeasureMode.Undefined;
2179
+ case "exactly":
2180
+ return MeasureMode.Exactly;
2181
+ case "at-most":
2182
+ return MeasureMode.AtMost;
2183
+ default:
2184
+ return MeasureMode.Undefined;
2185
+ }
2186
+ }
2187
+ function parseOverflow(value) {
2188
+ switch (value.toLowerCase()) {
2189
+ case "visible":
2190
+ return Overflow.Visible;
2191
+ case "hidden":
2192
+ return Overflow.Hidden;
2193
+ case "scroll":
2194
+ return Overflow.Scroll;
2195
+ default:
2196
+ return Overflow.Visible;
2197
+ }
2198
+ }
2049
2199
  function parsePositionType(value) {
2050
2200
  switch (value.toLowerCase()) {
2051
2201
  case "static":
@@ -2058,6 +2208,32 @@ function parsePositionType(value) {
2058
2208
  return PositionType.Static;
2059
2209
  }
2060
2210
  }
2211
+ function parseUnit(value) {
2212
+ switch (value.toLowerCase()) {
2213
+ case "undefined":
2214
+ return Unit.Undefined;
2215
+ case "point":
2216
+ return Unit.Point;
2217
+ case "percent":
2218
+ return Unit.Percent;
2219
+ case "auto":
2220
+ return Unit.Auto;
2221
+ default:
2222
+ return Unit.Point;
2223
+ }
2224
+ }
2225
+ function parseWrap(value) {
2226
+ switch (value.toLowerCase()) {
2227
+ case "no-wrap":
2228
+ return Wrap.NoWrap;
2229
+ case "wrap":
2230
+ return Wrap.Wrap;
2231
+ case "wrap-reverse":
2232
+ return Wrap.WrapReverse;
2233
+ default:
2234
+ return Wrap.NoWrap;
2235
+ }
2236
+ }
2061
2237
 
2062
2238
  // src/Renderable.ts
2063
2239
  var LayoutEvents;
@@ -2117,6 +2293,9 @@ function isPositionType(value) {
2117
2293
  }
2118
2294
  return isValidPercentage(value);
2119
2295
  }
2296
+ function isPostionTypeType(value) {
2297
+ return value === "relative" || value === "absolute";
2298
+ }
2120
2299
  function isDimensionType(value) {
2121
2300
  return isPositionType(value);
2122
2301
  }
@@ -2160,6 +2339,10 @@ class Renderable extends EventEmitter3 {
2160
2339
  _focused = false;
2161
2340
  keyHandler = getKeyHandler();
2162
2341
  keypressHandler = null;
2342
+ _live = false;
2343
+ _liveCount = 0;
2344
+ _mouseListeners = {};
2345
+ _keyListeners = {};
2163
2346
  layoutNode;
2164
2347
  _positionType = "relative";
2165
2348
  _position = {};
@@ -2185,9 +2368,12 @@ class Renderable extends EventEmitter3 {
2185
2368
  this._zIndex = options.zIndex ?? 0;
2186
2369
  this._visible = options.visible !== false;
2187
2370
  this.buffered = options.buffered ?? false;
2371
+ this._live = options.live ?? false;
2372
+ this._liveCount = this._live && this._visible ? 1 : 0;
2188
2373
  this.layoutNode = createTrackedNode({ renderable: this });
2189
2374
  this.layoutNode.yogaNode.setDisplay(this._visible ? Display.Flex : Display.None);
2190
2375
  this.setupYogaProperties(options);
2376
+ this.applyEventOptions(options);
2191
2377
  if (this.buffered) {
2192
2378
  this.createFrameBuffer();
2193
2379
  }
@@ -2196,8 +2382,18 @@ class Renderable extends EventEmitter3 {
2196
2382
  return this._visible;
2197
2383
  }
2198
2384
  set visible(value) {
2385
+ if (this._visible === value)
2386
+ return;
2387
+ const wasVisible = this._visible;
2199
2388
  this._visible = value;
2200
2389
  this.layoutNode.yogaNode.setDisplay(value ? Display.Flex : Display.None);
2390
+ if (this._live) {
2391
+ if (!wasVisible && value) {
2392
+ this.propagateLiveCount(1);
2393
+ } else if (wasVisible && !value) {
2394
+ this.propagateLiveCount(-1);
2395
+ }
2396
+ }
2201
2397
  if (this._focused) {
2202
2398
  this.blur();
2203
2399
  }
@@ -2221,6 +2417,7 @@ class Renderable extends EventEmitter3 {
2221
2417
  this._focused = true;
2222
2418
  this.needsUpdate();
2223
2419
  this.keypressHandler = (key) => {
2420
+ this._keyListeners["down"]?.(key);
2224
2421
  if (this.handleKeyPress) {
2225
2422
  this.handleKeyPress(key);
2226
2423
  }
@@ -2242,6 +2439,25 @@ class Renderable extends EventEmitter3 {
2242
2439
  get focused() {
2243
2440
  return this._focused;
2244
2441
  }
2442
+ get live() {
2443
+ return this._live;
2444
+ }
2445
+ get liveCount() {
2446
+ return this._liveCount;
2447
+ }
2448
+ set live(value) {
2449
+ if (this._live === value)
2450
+ return;
2451
+ this._live = value;
2452
+ if (this._visible) {
2453
+ const delta = value ? 1 : -1;
2454
+ this.propagateLiveCount(delta);
2455
+ }
2456
+ }
2457
+ propagateLiveCount(delta) {
2458
+ this._liveCount += delta;
2459
+ this.parent?.propagateLiveCount(delta);
2460
+ }
2245
2461
  get isDirty() {
2246
2462
  return this._dirty;
2247
2463
  }
@@ -2379,7 +2595,7 @@ class Renderable extends EventEmitter3 {
2379
2595
  this._height = options.height;
2380
2596
  this.layoutNode.setHeight(options.height);
2381
2597
  }
2382
- this._positionType = options.position ?? "relative";
2598
+ this._positionType = options.position === "absolute" ? "absolute" : "relative";
2383
2599
  if (this._positionType !== "relative") {
2384
2600
  node.setPositionType(parsePositionType(this._positionType));
2385
2601
  }
@@ -2441,7 +2657,7 @@ class Renderable extends EventEmitter3 {
2441
2657
  }
2442
2658
  }
2443
2659
  set position(positionType) {
2444
- if (this._positionType === positionType)
2660
+ if (!isPostionTypeType(positionType) || this._positionType === positionType)
2445
2661
  return;
2446
2662
  this._positionType = positionType;
2447
2663
  this.layoutNode.yogaNode.setPositionType(parsePositionType(positionType));
@@ -2704,6 +2920,9 @@ class Renderable extends EventEmitter3 {
2704
2920
  }
2705
2921
  this.needsZIndexSort = true;
2706
2922
  this.renderableMap.set(obj.id, obj);
2923
+ if (obj._liveCount > 0) {
2924
+ this.propagateLiveCount(obj._liveCount);
2925
+ }
2707
2926
  this.requestLayout();
2708
2927
  this.emit("child:added", obj);
2709
2928
  return insertedIndex;
@@ -2737,6 +2956,9 @@ class Renderable extends EventEmitter3 {
2737
2956
  if (this.renderableMap.has(id)) {
2738
2957
  const obj = this.renderableMap.get(id);
2739
2958
  if (obj) {
2959
+ if (obj._liveCount > 0) {
2960
+ this.propagateLiveCount(-obj._liveCount);
2961
+ }
2740
2962
  const childLayoutNode = obj.getLayoutNode();
2741
2963
  this.layoutNode.removeChild(childLayoutNode);
2742
2964
  this.requestLayout();
@@ -2801,19 +3023,107 @@ class Renderable extends EventEmitter3 {
2801
3023
  }
2802
3024
  destroySelf() {}
2803
3025
  processMouseEvent(event) {
3026
+ this._mouseListeners[event.type]?.(event);
2804
3027
  this.onMouseEvent(event);
2805
3028
  if (this.parent && !event.defaultPrevented) {
2806
3029
  this.parent.processMouseEvent(event);
2807
3030
  }
2808
3031
  }
2809
3032
  onMouseEvent(event) {}
3033
+ set onMouseDown(handler) {
3034
+ if (handler)
3035
+ this._mouseListeners["down"] = handler;
3036
+ else
3037
+ delete this._mouseListeners["down"];
3038
+ }
3039
+ set onMouseUp(handler) {
3040
+ if (handler)
3041
+ this._mouseListeners["up"] = handler;
3042
+ else
3043
+ delete this._mouseListeners["up"];
3044
+ }
3045
+ set onMouseMove(handler) {
3046
+ if (handler)
3047
+ this._mouseListeners["move"] = handler;
3048
+ else
3049
+ delete this._mouseListeners["move"];
3050
+ }
3051
+ set onMouseDrag(handler) {
3052
+ if (handler)
3053
+ this._mouseListeners["drag"] = handler;
3054
+ else
3055
+ delete this._mouseListeners["drag"];
3056
+ }
3057
+ set onMouseDragEnd(handler) {
3058
+ if (handler)
3059
+ this._mouseListeners["drag-end"] = handler;
3060
+ else
3061
+ delete this._mouseListeners["drag-end"];
3062
+ }
3063
+ set onMouseDrop(handler) {
3064
+ if (handler)
3065
+ this._mouseListeners["drop"] = handler;
3066
+ else
3067
+ delete this._mouseListeners["drop"];
3068
+ }
3069
+ set onMouseOver(handler) {
3070
+ if (handler)
3071
+ this._mouseListeners["over"] = handler;
3072
+ else
3073
+ delete this._mouseListeners["over"];
3074
+ }
3075
+ set onMouseOut(handler) {
3076
+ if (handler)
3077
+ this._mouseListeners["out"] = handler;
3078
+ else
3079
+ delete this._mouseListeners["out"];
3080
+ }
3081
+ set onMouseScroll(handler) {
3082
+ if (handler)
3083
+ this._mouseListeners["scroll"] = handler;
3084
+ else
3085
+ delete this._mouseListeners["scroll"];
3086
+ }
3087
+ set onKeyDown(handler) {
3088
+ if (handler)
3089
+ this._keyListeners["down"] = handler;
3090
+ else
3091
+ delete this._keyListeners["down"];
3092
+ }
3093
+ get onKeyDown() {
3094
+ return this._keyListeners["down"];
3095
+ }
3096
+ applyEventOptions(options) {
3097
+ if (options.onMouseDown)
3098
+ this.onMouseDown = options.onMouseDown;
3099
+ if (options.onMouseUp)
3100
+ this.onMouseUp = options.onMouseUp;
3101
+ if (options.onMouseMove)
3102
+ this.onMouseMove = options.onMouseMove;
3103
+ if (options.onMouseDrag)
3104
+ this.onMouseDrag = options.onMouseDrag;
3105
+ if (options.onMouseDragEnd)
3106
+ this.onMouseDragEnd = options.onMouseDragEnd;
3107
+ if (options.onMouseDrop)
3108
+ this.onMouseDrop = options.onMouseDrop;
3109
+ if (options.onMouseOver)
3110
+ this.onMouseOver = options.onMouseOver;
3111
+ if (options.onMouseOut)
3112
+ this.onMouseOut = options.onMouseOut;
3113
+ if (options.onMouseScroll)
3114
+ this.onMouseScroll = options.onMouseScroll;
3115
+ if (options.onKeyDown)
3116
+ this.onKeyDown = options.onKeyDown;
3117
+ }
2810
3118
  }
2811
3119
 
2812
3120
  class RootRenderable extends Renderable {
2813
3121
  yogaConfig;
2814
- constructor(width, height, ctx) {
3122
+ rootContext;
3123
+ constructor(width, height, ctx, rootContext) {
2815
3124
  super("__root__", { zIndex: 0, visible: true, width, height, enableLayout: true });
2816
3125
  this.ctx = ctx;
3126
+ this.rootContext = rootContext;
2817
3127
  this.yogaConfig = src_default.Config.create();
2818
3128
  this.yogaConfig.setUseWebDefaults(false);
2819
3129
  this.yogaConfig.setPointScaleFactor(1);
@@ -2829,13 +3139,22 @@ class RootRenderable extends Renderable {
2829
3139
  requestLayout() {
2830
3140
  this.needsUpdate();
2831
3141
  }
3142
+ propagateLiveCount(delta) {
3143
+ const oldCount = this._liveCount;
3144
+ this._liveCount += delta;
3145
+ if (oldCount === 0 && this._liveCount > 0) {
3146
+ this.rootContext.requestLive();
3147
+ } else if (oldCount > 0 && this._liveCount === 0) {
3148
+ this.rootContext.dropLive();
3149
+ }
3150
+ }
2832
3151
  calculateLayout() {
2833
3152
  this.layoutNode.yogaNode.calculateLayout(this.width, this.height, Direction.LTR);
2834
3153
  this.emit("layout-changed" /* LAYOUT_CHANGED */);
2835
3154
  }
2836
3155
  resize(width, height) {
2837
- this.layoutNode.setWidth(width);
2838
- this.layoutNode.setHeight(height);
3156
+ this.width = width;
3157
+ this.height = height;
2839
3158
  this.emit("resized" /* RESIZED */, { width, height });
2840
3159
  }
2841
3160
  beforeRender() {
@@ -2853,111 +3172,26 @@ class RootRenderable extends Renderable {
2853
3172
  super.destroySelf();
2854
3173
  }
2855
3174
  }
2856
- // src/utils.ts
2857
- function hexToRgb(hex) {
2858
- hex = hex.replace(/^#/, "");
2859
- if (hex.length === 3) {
2860
- hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
2861
- }
2862
- if (!/^[0-9A-Fa-f]{6}$/.test(hex)) {
2863
- console.warn(`Invalid hex color: ${hex}, defaulting to magenta`);
2864
- return RGBA.fromValues(1, 0, 1, 1);
2865
- }
2866
- const r = parseInt(hex.substring(0, 2), 16) / 255;
2867
- const g = parseInt(hex.substring(2, 4), 16) / 255;
2868
- const b = parseInt(hex.substring(4, 6), 16) / 255;
2869
- return RGBA.fromValues(r, g, b, 1);
2870
- }
2871
- function rgbToHex(rgb) {
2872
- return "#" + [rgb.r, rgb.g, rgb.b].map((x) => {
2873
- const hex = Math.floor(Math.max(0, Math.min(1, x) * 255)).toString(16);
2874
- return hex.length === 1 ? "0" + hex : hex;
2875
- }).join("");
2876
- }
2877
- function hsvToRgb(h, s, v) {
2878
- let r = 0, g = 0, b = 0;
2879
- const i = Math.floor(h / 60) % 6;
2880
- const f = h / 60 - Math.floor(h / 60);
2881
- const p = v * (1 - s);
2882
- const q = v * (1 - f * s);
2883
- const t = v * (1 - (1 - f) * s);
2884
- switch (i) {
2885
- case 0:
2886
- r = v;
2887
- g = t;
2888
- b = p;
2889
- break;
2890
- case 1:
2891
- r = q;
2892
- g = v;
2893
- b = p;
2894
- break;
2895
- case 2:
2896
- r = p;
2897
- g = v;
2898
- b = t;
2899
- break;
2900
- case 3:
2901
- r = p;
2902
- g = q;
2903
- b = v;
2904
- break;
2905
- case 4:
2906
- r = t;
2907
- g = p;
2908
- b = v;
2909
- break;
2910
- case 5:
2911
- r = v;
2912
- g = p;
2913
- b = q;
2914
- break;
2915
- }
2916
- return RGBA.fromValues(r, g, b, 1);
2917
- }
2918
- var CSS_COLOR_NAMES = {
2919
- black: "#000000",
2920
- white: "#FFFFFF",
2921
- red: "#FF0000",
2922
- green: "#008000",
2923
- blue: "#0000FF",
2924
- yellow: "#FFFF00",
2925
- cyan: "#00FFFF",
2926
- magenta: "#FF00FF",
2927
- silver: "#C0C0C0",
2928
- gray: "#808080",
2929
- grey: "#808080",
2930
- maroon: "#800000",
2931
- olive: "#808000",
2932
- lime: "#00FF00",
2933
- aqua: "#00FFFF",
2934
- teal: "#008080",
2935
- navy: "#000080",
2936
- fuchsia: "#FF00FF",
2937
- purple: "#800080",
2938
- orange: "#FFA500",
2939
- brightblack: "#666666",
2940
- brightred: "#FF6666",
2941
- brightgreen: "#66FF66",
2942
- brightblue: "#6666FF",
2943
- brightyellow: "#FFFF66",
2944
- brightcyan: "#66FFFF",
2945
- brightmagenta: "#FF66FF",
2946
- brightwhite: "#FFFFFF"
3175
+ // src/types.ts
3176
+ var TextAttributes = {
3177
+ NONE: 0,
3178
+ BOLD: 1 << 0,
3179
+ DIM: 1 << 1,
3180
+ ITALIC: 1 << 2,
3181
+ UNDERLINE: 1 << 3,
3182
+ BLINK: 1 << 4,
3183
+ INVERSE: 1 << 5,
3184
+ HIDDEN: 1 << 6,
3185
+ STRIKETHROUGH: 1 << 7
2947
3186
  };
2948
- function parseColor(color) {
2949
- if (typeof color === "string") {
2950
- const lowerColor = color.toLowerCase();
2951
- if (lowerColor === "transparent") {
2952
- return RGBA.fromValues(0, 0, 0, 0);
2953
- }
2954
- if (CSS_COLOR_NAMES[lowerColor]) {
2955
- return hexToRgb(CSS_COLOR_NAMES[lowerColor]);
2956
- }
2957
- return hexToRgb(color);
2958
- }
2959
- return color;
2960
- }
3187
+ var DebugOverlayCorner;
3188
+ ((DebugOverlayCorner2) => {
3189
+ DebugOverlayCorner2[DebugOverlayCorner2["topLeft"] = 0] = "topLeft";
3190
+ DebugOverlayCorner2[DebugOverlayCorner2["topRight"] = 1] = "topRight";
3191
+ DebugOverlayCorner2[DebugOverlayCorner2["bottomLeft"] = 2] = "bottomLeft";
3192
+ DebugOverlayCorner2[DebugOverlayCorner2["bottomRight"] = 3] = "bottomRight";
3193
+ })(DebugOverlayCorner ||= {});
3194
+ // src/utils.ts
2961
3195
  function createTextAttributes({
2962
3196
  bold = false,
2963
3197
  italic = false,
@@ -2987,15 +3221,110 @@ function createTextAttributes({
2987
3221
  attributes |= TextAttributes.STRIKETHROUGH;
2988
3222
  return attributes;
2989
3223
  }
2990
-
2991
- // src/types.ts
2992
- class RGBA {
2993
- buffer;
2994
- constructor(buffer) {
2995
- this.buffer = buffer;
3224
+ // src/lib/border.ts
3225
+ var BorderChars = {
3226
+ single: {
3227
+ topLeft: "\u250C",
3228
+ topRight: "\u2510",
3229
+ bottomLeft: "\u2514",
3230
+ bottomRight: "\u2518",
3231
+ horizontal: "\u2500",
3232
+ vertical: "\u2502",
3233
+ topT: "\u252C",
3234
+ bottomT: "\u2534",
3235
+ leftT: "\u251C",
3236
+ rightT: "\u2524",
3237
+ cross: "\u253C"
3238
+ },
3239
+ double: {
3240
+ topLeft: "\u2554",
3241
+ topRight: "\u2557",
3242
+ bottomLeft: "\u255A",
3243
+ bottomRight: "\u255D",
3244
+ horizontal: "\u2550",
3245
+ vertical: "\u2551",
3246
+ topT: "\u2566",
3247
+ bottomT: "\u2569",
3248
+ leftT: "\u2560",
3249
+ rightT: "\u2563",
3250
+ cross: "\u256C"
3251
+ },
3252
+ rounded: {
3253
+ topLeft: "\u256D",
3254
+ topRight: "\u256E",
3255
+ bottomLeft: "\u2570",
3256
+ bottomRight: "\u256F",
3257
+ horizontal: "\u2500",
3258
+ vertical: "\u2502",
3259
+ topT: "\u252C",
3260
+ bottomT: "\u2534",
3261
+ leftT: "\u251C",
3262
+ rightT: "\u2524",
3263
+ cross: "\u253C"
3264
+ },
3265
+ heavy: {
3266
+ topLeft: "\u250F",
3267
+ topRight: "\u2513",
3268
+ bottomLeft: "\u2517",
3269
+ bottomRight: "\u251B",
3270
+ horizontal: "\u2501",
3271
+ vertical: "\u2503",
3272
+ topT: "\u2533",
3273
+ bottomT: "\u253B",
3274
+ leftT: "\u2523",
3275
+ rightT: "\u252B",
3276
+ cross: "\u254B"
2996
3277
  }
2997
- static fromArray(array) {
2998
- return new RGBA(array);
3278
+ };
3279
+ function getBorderFromSides(sides) {
3280
+ const result = [];
3281
+ if (sides.top)
3282
+ result.push("top");
3283
+ if (sides.right)
3284
+ result.push("right");
3285
+ if (sides.bottom)
3286
+ result.push("bottom");
3287
+ if (sides.left)
3288
+ result.push("left");
3289
+ return result.length > 0 ? result : false;
3290
+ }
3291
+ function getBorderSides(border) {
3292
+ return border === true ? { top: true, right: true, bottom: true, left: true } : Array.isArray(border) ? {
3293
+ top: border.includes("top"),
3294
+ right: border.includes("right"),
3295
+ bottom: border.includes("bottom"),
3296
+ left: border.includes("left")
3297
+ } : { top: false, right: false, bottom: false, left: false };
3298
+ }
3299
+ function borderCharsToArray(chars) {
3300
+ const array = new Uint32Array(11);
3301
+ array[0] = chars.topLeft.codePointAt(0);
3302
+ array[1] = chars.topRight.codePointAt(0);
3303
+ array[2] = chars.bottomLeft.codePointAt(0);
3304
+ array[3] = chars.bottomRight.codePointAt(0);
3305
+ array[4] = chars.horizontal.codePointAt(0);
3306
+ array[5] = chars.vertical.codePointAt(0);
3307
+ array[6] = chars.topT.codePointAt(0);
3308
+ array[7] = chars.bottomT.codePointAt(0);
3309
+ array[8] = chars.leftT.codePointAt(0);
3310
+ array[9] = chars.rightT.codePointAt(0);
3311
+ array[10] = chars.cross.codePointAt(0);
3312
+ return array;
3313
+ }
3314
+ var BorderCharArrays = {
3315
+ single: borderCharsToArray(BorderChars.single),
3316
+ double: borderCharsToArray(BorderChars.double),
3317
+ rounded: borderCharsToArray(BorderChars.rounded),
3318
+ heavy: borderCharsToArray(BorderChars.heavy)
3319
+ };
3320
+ // src/lib/RGBA.ts
3321
+ class RGBA {
3322
+ buffer;
3323
+ constructor(buffer) {
3324
+ this.buffer = buffer;
3325
+ }
3326
+ static fromArray(array) {
3327
+ return new RGBA(array);
2999
3328
  }
3000
3329
  static fromValues(r, g, b, a = 1) {
3001
3330
  return new RGBA(new Float32Array([r, g, b, a]));
@@ -3040,849 +3369,110 @@ class RGBA {
3040
3369
  return `rgba(${this.r.toFixed(2)}, ${this.g.toFixed(2)}, ${this.b.toFixed(2)}, ${this.a.toFixed(2)})`;
3041
3370
  }
3042
3371
  }
3043
- var TextAttributes = {
3044
- NONE: 0,
3045
- BOLD: 1 << 0,
3046
- DIM: 1 << 1,
3047
- ITALIC: 1 << 2,
3048
- UNDERLINE: 1 << 3,
3049
- BLINK: 1 << 4,
3050
- INVERSE: 1 << 5,
3051
- HIDDEN: 1 << 6,
3052
- STRIKETHROUGH: 1 << 7
3053
- };
3054
- var DebugOverlayCorner;
3055
- ((DebugOverlayCorner2) => {
3056
- DebugOverlayCorner2[DebugOverlayCorner2["topLeft"] = 0] = "topLeft";
3057
- DebugOverlayCorner2[DebugOverlayCorner2["topRight"] = 1] = "topRight";
3058
- DebugOverlayCorner2[DebugOverlayCorner2["bottomLeft"] = 2] = "bottomLeft";
3059
- DebugOverlayCorner2[DebugOverlayCorner2["bottomRight"] = 3] = "bottomRight";
3060
- })(DebugOverlayCorner ||= {});
3061
- // src/zig.ts
3062
- import { dlopen, toArrayBuffer } from "bun:ffi";
3063
- import { existsSync } from "fs";
3064
-
3065
- // src/text-buffer.ts
3066
- class TextBuffer {
3067
- lib;
3068
- bufferPtr;
3069
- buffer;
3070
- _length = 0;
3071
- _capacity;
3072
- _lineInfo;
3073
- constructor(lib, ptr, buffer, capacity) {
3074
- this.lib = lib;
3075
- this.bufferPtr = ptr;
3076
- this.buffer = buffer;
3077
- this._capacity = capacity;
3078
- }
3079
- static create(capacity = 256) {
3080
- const lib = resolveRenderLib();
3081
- return lib.createTextBuffer(capacity);
3082
- }
3083
- syncBuffersAfterResize() {
3084
- const capacity = this.lib.textBufferGetCapacity(this.bufferPtr);
3085
- this.buffer = this.lib.getTextBufferArrays(this.bufferPtr, capacity);
3086
- this._capacity = capacity;
3087
- }
3088
- setStyledText(text) {
3089
- this.lib.textBufferReset(this.bufferPtr);
3090
- this._length = 0;
3091
- this._lineInfo = undefined;
3092
- for (const chunk of text.chunks) {
3093
- const result = this.lib.textBufferWriteChunk(this.bufferPtr, chunk.text, chunk.fg || null, chunk.bg || null, chunk.attributes ?? null);
3094
- if (result & 1) {
3095
- this.syncBuffersAfterResize();
3096
- }
3097
- }
3098
- this.lib.textBufferFinalizeLineInfo(this.bufferPtr);
3099
- this._length = this.lib.textBufferGetLength(this.bufferPtr);
3100
- }
3101
- setDefaultFg(fg) {
3102
- this.lib.textBufferSetDefaultFg(this.bufferPtr, fg);
3103
- }
3104
- setDefaultBg(bg) {
3105
- this.lib.textBufferSetDefaultBg(this.bufferPtr, bg);
3106
- }
3107
- setDefaultAttributes(attributes) {
3108
- this.lib.textBufferSetDefaultAttributes(this.bufferPtr, attributes);
3109
- }
3110
- resetDefaults() {
3111
- this.lib.textBufferResetDefaults(this.bufferPtr);
3112
- }
3113
- get length() {
3114
- return this._length;
3372
+ function hexToRgb(hex) {
3373
+ hex = hex.replace(/^#/, "");
3374
+ if (hex.length === 3) {
3375
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
3115
3376
  }
3116
- get capacity() {
3117
- return this._capacity;
3377
+ if (!/^[0-9A-Fa-f]{6}$/.test(hex)) {
3378
+ console.warn(`Invalid hex color: ${hex}, defaulting to magenta`);
3379
+ return RGBA.fromValues(1, 0, 1, 1);
3118
3380
  }
3119
- get ptr() {
3120
- return this.bufferPtr;
3381
+ const r = parseInt(hex.substring(0, 2), 16) / 255;
3382
+ const g = parseInt(hex.substring(2, 4), 16) / 255;
3383
+ const b = parseInt(hex.substring(4, 6), 16) / 255;
3384
+ return RGBA.fromValues(r, g, b, 1);
3385
+ }
3386
+ function rgbToHex(rgb) {
3387
+ return "#" + [rgb.r, rgb.g, rgb.b].map((x) => {
3388
+ const hex = Math.floor(Math.max(0, Math.min(1, x) * 255)).toString(16);
3389
+ return hex.length === 1 ? "0" + hex : hex;
3390
+ }).join("");
3391
+ }
3392
+ function hsvToRgb(h, s, v) {
3393
+ let r = 0, g = 0, b = 0;
3394
+ const i = Math.floor(h / 60) % 6;
3395
+ const f = h / 60 - Math.floor(h / 60);
3396
+ const p = v * (1 - s);
3397
+ const q = v * (1 - f * s);
3398
+ const t = v * (1 - (1 - f) * s);
3399
+ switch (i) {
3400
+ case 0:
3401
+ r = v;
3402
+ g = t;
3403
+ b = p;
3404
+ break;
3405
+ case 1:
3406
+ r = q;
3407
+ g = v;
3408
+ b = p;
3409
+ break;
3410
+ case 2:
3411
+ r = p;
3412
+ g = v;
3413
+ b = t;
3414
+ break;
3415
+ case 3:
3416
+ r = p;
3417
+ g = q;
3418
+ b = v;
3419
+ break;
3420
+ case 4:
3421
+ r = t;
3422
+ g = p;
3423
+ b = v;
3424
+ break;
3425
+ case 5:
3426
+ r = v;
3427
+ g = p;
3428
+ b = q;
3429
+ break;
3121
3430
  }
3122
- get lineInfo() {
3123
- if (!this._lineInfo) {
3124
- this._lineInfo = this.lib.textBufferGetLineInfo(this.bufferPtr);
3431
+ return RGBA.fromValues(r, g, b, 1);
3432
+ }
3433
+ var CSS_COLOR_NAMES = {
3434
+ black: "#000000",
3435
+ white: "#FFFFFF",
3436
+ red: "#FF0000",
3437
+ green: "#008000",
3438
+ blue: "#0000FF",
3439
+ yellow: "#FFFF00",
3440
+ cyan: "#00FFFF",
3441
+ magenta: "#FF00FF",
3442
+ silver: "#C0C0C0",
3443
+ gray: "#808080",
3444
+ grey: "#808080",
3445
+ maroon: "#800000",
3446
+ olive: "#808000",
3447
+ lime: "#00FF00",
3448
+ aqua: "#00FFFF",
3449
+ teal: "#008080",
3450
+ navy: "#000080",
3451
+ fuchsia: "#FF00FF",
3452
+ purple: "#800080",
3453
+ orange: "#FFA500",
3454
+ brightblack: "#666666",
3455
+ brightred: "#FF6666",
3456
+ brightgreen: "#66FF66",
3457
+ brightblue: "#6666FF",
3458
+ brightyellow: "#FFFF66",
3459
+ brightcyan: "#66FFFF",
3460
+ brightmagenta: "#FF66FF",
3461
+ brightwhite: "#FFFFFF"
3462
+ };
3463
+ function parseColor(color) {
3464
+ if (typeof color === "string") {
3465
+ const lowerColor = color.toLowerCase();
3466
+ if (lowerColor === "transparent") {
3467
+ return RGBA.fromValues(0, 0, 0, 0);
3125
3468
  }
3126
- return this._lineInfo;
3127
- }
3128
- toString() {
3129
- const chars = [];
3130
- for (let i = 0;i < this._length; i++) {
3131
- chars.push(String.fromCharCode(this.buffer.char[i]));
3469
+ if (CSS_COLOR_NAMES[lowerColor]) {
3470
+ return hexToRgb(CSS_COLOR_NAMES[lowerColor]);
3132
3471
  }
3133
- return chars.join("");
3134
- }
3135
- concat(other) {
3136
- return this.lib.textBufferConcat(this.bufferPtr, other.bufferPtr);
3137
- }
3138
- setSelection(start, end, bgColor, fgColor) {
3139
- this.lib.textBufferSetSelection(this.bufferPtr, start, end, bgColor || null, fgColor || null);
3140
- }
3141
- resetSelection() {
3142
- this.lib.textBufferResetSelection(this.bufferPtr);
3143
- }
3144
- destroy() {
3145
- this.lib.destroyTextBuffer(this.bufferPtr);
3472
+ return hexToRgb(color);
3146
3473
  }
3474
+ return color;
3147
3475
  }
3148
-
3149
- // src/zig.ts
3150
- var module = await import(`@opentui/core-${process.platform}-${process.arch}/index.ts`);
3151
- var targetLibPath = module.default;
3152
- if (!existsSync(targetLibPath)) {
3153
- throw new Error(`opentui is not supported on the current platform: ${process.platform}-${process.arch}`);
3154
- }
3155
- function getOpenTUILib(libPath) {
3156
- const resolvedLibPath = libPath || targetLibPath;
3157
- return dlopen(resolvedLibPath, {
3158
- createRenderer: {
3159
- args: ["u32", "u32"],
3160
- returns: "ptr"
3161
- },
3162
- destroyRenderer: {
3163
- args: ["ptr"],
3164
- returns: "void"
3165
- },
3166
- setUseThread: {
3167
- args: ["ptr", "bool"],
3168
- returns: "void"
3169
- },
3170
- setBackgroundColor: {
3171
- args: ["ptr", "ptr"],
3172
- returns: "void"
3173
- },
3174
- setRenderOffset: {
3175
- args: ["ptr", "u32"],
3176
- returns: "void"
3177
- },
3178
- updateStats: {
3179
- args: ["ptr", "f64", "u32", "f64"],
3180
- returns: "void"
3181
- },
3182
- updateMemoryStats: {
3183
- args: ["ptr", "u32", "u32", "u32"],
3184
- returns: "void"
3185
- },
3186
- render: {
3187
- args: ["ptr", "bool"],
3188
- returns: "void"
3189
- },
3190
- getNextBuffer: {
3191
- args: ["ptr"],
3192
- returns: "ptr"
3193
- },
3194
- getCurrentBuffer: {
3195
- args: ["ptr"],
3196
- returns: "ptr"
3197
- },
3198
- createOptimizedBuffer: {
3199
- args: ["u32", "u32", "bool"],
3200
- returns: "ptr"
3201
- },
3202
- destroyOptimizedBuffer: {
3203
- args: ["ptr"],
3204
- returns: "void"
3205
- },
3206
- drawFrameBuffer: {
3207
- args: ["ptr", "i32", "i32", "ptr", "u32", "u32", "u32", "u32"],
3208
- returns: "void"
3209
- },
3210
- getBufferWidth: {
3211
- args: ["ptr"],
3212
- returns: "u32"
3213
- },
3214
- getBufferHeight: {
3215
- args: ["ptr"],
3216
- returns: "u32"
3217
- },
3218
- bufferClear: {
3219
- args: ["ptr", "ptr"],
3220
- returns: "void"
3221
- },
3222
- bufferGetCharPtr: {
3223
- args: ["ptr"],
3224
- returns: "ptr"
3225
- },
3226
- bufferGetFgPtr: {
3227
- args: ["ptr"],
3228
- returns: "ptr"
3229
- },
3230
- bufferGetBgPtr: {
3231
- args: ["ptr"],
3232
- returns: "ptr"
3233
- },
3234
- bufferGetAttributesPtr: {
3235
- args: ["ptr"],
3236
- returns: "ptr"
3237
- },
3238
- bufferGetRespectAlpha: {
3239
- args: ["ptr"],
3240
- returns: "bool"
3241
- },
3242
- bufferSetRespectAlpha: {
3243
- args: ["ptr", "bool"],
3244
- returns: "void"
3245
- },
3246
- bufferDrawText: {
3247
- args: ["ptr", "ptr", "u32", "u32", "u32", "ptr", "ptr", "u8"],
3248
- returns: "void"
3249
- },
3250
- bufferSetCellWithAlphaBlending: {
3251
- args: ["ptr", "u32", "u32", "u32", "ptr", "ptr", "u8"],
3252
- returns: "void"
3253
- },
3254
- bufferFillRect: {
3255
- args: ["ptr", "u32", "u32", "u32", "u32", "ptr"],
3256
- returns: "void"
3257
- },
3258
- bufferResize: {
3259
- args: ["ptr", "u32", "u32"],
3260
- returns: "void"
3261
- },
3262
- resizeRenderer: {
3263
- args: ["ptr", "u32", "u32"],
3264
- returns: "void"
3265
- },
3266
- setCursorPosition: {
3267
- args: ["i32", "i32", "bool"],
3268
- returns: "void"
3269
- },
3270
- setCursorStyle: {
3271
- args: ["ptr", "u32", "bool"],
3272
- returns: "void"
3273
- },
3274
- setCursorColor: {
3275
- args: ["ptr"],
3276
- returns: "void"
3277
- },
3278
- setDebugOverlay: {
3279
- args: ["ptr", "bool", "u8"],
3280
- returns: "void"
3281
- },
3282
- clearTerminal: {
3283
- args: ["ptr"],
3284
- returns: "void"
3285
- },
3286
- bufferDrawSuperSampleBuffer: {
3287
- args: ["ptr", "u32", "u32", "ptr", "usize", "u8", "u32"],
3288
- returns: "void"
3289
- },
3290
- bufferDrawPackedBuffer: {
3291
- args: ["ptr", "ptr", "usize", "u32", "u32", "u32", "u32"],
3292
- returns: "void"
3293
- },
3294
- bufferDrawBox: {
3295
- args: ["ptr", "i32", "i32", "u32", "u32", "ptr", "u32", "ptr", "ptr", "ptr", "u32"],
3296
- returns: "void"
3297
- },
3298
- addToHitGrid: {
3299
- args: ["ptr", "i32", "i32", "u32", "u32", "u32"],
3300
- returns: "void"
3301
- },
3302
- checkHit: {
3303
- args: ["ptr", "u32", "u32"],
3304
- returns: "u32"
3305
- },
3306
- dumpHitGrid: {
3307
- args: ["ptr"],
3308
- returns: "void"
3309
- },
3310
- dumpBuffers: {
3311
- args: ["ptr", "i64"],
3312
- returns: "void"
3313
- },
3314
- dumpStdoutBuffer: {
3315
- args: ["ptr", "i64"],
3316
- returns: "void"
3317
- },
3318
- createTextBuffer: {
3319
- args: ["u32"],
3320
- returns: "ptr"
3321
- },
3322
- destroyTextBuffer: {
3323
- args: ["ptr"],
3324
- returns: "void"
3325
- },
3326
- textBufferGetCharPtr: {
3327
- args: ["ptr"],
3328
- returns: "ptr"
3329
- },
3330
- textBufferGetFgPtr: {
3331
- args: ["ptr"],
3332
- returns: "ptr"
3333
- },
3334
- textBufferGetBgPtr: {
3335
- args: ["ptr"],
3336
- returns: "ptr"
3337
- },
3338
- textBufferGetAttributesPtr: {
3339
- args: ["ptr"],
3340
- returns: "ptr"
3341
- },
3342
- textBufferGetLength: {
3343
- args: ["ptr"],
3344
- returns: "u32"
3345
- },
3346
- textBufferSetCell: {
3347
- args: ["ptr", "u32", "u32", "ptr", "ptr", "u16"],
3348
- returns: "void"
3349
- },
3350
- textBufferConcat: {
3351
- args: ["ptr", "ptr"],
3352
- returns: "ptr"
3353
- },
3354
- textBufferResize: {
3355
- args: ["ptr", "u32"],
3356
- returns: "void"
3357
- },
3358
- textBufferReset: {
3359
- args: ["ptr"],
3360
- returns: "void"
3361
- },
3362
- textBufferSetSelection: {
3363
- args: ["ptr", "u32", "u32", "ptr", "ptr"],
3364
- returns: "void"
3365
- },
3366
- textBufferResetSelection: {
3367
- args: ["ptr"],
3368
- returns: "void"
3369
- },
3370
- textBufferSetDefaultFg: {
3371
- args: ["ptr", "ptr"],
3372
- returns: "void"
3373
- },
3374
- textBufferSetDefaultBg: {
3375
- args: ["ptr", "ptr"],
3376
- returns: "void"
3377
- },
3378
- textBufferSetDefaultAttributes: {
3379
- args: ["ptr", "ptr"],
3380
- returns: "void"
3381
- },
3382
- textBufferResetDefaults: {
3383
- args: ["ptr"],
3384
- returns: "void"
3385
- },
3386
- textBufferWriteChunk: {
3387
- args: ["ptr", "ptr", "u32", "ptr", "ptr", "ptr"],
3388
- returns: "u32"
3389
- },
3390
- textBufferGetCapacity: {
3391
- args: ["ptr"],
3392
- returns: "u32"
3393
- },
3394
- textBufferFinalizeLineInfo: {
3395
- args: ["ptr"],
3396
- returns: "void"
3397
- },
3398
- textBufferGetLineStartsPtr: {
3399
- args: ["ptr"],
3400
- returns: "ptr"
3401
- },
3402
- textBufferGetLineWidthsPtr: {
3403
- args: ["ptr"],
3404
- returns: "ptr"
3405
- },
3406
- textBufferGetLineCount: {
3407
- args: ["ptr"],
3408
- returns: "u32"
3409
- },
3410
- bufferDrawTextBuffer: {
3411
- args: ["ptr", "ptr", "i32", "i32", "i32", "i32", "u32", "u32", "bool"],
3412
- returns: "void"
3413
- }
3414
- });
3415
- }
3416
-
3417
- class FFIRenderLib {
3418
- opentui;
3419
- encoder = new TextEncoder;
3420
- constructor(libPath) {
3421
- this.opentui = getOpenTUILib(libPath);
3422
- }
3423
- createRenderer(width, height) {
3424
- return this.opentui.symbols.createRenderer(width, height);
3425
- }
3426
- destroyRenderer(renderer) {
3427
- this.opentui.symbols.destroyRenderer(renderer);
3428
- }
3429
- setUseThread(renderer, useThread) {
3430
- this.opentui.symbols.setUseThread(renderer, useThread);
3431
- }
3432
- setBackgroundColor(renderer, color) {
3433
- this.opentui.symbols.setBackgroundColor(renderer, color.buffer);
3434
- }
3435
- setRenderOffset(renderer, offset) {
3436
- this.opentui.symbols.setRenderOffset(renderer, offset);
3437
- }
3438
- updateStats(renderer, time, fps, frameCallbackTime) {
3439
- this.opentui.symbols.updateStats(renderer, time, fps, frameCallbackTime);
3440
- }
3441
- updateMemoryStats(renderer, heapUsed, heapTotal, arrayBuffers) {
3442
- this.opentui.symbols.updateMemoryStats(renderer, heapUsed, heapTotal, arrayBuffers);
3443
- }
3444
- getNextBuffer(renderer) {
3445
- const bufferPtr = this.opentui.symbols.getNextBuffer(renderer);
3446
- if (!bufferPtr) {
3447
- throw new Error("Failed to get next buffer");
3448
- }
3449
- const width = this.opentui.symbols.getBufferWidth(bufferPtr);
3450
- const height = this.opentui.symbols.getBufferHeight(bufferPtr);
3451
- const size = width * height;
3452
- const buffers = this.getBuffer(bufferPtr, size);
3453
- return new OptimizedBuffer(this, bufferPtr, buffers, width, height, {});
3454
- }
3455
- getCurrentBuffer(renderer) {
3456
- const bufferPtr = this.opentui.symbols.getCurrentBuffer(renderer);
3457
- if (!bufferPtr) {
3458
- throw new Error("Failed to get current buffer");
3459
- }
3460
- const width = this.opentui.symbols.getBufferWidth(bufferPtr);
3461
- const height = this.opentui.symbols.getBufferHeight(bufferPtr);
3462
- const size = width * height;
3463
- const buffers = this.getBuffer(bufferPtr, size);
3464
- return new OptimizedBuffer(this, bufferPtr, buffers, width, height, {});
3465
- }
3466
- getBuffer(bufferPtr, size) {
3467
- const charPtr = this.opentui.symbols.bufferGetCharPtr(bufferPtr);
3468
- const fgPtr = this.opentui.symbols.bufferGetFgPtr(bufferPtr);
3469
- const bgPtr = this.opentui.symbols.bufferGetBgPtr(bufferPtr);
3470
- const attributesPtr = this.opentui.symbols.bufferGetAttributesPtr(bufferPtr);
3471
- if (!charPtr || !fgPtr || !bgPtr || !attributesPtr) {
3472
- throw new Error("Failed to get buffer pointers");
3473
- }
3474
- const buffers = {
3475
- char: new Uint32Array(toArrayBuffer(charPtr, 0, size * 4)),
3476
- fg: new Float32Array(toArrayBuffer(fgPtr, 0, size * 4 * 4)),
3477
- bg: new Float32Array(toArrayBuffer(bgPtr, 0, size * 4 * 4)),
3478
- attributes: new Uint8Array(toArrayBuffer(attributesPtr, 0, size))
3479
- };
3480
- return buffers;
3481
- }
3482
- getTextBuffer(bufferPtr, size) {
3483
- const charPtr = this.opentui.symbols.textBufferGetCharPtr(bufferPtr);
3484
- const fgPtr = this.opentui.symbols.textBufferGetFgPtr(bufferPtr);
3485
- const bgPtr = this.opentui.symbols.textBufferGetBgPtr(bufferPtr);
3486
- const attributesPtr = this.opentui.symbols.textBufferGetAttributesPtr(bufferPtr);
3487
- if (!charPtr || !fgPtr || !bgPtr || !attributesPtr) {
3488
- throw new Error("Failed to get text buffer pointers");
3489
- }
3490
- const buffers = {
3491
- char: new Uint32Array(toArrayBuffer(charPtr, 0, size * 4)),
3492
- fg: new Float32Array(toArrayBuffer(fgPtr, 0, size * 4 * 4)),
3493
- bg: new Float32Array(toArrayBuffer(bgPtr, 0, size * 4 * 4)),
3494
- attributes: new Uint16Array(toArrayBuffer(attributesPtr, 0, size * 2))
3495
- };
3496
- return buffers;
3497
- }
3498
- bufferGetCharPtr(buffer) {
3499
- const ptr = this.opentui.symbols.bufferGetCharPtr(buffer);
3500
- if (!ptr) {
3501
- throw new Error("Failed to get char pointer");
3502
- }
3503
- return ptr;
3504
- }
3505
- bufferGetFgPtr(buffer) {
3506
- const ptr = this.opentui.symbols.bufferGetFgPtr(buffer);
3507
- if (!ptr) {
3508
- throw new Error("Failed to get fg pointer");
3509
- }
3510
- return ptr;
3511
- }
3512
- bufferGetBgPtr(buffer) {
3513
- const ptr = this.opentui.symbols.bufferGetBgPtr(buffer);
3514
- if (!ptr) {
3515
- throw new Error("Failed to get bg pointer");
3516
- }
3517
- return ptr;
3518
- }
3519
- bufferGetAttributesPtr(buffer) {
3520
- const ptr = this.opentui.symbols.bufferGetAttributesPtr(buffer);
3521
- if (!ptr) {
3522
- throw new Error("Failed to get attributes pointer");
3523
- }
3524
- return ptr;
3525
- }
3526
- bufferGetRespectAlpha(buffer) {
3527
- return this.opentui.symbols.bufferGetRespectAlpha(buffer);
3528
- }
3529
- bufferSetRespectAlpha(buffer, respectAlpha) {
3530
- this.opentui.symbols.bufferSetRespectAlpha(buffer, respectAlpha);
3531
- }
3532
- getBufferWidth(buffer) {
3533
- return this.opentui.symbols.getBufferWidth(buffer);
3534
- }
3535
- getBufferHeight(buffer) {
3536
- return this.opentui.symbols.getBufferHeight(buffer);
3537
- }
3538
- bufferClear(buffer, color) {
3539
- this.opentui.symbols.bufferClear(buffer, color.buffer);
3540
- }
3541
- bufferDrawText(buffer, text, x, y, color, bgColor, attributes) {
3542
- const textBytes = this.encoder.encode(text);
3543
- const textLength = textBytes.byteLength;
3544
- const bg = bgColor ? bgColor.buffer : null;
3545
- const fg = color.buffer;
3546
- this.opentui.symbols.bufferDrawText(buffer, textBytes, textLength, x, y, fg, bg, attributes ?? 0);
3547
- }
3548
- bufferSetCellWithAlphaBlending(buffer, x, y, char, color, bgColor, attributes) {
3549
- const charPtr = char.codePointAt(0) ?? " ".codePointAt(0);
3550
- const bg = bgColor.buffer;
3551
- const fg = color.buffer;
3552
- this.opentui.symbols.bufferSetCellWithAlphaBlending(buffer, x, y, charPtr, fg, bg, attributes ?? 0);
3553
- }
3554
- bufferFillRect(buffer, x, y, width, height, color) {
3555
- const bg = color.buffer;
3556
- this.opentui.symbols.bufferFillRect(buffer, x, y, width, height, bg);
3557
- }
3558
- bufferDrawSuperSampleBuffer(buffer, x, y, pixelDataPtr, pixelDataLength, format, alignedBytesPerRow) {
3559
- const formatId = format === "bgra8unorm" ? 0 : 1;
3560
- this.opentui.symbols.bufferDrawSuperSampleBuffer(buffer, x, y, pixelDataPtr, pixelDataLength, formatId, alignedBytesPerRow);
3561
- }
3562
- bufferDrawPackedBuffer(buffer, dataPtr, dataLen, posX, posY, terminalWidthCells, terminalHeightCells) {
3563
- this.opentui.symbols.bufferDrawPackedBuffer(buffer, dataPtr, dataLen, posX, posY, terminalWidthCells, terminalHeightCells);
3564
- }
3565
- bufferDrawBox(buffer, x, y, width, height, borderChars, packedOptions, borderColor, backgroundColor, title) {
3566
- const titleBytes = title ? this.encoder.encode(title) : null;
3567
- const titleLen = title ? titleBytes.length : 0;
3568
- const titlePtr = title ? titleBytes : null;
3569
- this.opentui.symbols.bufferDrawBox(buffer, x, y, width, height, borderChars, packedOptions, borderColor.buffer, backgroundColor.buffer, titlePtr, titleLen);
3570
- }
3571
- bufferResize(buffer, width, height) {
3572
- this.opentui.symbols.bufferResize(buffer, width, height);
3573
- const buffers = this.getBuffer(buffer, width * height);
3574
- return buffers;
3575
- }
3576
- resizeRenderer(renderer, width, height) {
3577
- this.opentui.symbols.resizeRenderer(renderer, width, height);
3578
- }
3579
- setCursorPosition(x, y, visible) {
3580
- this.opentui.symbols.setCursorPosition(x, y, visible);
3581
- }
3582
- setCursorStyle(style, blinking) {
3583
- const stylePtr = this.encoder.encode(style);
3584
- this.opentui.symbols.setCursorStyle(stylePtr, style.length, blinking);
3585
- }
3586
- setCursorColor(color) {
3587
- this.opentui.symbols.setCursorColor(color.buffer);
3588
- }
3589
- render(renderer, force) {
3590
- this.opentui.symbols.render(renderer, force);
3591
- }
3592
- createOptimizedBuffer(width, height, respectAlpha = false) {
3593
- if (Number.isNaN(width) || Number.isNaN(height)) {
3594
- console.error(new Error(`Invalid dimensions for OptimizedBuffer: ${width}x${height}`).stack);
3595
- }
3596
- const bufferPtr = this.opentui.symbols.createOptimizedBuffer(width, height, respectAlpha);
3597
- if (!bufferPtr) {
3598
- throw new Error(`Failed to create optimized buffer: ${width}x${height}`);
3599
- }
3600
- const size = width * height;
3601
- const buffers = this.getBuffer(bufferPtr, size);
3602
- return new OptimizedBuffer(this, bufferPtr, buffers, width, height, { respectAlpha });
3603
- }
3604
- destroyOptimizedBuffer(bufferPtr) {
3605
- this.opentui.symbols.destroyOptimizedBuffer(bufferPtr);
3606
- }
3607
- drawFrameBuffer(targetBufferPtr, destX, destY, bufferPtr, sourceX, sourceY, sourceWidth, sourceHeight) {
3608
- const srcX = sourceX ?? 0;
3609
- const srcY = sourceY ?? 0;
3610
- const srcWidth = sourceWidth ?? 0;
3611
- const srcHeight = sourceHeight ?? 0;
3612
- this.opentui.symbols.drawFrameBuffer(targetBufferPtr, destX, destY, bufferPtr, srcX, srcY, srcWidth, srcHeight);
3613
- }
3614
- setDebugOverlay(renderer, enabled, corner) {
3615
- this.opentui.symbols.setDebugOverlay(renderer, enabled, corner);
3616
- }
3617
- clearTerminal(renderer) {
3618
- this.opentui.symbols.clearTerminal(renderer);
3619
- }
3620
- addToHitGrid(renderer, x, y, width, height, id) {
3621
- this.opentui.symbols.addToHitGrid(renderer, x, y, width, height, id);
3622
- }
3623
- checkHit(renderer, x, y) {
3624
- return this.opentui.symbols.checkHit(renderer, x, y);
3625
- }
3626
- dumpHitGrid(renderer) {
3627
- this.opentui.symbols.dumpHitGrid(renderer);
3628
- }
3629
- dumpBuffers(renderer, timestamp) {
3630
- const ts = timestamp ?? Date.now();
3631
- this.opentui.symbols.dumpBuffers(renderer, ts);
3632
- }
3633
- dumpStdoutBuffer(renderer, timestamp) {
3634
- const ts = timestamp ?? Date.now();
3635
- this.opentui.symbols.dumpStdoutBuffer(renderer, ts);
3636
- }
3637
- createTextBuffer(capacity) {
3638
- const bufferPtr = this.opentui.symbols.createTextBuffer(capacity);
3639
- if (!bufferPtr) {
3640
- throw new Error(`Failed to create TextBuffer with capacity ${capacity}`);
3641
- }
3642
- const charPtr = this.textBufferGetCharPtr(bufferPtr);
3643
- const fgPtr = this.textBufferGetFgPtr(bufferPtr);
3644
- const bgPtr = this.textBufferGetBgPtr(bufferPtr);
3645
- const attributesPtr = this.textBufferGetAttributesPtr(bufferPtr);
3646
- const buffer = {
3647
- char: new Uint32Array(toArrayBuffer(charPtr, 0, capacity * 4)),
3648
- fg: new Float32Array(toArrayBuffer(fgPtr, 0, capacity * 4 * 4)),
3649
- bg: new Float32Array(toArrayBuffer(bgPtr, 0, capacity * 4 * 4)),
3650
- attributes: new Uint16Array(toArrayBuffer(attributesPtr, 0, capacity * 2))
3651
- };
3652
- return new TextBuffer(this, bufferPtr, buffer, capacity);
3653
- }
3654
- destroyTextBuffer(buffer) {
3655
- this.opentui.symbols.destroyTextBuffer(buffer);
3656
- }
3657
- textBufferGetCharPtr(buffer) {
3658
- const ptr = this.opentui.symbols.textBufferGetCharPtr(buffer);
3659
- if (!ptr) {
3660
- throw new Error("Failed to get TextBuffer char pointer");
3661
- }
3662
- return ptr;
3663
- }
3664
- textBufferGetFgPtr(buffer) {
3665
- const ptr = this.opentui.symbols.textBufferGetFgPtr(buffer);
3666
- if (!ptr) {
3667
- throw new Error("Failed to get TextBuffer fg pointer");
3668
- }
3669
- return ptr;
3670
- }
3671
- textBufferGetBgPtr(buffer) {
3672
- const ptr = this.opentui.symbols.textBufferGetBgPtr(buffer);
3673
- if (!ptr) {
3674
- throw new Error("Failed to get TextBuffer bg pointer");
3675
- }
3676
- return ptr;
3677
- }
3678
- textBufferGetAttributesPtr(buffer) {
3679
- const ptr = this.opentui.symbols.textBufferGetAttributesPtr(buffer);
3680
- if (!ptr) {
3681
- throw new Error("Failed to get TextBuffer attributes pointer");
3682
- }
3683
- return ptr;
3684
- }
3685
- textBufferGetLength(buffer) {
3686
- return this.opentui.symbols.textBufferGetLength(buffer);
3687
- }
3688
- textBufferSetCell(buffer, index, char, fg, bg, attr) {
3689
- this.opentui.symbols.textBufferSetCell(buffer, index, char, fg, bg, attr);
3690
- }
3691
- textBufferConcat(buffer1, buffer2) {
3692
- const resultPtr = this.opentui.symbols.textBufferConcat(buffer1, buffer2);
3693
- if (!resultPtr) {
3694
- throw new Error("Failed to concatenate TextBuffers");
3695
- }
3696
- const length = this.textBufferGetLength(resultPtr);
3697
- const charPtr = this.textBufferGetCharPtr(resultPtr);
3698
- const fgPtr = this.textBufferGetFgPtr(resultPtr);
3699
- const bgPtr = this.textBufferGetBgPtr(resultPtr);
3700
- const attributesPtr = this.textBufferGetAttributesPtr(resultPtr);
3701
- const buffer = {
3702
- char: new Uint32Array(toArrayBuffer(charPtr, 0, length * 4)),
3703
- fg: new Float32Array(toArrayBuffer(fgPtr, 0, length * 4 * 4)),
3704
- bg: new Float32Array(toArrayBuffer(bgPtr, 0, length * 4 * 4)),
3705
- attributes: new Uint16Array(toArrayBuffer(attributesPtr, 0, length * 2))
3706
- };
3707
- return new TextBuffer(this, resultPtr, buffer, length);
3708
- }
3709
- textBufferResize(buffer, newLength) {
3710
- this.opentui.symbols.textBufferResize(buffer, newLength);
3711
- const buffers = this.getTextBuffer(buffer, newLength);
3712
- return buffers;
3713
- }
3714
- textBufferReset(buffer) {
3715
- this.opentui.symbols.textBufferReset(buffer);
3716
- }
3717
- textBufferSetSelection(buffer, start, end, bgColor, fgColor) {
3718
- const bg = bgColor ? bgColor.buffer : null;
3719
- const fg = fgColor ? fgColor.buffer : null;
3720
- this.opentui.symbols.textBufferSetSelection(buffer, start, end, bg, fg);
3721
- }
3722
- textBufferResetSelection(buffer) {
3723
- this.opentui.symbols.textBufferResetSelection(buffer);
3724
- }
3725
- textBufferSetDefaultFg(buffer, fg) {
3726
- const fgPtr = fg ? fg.buffer : null;
3727
- this.opentui.symbols.textBufferSetDefaultFg(buffer, fgPtr);
3728
- }
3729
- textBufferSetDefaultBg(buffer, bg) {
3730
- const bgPtr = bg ? bg.buffer : null;
3731
- this.opentui.symbols.textBufferSetDefaultBg(buffer, bgPtr);
3732
- }
3733
- textBufferSetDefaultAttributes(buffer, attributes) {
3734
- const attrValue = attributes === null ? null : new Uint8Array([attributes]);
3735
- this.opentui.symbols.textBufferSetDefaultAttributes(buffer, attrValue);
3736
- }
3737
- textBufferResetDefaults(buffer) {
3738
- this.opentui.symbols.textBufferResetDefaults(buffer);
3739
- }
3740
- textBufferWriteChunk(buffer, textBytes, fg, bg, attributes) {
3741
- const attrValue = attributes === null ? null : new Uint8Array([attributes]);
3742
- return this.opentui.symbols.textBufferWriteChunk(buffer, textBytes, textBytes.length, fg ? fg.buffer : null, bg ? bg.buffer : null, attrValue);
3743
- }
3744
- textBufferGetCapacity(buffer) {
3745
- return this.opentui.symbols.textBufferGetCapacity(buffer);
3746
- }
3747
- textBufferFinalizeLineInfo(buffer) {
3748
- this.opentui.symbols.textBufferFinalizeLineInfo(buffer);
3749
- }
3750
- textBufferGetLineInfo(buffer) {
3751
- const lineCount = this.opentui.symbols.textBufferGetLineCount(buffer);
3752
- if (lineCount === 0) {
3753
- return { lineStarts: [], lineWidths: [] };
3754
- }
3755
- const lineStartsPtr = this.opentui.symbols.textBufferGetLineStartsPtr(buffer);
3756
- const lineWidthsPtr = this.opentui.symbols.textBufferGetLineWidthsPtr(buffer);
3757
- if (!lineStartsPtr || !lineWidthsPtr) {
3758
- return { lineStarts: [], lineWidths: [] };
3759
- }
3760
- const lineStartsArray = new Uint32Array(toArrayBuffer(lineStartsPtr, 0, lineCount * 4));
3761
- const lineWidthsArray = new Uint32Array(toArrayBuffer(lineWidthsPtr, 0, lineCount * 4));
3762
- const lineStarts = Array.from(lineStartsArray);
3763
- const lineWidths = Array.from(lineWidthsArray);
3764
- return { lineStarts, lineWidths };
3765
- }
3766
- getTextBufferArrays(buffer, size) {
3767
- return this.getTextBuffer(buffer, size);
3768
- }
3769
- bufferDrawTextBuffer(buffer, textBuffer, x, y, clipRect) {
3770
- const hasClipRect = clipRect !== undefined && clipRect !== null;
3771
- const clipX = clipRect?.x ?? 0;
3772
- const clipY = clipRect?.y ?? 0;
3773
- const clipWidth = clipRect?.width ?? 0;
3774
- const clipHeight = clipRect?.height ?? 0;
3775
- this.opentui.symbols.bufferDrawTextBuffer(buffer, textBuffer, x, y, clipX, clipY, clipWidth, clipHeight, hasClipRect);
3776
- }
3777
- }
3778
- var opentuiLibPath;
3779
- var opentuiLib;
3780
- function setRenderLibPath(libPath) {
3781
- opentuiLibPath = libPath;
3782
- }
3783
- function resolveRenderLib() {
3784
- if (!opentuiLib) {
3785
- opentuiLib = new FFIRenderLib(opentuiLibPath);
3786
- }
3787
- return opentuiLib;
3788
- }
3789
-
3790
- // src/lib/border.ts
3791
- var BorderChars = {
3792
- single: {
3793
- topLeft: "\u250C",
3794
- topRight: "\u2510",
3795
- bottomLeft: "\u2514",
3796
- bottomRight: "\u2518",
3797
- horizontal: "\u2500",
3798
- vertical: "\u2502",
3799
- topT: "\u252C",
3800
- bottomT: "\u2534",
3801
- leftT: "\u251C",
3802
- rightT: "\u2524",
3803
- cross: "\u253C"
3804
- },
3805
- double: {
3806
- topLeft: "\u2554",
3807
- topRight: "\u2557",
3808
- bottomLeft: "\u255A",
3809
- bottomRight: "\u255D",
3810
- horizontal: "\u2550",
3811
- vertical: "\u2551",
3812
- topT: "\u2566",
3813
- bottomT: "\u2569",
3814
- leftT: "\u2560",
3815
- rightT: "\u2563",
3816
- cross: "\u256C"
3817
- },
3818
- rounded: {
3819
- topLeft: "\u256D",
3820
- topRight: "\u256E",
3821
- bottomLeft: "\u2570",
3822
- bottomRight: "\u256F",
3823
- horizontal: "\u2500",
3824
- vertical: "\u2502",
3825
- topT: "\u252C",
3826
- bottomT: "\u2534",
3827
- leftT: "\u251C",
3828
- rightT: "\u2524",
3829
- cross: "\u253C"
3830
- },
3831
- heavy: {
3832
- topLeft: "\u250F",
3833
- topRight: "\u2513",
3834
- bottomLeft: "\u2517",
3835
- bottomRight: "\u251B",
3836
- horizontal: "\u2501",
3837
- vertical: "\u2503",
3838
- topT: "\u2533",
3839
- bottomT: "\u253B",
3840
- leftT: "\u2523",
3841
- rightT: "\u252B",
3842
- cross: "\u254B"
3843
- }
3844
- };
3845
- function getBorderFromSides(sides) {
3846
- const result = [];
3847
- if (sides.top)
3848
- result.push("top");
3849
- if (sides.right)
3850
- result.push("right");
3851
- if (sides.bottom)
3852
- result.push("bottom");
3853
- if (sides.left)
3854
- result.push("left");
3855
- return result.length > 0 ? result : false;
3856
- }
3857
- function getBorderSides(border) {
3858
- return border === true ? { top: true, right: true, bottom: true, left: true } : Array.isArray(border) ? {
3859
- top: border.includes("top"),
3860
- right: border.includes("right"),
3861
- bottom: border.includes("bottom"),
3862
- left: border.includes("left")
3863
- } : { top: false, right: false, bottom: false, left: false };
3864
- }
3865
- function borderCharsToArray(chars) {
3866
- const array = new Uint32Array(11);
3867
- array[0] = chars.topLeft.codePointAt(0);
3868
- array[1] = chars.topRight.codePointAt(0);
3869
- array[2] = chars.bottomLeft.codePointAt(0);
3870
- array[3] = chars.bottomRight.codePointAt(0);
3871
- array[4] = chars.horizontal.codePointAt(0);
3872
- array[5] = chars.vertical.codePointAt(0);
3873
- array[6] = chars.topT.codePointAt(0);
3874
- array[7] = chars.bottomT.codePointAt(0);
3875
- array[8] = chars.leftT.codePointAt(0);
3876
- array[9] = chars.rightT.codePointAt(0);
3877
- array[10] = chars.cross.codePointAt(0);
3878
- return array;
3879
- }
3880
- var BorderCharArrays = {
3881
- single: borderCharsToArray(BorderChars.single),
3882
- double: borderCharsToArray(BorderChars.double),
3883
- rounded: borderCharsToArray(BorderChars.rounded),
3884
- heavy: borderCharsToArray(BorderChars.heavy)
3885
- };
3886
3476
  // src/lib/fonts/tiny.json
3887
3477
  var tiny_default = {
3888
3478
  name: "tiny",
@@ -5272,526 +4862,1633 @@ var slick_default = {
5272
4862
  '"': ["<c1>\u256D\u256E\u256D\u256E</c1>", "<c1>\u2570\u256F\u2570\u256F</c1>", "<c2>\u2571\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571\u2571</c2>"],
5273
4863
  " ": ["<c2>\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571</c2>"]
5274
4864
  }
5275
- };
4865
+ };
4866
+
4867
+ // src/lib/ascii.font.ts
4868
+ var fonts = {
4869
+ tiny: tiny_default,
4870
+ block: block_default,
4871
+ shade: shade_default,
4872
+ slick: slick_default
4873
+ };
4874
+ var parsedFonts = {};
4875
+ function parseColorTags(text) {
4876
+ const segments = [];
4877
+ let currentIndex = 0;
4878
+ const colorTagRegex = /<c(\d+)>(.*?)<\/c\d+>/g;
4879
+ let lastIndex = 0;
4880
+ let match;
4881
+ while ((match = colorTagRegex.exec(text)) !== null) {
4882
+ if (match.index > lastIndex) {
4883
+ const plainText = text.slice(lastIndex, match.index);
4884
+ if (plainText) {
4885
+ segments.push({ text: plainText, colorIndex: 0 });
4886
+ }
4887
+ }
4888
+ const colorIndex = parseInt(match[1]) - 1;
4889
+ const taggedText = match[2];
4890
+ segments.push({ text: taggedText, colorIndex: Math.max(0, colorIndex) });
4891
+ lastIndex = match.index + match[0].length;
4892
+ }
4893
+ if (lastIndex < text.length) {
4894
+ const remainingText = text.slice(lastIndex);
4895
+ if (remainingText) {
4896
+ segments.push({ text: remainingText, colorIndex: 0 });
4897
+ }
4898
+ }
4899
+ return segments;
4900
+ }
4901
+ function getParsedFont(fontKey) {
4902
+ if (!parsedFonts[fontKey]) {
4903
+ const fontDef = fonts[fontKey];
4904
+ const parsedChars = {};
4905
+ for (const [char, lines] of Object.entries(fontDef.chars)) {
4906
+ parsedChars[char] = lines.map((line) => parseColorTags(line));
4907
+ }
4908
+ parsedFonts[fontKey] = {
4909
+ ...fontDef,
4910
+ colors: fontDef.colors || 1,
4911
+ chars: parsedChars
4912
+ };
4913
+ }
4914
+ return parsedFonts[fontKey];
4915
+ }
4916
+ function measureText({ text, font = "tiny" }) {
4917
+ const fontDef = getParsedFont(font);
4918
+ if (!fontDef) {
4919
+ console.warn(`Font '${font}' not found`);
4920
+ return { width: 0, height: 0 };
4921
+ }
4922
+ let currentX = 0;
4923
+ for (let i = 0;i < text.length; i++) {
4924
+ const char = text[i].toUpperCase();
4925
+ const charDef = fontDef.chars[char];
4926
+ if (!charDef) {
4927
+ const spaceChar = fontDef.chars[" "];
4928
+ if (spaceChar && spaceChar[0]) {
4929
+ let spaceWidth = 0;
4930
+ for (const segment of spaceChar[0]) {
4931
+ spaceWidth += segment.text.length;
4932
+ }
4933
+ currentX += spaceWidth;
4934
+ } else {
4935
+ currentX += 1;
4936
+ }
4937
+ continue;
4938
+ }
4939
+ let charWidth = 0;
4940
+ if (charDef[0]) {
4941
+ for (const segment of charDef[0]) {
4942
+ charWidth += segment.text.length;
4943
+ }
4944
+ }
4945
+ currentX += charWidth;
4946
+ if (i < text.length - 1) {
4947
+ currentX += fontDef.letterspace_size;
4948
+ }
4949
+ }
4950
+ return {
4951
+ width: currentX,
4952
+ height: fontDef.lines
4953
+ };
4954
+ }
4955
+ function getCharacterPositions(text, font = "tiny") {
4956
+ const fontDef = getParsedFont(font);
4957
+ if (!fontDef) {
4958
+ return [0];
4959
+ }
4960
+ const positions = [0];
4961
+ let currentX = 0;
4962
+ for (let i = 0;i < text.length; i++) {
4963
+ const char = text[i].toUpperCase();
4964
+ const charDef = fontDef.chars[char];
4965
+ let charWidth = 0;
4966
+ if (!charDef) {
4967
+ const spaceChar = fontDef.chars[" "];
4968
+ if (spaceChar && spaceChar[0]) {
4969
+ for (const segment of spaceChar[0]) {
4970
+ charWidth += segment.text.length;
4971
+ }
4972
+ } else {
4973
+ charWidth = 1;
4974
+ }
4975
+ } else if (charDef[0]) {
4976
+ for (const segment of charDef[0]) {
4977
+ charWidth += segment.text.length;
4978
+ }
4979
+ }
4980
+ currentX += charWidth;
4981
+ if (i < text.length - 1) {
4982
+ currentX += fontDef.letterspace_size;
4983
+ }
4984
+ positions.push(currentX);
4985
+ }
4986
+ return positions;
4987
+ }
4988
+ function coordinateToCharacterIndex(x, text, font = "tiny") {
4989
+ const positions = getCharacterPositions(text, font);
4990
+ if (x < 0) {
4991
+ return 0;
4992
+ }
4993
+ for (let i = 0;i < positions.length - 1; i++) {
4994
+ const currentPos = positions[i];
4995
+ const nextPos = positions[i + 1];
4996
+ if (x >= currentPos && x < nextPos) {
4997
+ const charMidpoint = currentPos + (nextPos - currentPos) / 2;
4998
+ return x < charMidpoint ? i : i + 1;
4999
+ }
5000
+ }
5001
+ if (positions.length > 0 && x >= positions[positions.length - 1]) {
5002
+ return text.length;
5003
+ }
5004
+ return 0;
5005
+ }
5006
+ function renderFontToFrameBuffer(buffer, {
5007
+ text,
5008
+ x = 0,
5009
+ y = 0,
5010
+ fg = [RGBA.fromInts(255, 255, 255, 255)],
5011
+ bg = RGBA.fromInts(0, 0, 0, 255),
5012
+ font = "tiny"
5013
+ }) {
5014
+ const width = buffer.getWidth();
5015
+ const height = buffer.getHeight();
5016
+ const fontDef = getParsedFont(font);
5017
+ if (!fontDef) {
5018
+ console.warn(`Font '${font}' not found`);
5019
+ return { width: 0, height: 0 };
5020
+ }
5021
+ const colors = Array.isArray(fg) ? fg : [fg];
5022
+ if (y < 0 || y + fontDef.lines > height) {
5023
+ return { width: 0, height: fontDef.lines };
5024
+ }
5025
+ let currentX = x;
5026
+ const startX = x;
5027
+ for (let i = 0;i < text.length; i++) {
5028
+ const char = text[i].toUpperCase();
5029
+ const charDef = fontDef.chars[char];
5030
+ if (!charDef) {
5031
+ const spaceChar = fontDef.chars[" "];
5032
+ if (spaceChar && spaceChar[0]) {
5033
+ let spaceWidth = 0;
5034
+ for (const segment of spaceChar[0]) {
5035
+ spaceWidth += segment.text.length;
5036
+ }
5037
+ currentX += spaceWidth;
5038
+ } else {
5039
+ currentX += 1;
5040
+ }
5041
+ continue;
5042
+ }
5043
+ let charWidth = 0;
5044
+ if (charDef[0]) {
5045
+ for (const segment of charDef[0]) {
5046
+ charWidth += segment.text.length;
5047
+ }
5048
+ }
5049
+ if (currentX >= width)
5050
+ break;
5051
+ if (currentX + charWidth < 0) {
5052
+ currentX += charWidth + fontDef.letterspace_size;
5053
+ continue;
5054
+ }
5055
+ for (let lineIdx = 0;lineIdx < fontDef.lines && lineIdx < charDef.length; lineIdx++) {
5056
+ const segments = charDef[lineIdx];
5057
+ const renderY = y + lineIdx;
5058
+ if (renderY >= 0 && renderY < height) {
5059
+ let segmentX = currentX;
5060
+ for (const segment of segments) {
5061
+ const segmentColor = colors[segment.colorIndex] || colors[0];
5062
+ for (let charIdx = 0;charIdx < segment.text.length; charIdx++) {
5063
+ const renderX = segmentX + charIdx;
5064
+ if (renderX >= 0 && renderX < width) {
5065
+ const fontChar = segment.text[charIdx];
5066
+ if (fontChar !== " ") {
5067
+ buffer.setCell(renderX, renderY, fontChar, segmentColor, bg);
5068
+ }
5069
+ }
5070
+ }
5071
+ segmentX += segment.text.length;
5072
+ }
5073
+ }
5074
+ }
5075
+ currentX += charWidth;
5076
+ if (i < text.length - 1) {
5077
+ currentX += fontDef.letterspace_size;
5078
+ }
5079
+ }
5080
+ return {
5081
+ width: currentX - startX,
5082
+ height: fontDef.lines
5083
+ };
5084
+ }
5085
+ // src/lib/styled-text.ts
5086
+ var textEncoder = new TextEncoder;
5087
+
5088
+ class StyledText {
5089
+ chunks;
5090
+ _plainText = "";
5091
+ constructor(chunks) {
5092
+ this.chunks = chunks;
5093
+ for (let i = 0;i < chunks.length; i++) {
5094
+ this._plainText += chunks[i].plainText;
5095
+ }
5096
+ }
5097
+ toString() {
5098
+ return this._plainText;
5099
+ }
5100
+ static _createInstance(chunks, plainText) {
5101
+ const newInstance = Object.create(StyledText.prototype);
5102
+ newInstance.chunks = chunks;
5103
+ newInstance._plainText = plainText;
5104
+ return newInstance;
5105
+ }
5106
+ static _chunksToPlainText(chunks) {
5107
+ let plainText = "";
5108
+ for (const chunk of chunks) {
5109
+ plainText += chunk.plainText;
5110
+ }
5111
+ return plainText;
5112
+ }
5113
+ insert(chunk, index) {
5114
+ const originalLength = this.chunks.length;
5115
+ let newChunks;
5116
+ let newPlainText;
5117
+ if (index === undefined) {
5118
+ newChunks = [...this.chunks, chunk];
5119
+ newPlainText = this._plainText + chunk.plainText;
5120
+ } else if (index === originalLength) {
5121
+ newChunks = [...this.chunks, chunk];
5122
+ newPlainText = this._plainText + chunk.plainText;
5123
+ } else {
5124
+ newChunks = [...this.chunks.slice(0, index), chunk, ...this.chunks.slice(index)];
5125
+ newPlainText = StyledText._chunksToPlainText(newChunks);
5126
+ }
5127
+ return StyledText._createInstance(newChunks, newPlainText);
5128
+ }
5129
+ remove(chunk) {
5130
+ const originalLength = this.chunks.length;
5131
+ const index = this.chunks.indexOf(chunk);
5132
+ if (index === -1)
5133
+ return this;
5134
+ let newChunks;
5135
+ let newPlainText;
5136
+ if (index === originalLength - 1) {
5137
+ newChunks = this.chunks.slice(0, -1);
5138
+ newPlainText = this._plainText.slice(0, this._plainText.length - chunk.plainText.length);
5139
+ } else {
5140
+ newChunks = [...this.chunks.slice(0, index), ...this.chunks.slice(index + 1)];
5141
+ newPlainText = StyledText._chunksToPlainText(newChunks);
5142
+ }
5143
+ return StyledText._createInstance(newChunks, newPlainText);
5144
+ }
5145
+ replace(chunk, oldChunk) {
5146
+ const index = this.chunks.indexOf(oldChunk);
5147
+ if (index === -1)
5148
+ return this;
5149
+ let newChunks;
5150
+ let newPlainText;
5151
+ if (index === this.chunks.length - 1) {
5152
+ newChunks = [...this.chunks.slice(0, -1), chunk];
5153
+ newPlainText = this._plainText.slice(0, this._plainText.length - oldChunk.plainText.length) + chunk.plainText;
5154
+ } else {
5155
+ newChunks = [...this.chunks.slice(0, index), chunk, ...this.chunks.slice(index + 1)];
5156
+ newPlainText = StyledText._chunksToPlainText(newChunks);
5157
+ }
5158
+ return StyledText._createInstance(newChunks, newPlainText);
5159
+ }
5160
+ }
5161
+ function stringToStyledText(content) {
5162
+ const textEncoder2 = new TextEncoder;
5163
+ const chunk = {
5164
+ __isChunk: true,
5165
+ text: textEncoder2.encode(content),
5166
+ plainText: content
5167
+ };
5168
+ return new StyledText([chunk]);
5169
+ }
5170
+ var templateCache = new WeakMap;
5171
+ function applyStyle(input, style) {
5172
+ if (typeof input === "object" && "__isChunk" in input) {
5173
+ const existingChunk = input;
5174
+ const fg = style.fg ? parseColor(style.fg) : existingChunk.fg;
5175
+ const bg = style.bg ? parseColor(style.bg) : existingChunk.bg;
5176
+ const newAttrs = createTextAttributes(style);
5177
+ const mergedAttrs = existingChunk.attributes ? existingChunk.attributes | newAttrs : newAttrs;
5178
+ return {
5179
+ __isChunk: true,
5180
+ text: existingChunk.text,
5181
+ plainText: existingChunk.plainText,
5182
+ fg,
5183
+ bg,
5184
+ attributes: mergedAttrs
5185
+ };
5186
+ } else {
5187
+ const plainTextStr = String(input);
5188
+ const text = textEncoder.encode(plainTextStr);
5189
+ const fg = style.fg ? parseColor(style.fg) : undefined;
5190
+ const bg = style.bg ? parseColor(style.bg) : undefined;
5191
+ const attributes = createTextAttributes(style);
5192
+ return {
5193
+ __isChunk: true,
5194
+ text,
5195
+ plainText: plainTextStr,
5196
+ fg,
5197
+ bg,
5198
+ attributes
5199
+ };
5200
+ }
5201
+ }
5202
+ var black = (input) => applyStyle(input, { fg: "black" });
5203
+ var red = (input) => applyStyle(input, { fg: "red" });
5204
+ var green = (input) => applyStyle(input, { fg: "green" });
5205
+ var yellow = (input) => applyStyle(input, { fg: "yellow" });
5206
+ var blue = (input) => applyStyle(input, { fg: "blue" });
5207
+ var magenta = (input) => applyStyle(input, { fg: "magenta" });
5208
+ var cyan = (input) => applyStyle(input, { fg: "cyan" });
5209
+ var white = (input) => applyStyle(input, { fg: "white" });
5210
+ var brightBlack = (input) => applyStyle(input, { fg: "brightBlack" });
5211
+ var brightRed = (input) => applyStyle(input, { fg: "brightRed" });
5212
+ var brightGreen = (input) => applyStyle(input, { fg: "brightGreen" });
5213
+ var brightYellow = (input) => applyStyle(input, { fg: "brightYellow" });
5214
+ var brightBlue = (input) => applyStyle(input, { fg: "brightBlue" });
5215
+ var brightMagenta = (input) => applyStyle(input, { fg: "brightMagenta" });
5216
+ var brightCyan = (input) => applyStyle(input, { fg: "brightCyan" });
5217
+ var brightWhite = (input) => applyStyle(input, { fg: "brightWhite" });
5218
+ var bgBlack = (input) => applyStyle(input, { bg: "black" });
5219
+ var bgRed = (input) => applyStyle(input, { bg: "red" });
5220
+ var bgGreen = (input) => applyStyle(input, { bg: "green" });
5221
+ var bgYellow = (input) => applyStyle(input, { bg: "yellow" });
5222
+ var bgBlue = (input) => applyStyle(input, { bg: "blue" });
5223
+ var bgMagenta = (input) => applyStyle(input, { bg: "magenta" });
5224
+ var bgCyan = (input) => applyStyle(input, { bg: "cyan" });
5225
+ var bgWhite = (input) => applyStyle(input, { bg: "white" });
5226
+ var bold = (input) => applyStyle(input, { bold: true });
5227
+ var italic = (input) => applyStyle(input, { italic: true });
5228
+ var underline = (input) => applyStyle(input, { underline: true });
5229
+ var strikethrough = (input) => applyStyle(input, { strikethrough: true });
5230
+ var dim = (input) => applyStyle(input, { dim: true });
5231
+ var reverse = (input) => applyStyle(input, { reverse: true });
5232
+ var blink = (input) => applyStyle(input, { blink: true });
5233
+ var fg = (color) => (input) => applyStyle(input, { fg: color });
5234
+ var bg = (color) => (input) => applyStyle(input, { bg: color });
5235
+ function tn(strings, ...values) {
5236
+ const chunks = [];
5237
+ let length = 0;
5238
+ let plainText = "";
5239
+ for (let i = 0;i < strings.length; i++) {
5240
+ const raw = strings[i];
5241
+ if (raw) {
5242
+ chunks.push({
5243
+ __isChunk: true,
5244
+ text: textEncoder.encode(raw),
5245
+ plainText: raw,
5246
+ attributes: 0
5247
+ });
5248
+ length += raw.length;
5249
+ plainText += raw;
5250
+ }
5251
+ const val = values[i];
5252
+ if (typeof val === "object" && "__isChunk" in val) {
5253
+ chunks.push(val);
5254
+ length += val.plainText.length;
5255
+ plainText += val.plainText;
5256
+ } else if (val !== undefined) {
5257
+ const plainTextStr = String(val);
5258
+ chunks.push({
5259
+ __isChunk: true,
5260
+ text: textEncoder.encode(plainTextStr),
5261
+ plainText: plainTextStr,
5262
+ attributes: 0
5263
+ });
5264
+ length += plainTextStr.length;
5265
+ plainText += plainTextStr;
5266
+ }
5267
+ }
5268
+ return new StyledText(chunks);
5269
+ }
5270
+ function t(strings, ...values) {
5271
+ let cachedStringChunks = templateCache.get(strings);
5272
+ let length = 0;
5273
+ let plainText = "";
5274
+ if (!cachedStringChunks) {
5275
+ cachedStringChunks = [];
5276
+ for (let i = 0;i < strings.length; i++) {
5277
+ const raw = strings[i];
5278
+ if (raw) {
5279
+ cachedStringChunks.push({
5280
+ __isChunk: true,
5281
+ text: textEncoder.encode(raw),
5282
+ plainText: raw,
5283
+ attributes: 0
5284
+ });
5285
+ } else {
5286
+ cachedStringChunks.push(null);
5287
+ }
5288
+ }
5289
+ templateCache.set(strings, cachedStringChunks);
5290
+ }
5291
+ const chunks = [];
5292
+ for (let i = 0;i < strings.length; i++) {
5293
+ const stringChunk = cachedStringChunks[i];
5294
+ if (stringChunk) {
5295
+ chunks.push(stringChunk);
5296
+ length += stringChunk.plainText.length;
5297
+ plainText += stringChunk.plainText;
5298
+ }
5299
+ const val = values[i];
5300
+ if (typeof val === "object" && "__isChunk" in val) {
5301
+ chunks.push(val);
5302
+ length += val.plainText.length;
5303
+ plainText += val.plainText;
5304
+ } else if (val !== undefined) {
5305
+ const plainTextStr = String(val);
5306
+ chunks.push({
5307
+ __isChunk: true,
5308
+ text: textEncoder.encode(plainTextStr),
5309
+ plainText: plainTextStr,
5310
+ attributes: 0
5311
+ });
5312
+ length += plainTextStr.length;
5313
+ plainText += plainTextStr;
5314
+ }
5315
+ }
5316
+ return new StyledText(chunks);
5317
+ }
5318
+
5319
+ // src/lib/hast-styled-text.ts
5320
+ class SyntaxStyle {
5321
+ styles;
5322
+ mergedStyleCache;
5323
+ constructor(styles) {
5324
+ this.styles = styles;
5325
+ this.mergedStyleCache = new Map;
5326
+ }
5327
+ mergeStyles(...styleNames) {
5328
+ const cacheKey = styleNames.join(":");
5329
+ const cached = this.mergedStyleCache.get(cacheKey);
5330
+ if (cached)
5331
+ return cached;
5332
+ const styleDefinition = {};
5333
+ for (const name of styleNames) {
5334
+ const style = this.styles[name];
5335
+ if (!style)
5336
+ continue;
5337
+ if (style.fg)
5338
+ styleDefinition.fg = style.fg;
5339
+ if (style.bg)
5340
+ styleDefinition.bg = style.bg;
5341
+ if (style.bold !== undefined)
5342
+ styleDefinition.bold = style.bold;
5343
+ if (style.italic !== undefined)
5344
+ styleDefinition.italic = style.italic;
5345
+ if (style.underline !== undefined)
5346
+ styleDefinition.underline = style.underline;
5347
+ if (style.dim !== undefined)
5348
+ styleDefinition.dim = style.dim;
5349
+ }
5350
+ const attributes = createTextAttributes({
5351
+ bold: styleDefinition.bold,
5352
+ italic: styleDefinition.italic,
5353
+ underline: styleDefinition.underline,
5354
+ dim: styleDefinition.dim
5355
+ });
5356
+ const merged = {
5357
+ fg: styleDefinition.fg,
5358
+ bg: styleDefinition.bg,
5359
+ attributes
5360
+ };
5361
+ this.mergedStyleCache.set(cacheKey, merged);
5362
+ return merged;
5363
+ }
5364
+ clearCache() {
5365
+ this.mergedStyleCache.clear();
5366
+ }
5367
+ getCacheSize() {
5368
+ return this.mergedStyleCache.size;
5369
+ }
5370
+ }
5371
+ var textEncoder2 = new TextEncoder;
5372
+ function hastToTextChunks(node, syntaxStyle, parentStyles = []) {
5373
+ const chunks = [];
5374
+ if (node.type === "text") {
5375
+ const stylesToMerge = parentStyles.length > 0 ? parentStyles : ["default"];
5376
+ const mergedStyle = syntaxStyle.mergeStyles(...stylesToMerge);
5377
+ chunks.push({
5378
+ __isChunk: true,
5379
+ text: textEncoder2.encode(node.value),
5380
+ plainText: node.value,
5381
+ fg: mergedStyle.fg,
5382
+ bg: mergedStyle.bg,
5383
+ attributes: mergedStyle.attributes
5384
+ });
5385
+ } else if (node.type === "element") {
5386
+ let currentStyles = [...parentStyles];
5387
+ if (node.properties?.className) {
5388
+ const classes = node.properties.className.split(" ");
5389
+ for (const cls of classes) {
5390
+ currentStyles.push(cls);
5391
+ }
5392
+ }
5393
+ for (const child of node.children) {
5394
+ chunks.push(...hastToTextChunks(child, syntaxStyle, currentStyles));
5395
+ }
5396
+ }
5397
+ return chunks;
5398
+ }
5399
+ function hastToStyledText(hast, syntaxStyle) {
5400
+ const chunks = hastToTextChunks(hast, syntaxStyle);
5401
+ return new StyledText(chunks);
5402
+ }
5403
+ // src/lib/parse.mouse.ts
5404
+ class MouseParser {
5405
+ mouseButtonsPressed = new Set;
5406
+ static SCROLL_DIRECTIONS = {
5407
+ 64: "up",
5408
+ 65: "down",
5409
+ 66: "left",
5410
+ 67: "right"
5411
+ };
5412
+ reset() {
5413
+ this.mouseButtonsPressed.clear();
5414
+ }
5415
+ parseMouseEvent(data) {
5416
+ const str = data.toString();
5417
+ const sgrMatch = str.match(/\x1b\[<(\d+);(\d+);(\d+)([Mm])/);
5418
+ if (sgrMatch) {
5419
+ const [, buttonCode, x, y, pressRelease] = sgrMatch;
5420
+ const rawButtonCode = parseInt(buttonCode);
5421
+ const scrollDirection = MouseParser.SCROLL_DIRECTIONS[rawButtonCode];
5422
+ const isScroll = scrollDirection !== undefined;
5423
+ const button = rawButtonCode & 3;
5424
+ const isMotion = (rawButtonCode & 32) !== 0;
5425
+ const modifiers = {
5426
+ shift: (rawButtonCode & 4) !== 0,
5427
+ alt: (rawButtonCode & 8) !== 0,
5428
+ ctrl: (rawButtonCode & 16) !== 0
5429
+ };
5430
+ let type;
5431
+ let scrollInfo;
5432
+ if (isScroll && pressRelease === "M") {
5433
+ type = "scroll";
5434
+ scrollInfo = {
5435
+ direction: scrollDirection,
5436
+ delta: 1
5437
+ };
5438
+ } else if (isMotion) {
5439
+ const isDragging = this.mouseButtonsPressed.size > 0;
5440
+ if (button === 3) {
5441
+ type = "move";
5442
+ } else if (isDragging) {
5443
+ type = "drag";
5444
+ } else {
5445
+ type = "move";
5446
+ }
5447
+ } else {
5448
+ type = pressRelease === "M" ? "down" : "up";
5449
+ if (type === "down" && button !== 3) {
5450
+ this.mouseButtonsPressed.add(button);
5451
+ } else if (type === "up") {
5452
+ this.mouseButtonsPressed.clear();
5453
+ }
5454
+ }
5455
+ return {
5456
+ type,
5457
+ button: button === 3 ? 0 : button,
5458
+ x: parseInt(x) - 1,
5459
+ y: parseInt(y) - 1,
5460
+ modifiers,
5461
+ scroll: scrollInfo
5462
+ };
5463
+ }
5464
+ if (str.startsWith("\x1B[M") && str.length >= 6) {
5465
+ const buttonByte = str.charCodeAt(3) - 32;
5466
+ const x = str.charCodeAt(4) - 33;
5467
+ const y = str.charCodeAt(5) - 33;
5468
+ const scrollDirection = MouseParser.SCROLL_DIRECTIONS[buttonByte];
5469
+ const isScroll = scrollDirection !== undefined;
5470
+ const button = buttonByte & 3;
5471
+ const modifiers = {
5472
+ shift: (buttonByte & 4) !== 0,
5473
+ alt: (buttonByte & 8) !== 0,
5474
+ ctrl: (buttonByte & 16) !== 0
5475
+ };
5476
+ let type;
5477
+ let actualButton;
5478
+ let scrollInfo;
5479
+ if (isScroll) {
5480
+ type = "scroll";
5481
+ actualButton = 0;
5482
+ scrollInfo = {
5483
+ direction: scrollDirection,
5484
+ delta: 1
5485
+ };
5486
+ } else {
5487
+ type = button === 3 ? "up" : "down";
5488
+ actualButton = button === 3 ? 0 : button;
5489
+ }
5490
+ return {
5491
+ type,
5492
+ button: actualButton,
5493
+ x,
5494
+ y,
5495
+ modifiers,
5496
+ scroll: scrollInfo
5497
+ };
5498
+ }
5499
+ return null;
5500
+ }
5501
+ }
5502
+ // src/lib/selection.ts
5503
+ class Selection {
5504
+ _anchor;
5505
+ _focus;
5506
+ _selectedRenderables = [];
5507
+ constructor(anchor, focus) {
5508
+ this._anchor = { ...anchor };
5509
+ this._focus = { ...focus };
5510
+ }
5511
+ get anchor() {
5512
+ return { ...this._anchor };
5513
+ }
5514
+ get focus() {
5515
+ return { ...this._focus };
5516
+ }
5517
+ get bounds() {
5518
+ return {
5519
+ startX: Math.min(this._anchor.x, this._focus.x),
5520
+ startY: Math.min(this._anchor.y, this._focus.y),
5521
+ endX: Math.max(this._anchor.x, this._focus.x),
5522
+ endY: Math.max(this._anchor.y, this._focus.y)
5523
+ };
5524
+ }
5525
+ updateSelectedRenderables(selectedRenderables) {
5526
+ this._selectedRenderables = selectedRenderables;
5527
+ }
5528
+ getSelectedText() {
5529
+ const selectedTexts = this._selectedRenderables.sort((a, b) => {
5530
+ const aY = a.y;
5531
+ const bY = b.y;
5532
+ if (aY !== bY) {
5533
+ return aY - bY;
5534
+ }
5535
+ return a.x - b.x;
5536
+ }).map((renderable) => renderable.getSelectedText()).filter((text) => text);
5537
+ return selectedTexts.join(`
5538
+ `);
5539
+ }
5540
+ }
5541
+
5542
+ class TextSelectionHelper {
5543
+ getX;
5544
+ getY;
5545
+ getTextLength;
5546
+ getLineInfo;
5547
+ localSelection = null;
5548
+ cachedGlobalSelection = null;
5549
+ constructor(getX, getY, getTextLength, getLineInfo) {
5550
+ this.getX = getX;
5551
+ this.getY = getY;
5552
+ this.getTextLength = getTextLength;
5553
+ this.getLineInfo = getLineInfo;
5554
+ }
5555
+ hasSelection() {
5556
+ return this.localSelection !== null;
5557
+ }
5558
+ getSelection() {
5559
+ return this.localSelection;
5560
+ }
5561
+ reevaluateSelection(width, height = 1) {
5562
+ if (!this.cachedGlobalSelection) {
5563
+ return false;
5564
+ }
5565
+ return this.onSelectionChanged(this.cachedGlobalSelection, width, height);
5566
+ }
5567
+ shouldStartSelection(x, y, width, height) {
5568
+ const localX = x - this.getX();
5569
+ const localY = y - this.getY();
5570
+ return localX >= 0 && localX < width && localY >= 0 && localY < height;
5571
+ }
5572
+ onSelectionChanged(selection, width, height = 1) {
5573
+ this.cachedGlobalSelection = selection;
5574
+ const previousSelection = this.localSelection;
5575
+ if (!selection?.isActive) {
5576
+ this.localSelection = null;
5577
+ return previousSelection !== null;
5578
+ }
5579
+ const myY = this.getY();
5580
+ const myEndY = myY + height - 1;
5581
+ if (myEndY < selection.anchor.y || myY > selection.focus.y) {
5582
+ this.localSelection = null;
5583
+ return previousSelection !== null;
5584
+ }
5585
+ if (height === 1) {
5586
+ this.localSelection = this.calculateSingleLineSelection(myY, selection.anchor.y, selection.focus.y, selection.anchor.x, selection.focus.x, width);
5587
+ } else {
5588
+ this.localSelection = this.calculateMultiLineSelection(myY, selection.anchor.y, selection.focus.y, selection.anchor.x, selection.focus.x);
5589
+ }
5590
+ return this.localSelection !== null !== (previousSelection !== null) || this.localSelection?.start !== previousSelection?.start || this.localSelection?.end !== previousSelection?.end;
5591
+ }
5592
+ calculateSingleLineSelection(lineY, anchorY, focusY, anchorX, focusX, width) {
5593
+ const textLength = this.getTextLength();
5594
+ const myX = this.getX();
5595
+ if (lineY > anchorY && lineY < focusY) {
5596
+ return { start: 0, end: textLength };
5597
+ }
5598
+ if (lineY === anchorY && lineY === focusY) {
5599
+ const start = Math.max(0, Math.min(anchorX - myX, textLength));
5600
+ const end = Math.max(0, Math.min(focusX - myX, textLength));
5601
+ return start < end ? { start, end } : null;
5602
+ }
5603
+ if (lineY === anchorY) {
5604
+ const start = Math.max(0, Math.min(anchorX - myX, textLength));
5605
+ return start < textLength ? { start, end: textLength } : null;
5606
+ }
5607
+ if (lineY === focusY) {
5608
+ const end = Math.max(0, Math.min(focusX - myX, textLength));
5609
+ return end > 0 ? { start: 0, end } : null;
5610
+ }
5611
+ return null;
5612
+ }
5613
+ calculateMultiLineSelection(startY, anchorY, focusY, anchorX, focusX) {
5614
+ const lineInfo = this.getLineInfo?.();
5615
+ if (!lineInfo) {
5616
+ return { start: 0, end: this.getTextLength() };
5617
+ }
5618
+ const myX = this.getX();
5619
+ let selectionStart = null;
5620
+ let selectionEnd = null;
5621
+ for (let i = 0;i < lineInfo.lineStarts.length; i++) {
5622
+ const lineY = startY + i;
5623
+ if (lineY < anchorY || lineY > focusY)
5624
+ continue;
5625
+ const lineStart = lineInfo.lineStarts[i];
5626
+ const lineEnd = i < lineInfo.lineStarts.length - 1 ? lineInfo.lineStarts[i + 1] - 1 : this.getTextLength();
5627
+ const lineWidth = lineInfo.lineWidths[i];
5628
+ if (lineY > anchorY && lineY < focusY) {
5629
+ if (selectionStart === null)
5630
+ selectionStart = lineStart;
5631
+ selectionEnd = lineEnd;
5632
+ } else if (lineY === anchorY && lineY === focusY) {
5633
+ const localStartX = Math.max(0, Math.min(anchorX - myX, lineWidth));
5634
+ const localEndX = Math.max(0, Math.min(focusX - myX, lineWidth));
5635
+ if (localStartX < localEndX) {
5636
+ selectionStart = lineStart + localStartX;
5637
+ selectionEnd = lineStart + localEndX;
5638
+ }
5639
+ } else if (lineY === anchorY) {
5640
+ const localStartX = Math.max(0, Math.min(anchorX - myX, lineWidth));
5641
+ if (localStartX < lineWidth) {
5642
+ selectionStart = lineStart + localStartX;
5643
+ selectionEnd = lineEnd;
5644
+ }
5645
+ } else if (lineY === focusY) {
5646
+ const localEndX = Math.max(0, Math.min(focusX - myX, lineWidth));
5647
+ if (localEndX > 0) {
5648
+ if (selectionStart === null)
5649
+ selectionStart = lineStart;
5650
+ selectionEnd = lineStart + localEndX;
5651
+ }
5652
+ }
5653
+ }
5654
+ return selectionStart !== null && selectionEnd !== null && selectionStart < selectionEnd ? { start: selectionStart, end: selectionEnd } : null;
5655
+ }
5656
+ }
5657
+
5658
+ class ASCIIFontSelectionHelper {
5659
+ getX;
5660
+ getY;
5661
+ getText;
5662
+ getFont;
5663
+ localSelection = null;
5664
+ cachedGlobalSelection = null;
5665
+ constructor(getX, getY, getText, getFont) {
5666
+ this.getX = getX;
5667
+ this.getY = getY;
5668
+ this.getText = getText;
5669
+ this.getFont = getFont;
5670
+ }
5671
+ hasSelection() {
5672
+ return this.localSelection !== null;
5673
+ }
5674
+ getSelection() {
5675
+ return this.localSelection;
5676
+ }
5677
+ shouldStartSelection(x, y, width, height) {
5678
+ const localX = x - this.getX();
5679
+ const localY = y - this.getY();
5680
+ if (localX < 0 || localX >= width || localY < 0 || localY >= height) {
5681
+ return false;
5682
+ }
5683
+ const text = this.getText();
5684
+ const font = this.getFont();
5685
+ const charIndex = coordinateToCharacterIndex(localX, text, font);
5686
+ return charIndex >= 0 && charIndex <= text.length;
5687
+ }
5688
+ onSelectionChanged(selection, width, height) {
5689
+ this.cachedGlobalSelection = selection;
5690
+ const previousSelection = this.localSelection;
5691
+ if (!selection?.isActive) {
5692
+ this.localSelection = null;
5693
+ return previousSelection !== null;
5694
+ }
5695
+ const myX = this.getX();
5696
+ const myY = this.getY();
5697
+ const myEndY = myY + height - 1;
5698
+ const text = this.getText();
5699
+ const font = this.getFont();
5700
+ let selStart;
5701
+ let selEnd;
5702
+ if (selection.anchor.y < selection.focus.y || selection.anchor.y === selection.focus.y && selection.anchor.x <= selection.focus.x) {
5703
+ selStart = selection.anchor;
5704
+ selEnd = selection.focus;
5705
+ } else {
5706
+ selStart = selection.focus;
5707
+ selEnd = selection.anchor;
5708
+ }
5709
+ if (myEndY < selStart.y || myY > selEnd.y) {
5710
+ this.localSelection = null;
5711
+ return previousSelection !== null;
5712
+ }
5713
+ let startCharIndex = 0;
5714
+ let endCharIndex = text.length;
5715
+ if (selStart.y > myEndY) {
5716
+ this.localSelection = null;
5717
+ return previousSelection !== null;
5718
+ } else if (selStart.y >= myY && selStart.y <= myEndY) {
5719
+ const localX = selStart.x - myX;
5720
+ if (localX > 0) {
5721
+ startCharIndex = coordinateToCharacterIndex(localX, text, font);
5722
+ }
5723
+ }
5724
+ if (selEnd.y < myY) {
5725
+ this.localSelection = null;
5726
+ return previousSelection !== null;
5727
+ } else if (selEnd.y >= myY && selEnd.y <= myEndY) {
5728
+ const localX = selEnd.x - myX;
5729
+ if (localX >= 0) {
5730
+ endCharIndex = coordinateToCharacterIndex(localX, text, font);
5731
+ } else {
5732
+ endCharIndex = 0;
5733
+ }
5734
+ }
5735
+ if (startCharIndex < endCharIndex && startCharIndex >= 0 && endCharIndex <= text.length) {
5736
+ this.localSelection = { start: startCharIndex, end: endCharIndex };
5737
+ } else {
5738
+ this.localSelection = null;
5739
+ }
5740
+ return this.localSelection !== null !== (previousSelection !== null) || this.localSelection?.start !== previousSelection?.start || this.localSelection?.end !== previousSelection?.end;
5741
+ }
5742
+ reevaluateSelection(width, height) {
5743
+ if (!this.cachedGlobalSelection) {
5744
+ return false;
5745
+ }
5746
+ return this.onSelectionChanged(this.cachedGlobalSelection, width, height);
5747
+ }
5748
+ }
5749
+ // src/zig.ts
5750
+ import { dlopen, toArrayBuffer } from "bun:ffi";
5751
+ import { existsSync } from "fs";
5752
+
5753
+ // src/text-buffer.ts
5754
+ class TextBuffer {
5755
+ lib;
5756
+ bufferPtr;
5757
+ buffer;
5758
+ _length = 0;
5759
+ _capacity;
5760
+ _lineInfo;
5761
+ constructor(lib, ptr, buffer, capacity) {
5762
+ this.lib = lib;
5763
+ this.bufferPtr = ptr;
5764
+ this.buffer = buffer;
5765
+ this._capacity = capacity;
5766
+ }
5767
+ static create(capacity = 256) {
5768
+ const lib = resolveRenderLib();
5769
+ return lib.createTextBuffer(capacity);
5770
+ }
5771
+ syncBuffersAfterResize() {
5772
+ const capacity = this.lib.textBufferGetCapacity(this.bufferPtr);
5773
+ this.buffer = this.lib.getTextBufferArrays(this.bufferPtr, capacity);
5774
+ this._capacity = capacity;
5775
+ }
5776
+ setStyledText(text) {
5777
+ this.lib.textBufferReset(this.bufferPtr);
5778
+ this._length = 0;
5779
+ this._lineInfo = undefined;
5780
+ for (const chunk of text.chunks) {
5781
+ const result = this.lib.textBufferWriteChunk(this.bufferPtr, chunk.text, chunk.fg || null, chunk.bg || null, chunk.attributes ?? null);
5782
+ if (result & 1) {
5783
+ this.syncBuffersAfterResize();
5784
+ }
5785
+ }
5786
+ this.lib.textBufferFinalizeLineInfo(this.bufferPtr);
5787
+ this._length = this.lib.textBufferGetLength(this.bufferPtr);
5788
+ }
5789
+ setDefaultFg(fg2) {
5790
+ this.lib.textBufferSetDefaultFg(this.bufferPtr, fg2);
5791
+ }
5792
+ setDefaultBg(bg2) {
5793
+ this.lib.textBufferSetDefaultBg(this.bufferPtr, bg2);
5794
+ }
5795
+ setDefaultAttributes(attributes) {
5796
+ this.lib.textBufferSetDefaultAttributes(this.bufferPtr, attributes);
5797
+ }
5798
+ resetDefaults() {
5799
+ this.lib.textBufferResetDefaults(this.bufferPtr);
5800
+ }
5801
+ get length() {
5802
+ return this._length;
5803
+ }
5804
+ get capacity() {
5805
+ return this._capacity;
5806
+ }
5807
+ get ptr() {
5808
+ return this.bufferPtr;
5809
+ }
5810
+ get lineInfo() {
5811
+ if (!this._lineInfo) {
5812
+ this._lineInfo = this.lib.textBufferGetLineInfo(this.bufferPtr);
5813
+ }
5814
+ return this._lineInfo;
5815
+ }
5816
+ toString() {
5817
+ const chars = [];
5818
+ for (let i = 0;i < this._length; i++) {
5819
+ chars.push(String.fromCharCode(this.buffer.char[i]));
5820
+ }
5821
+ return chars.join("");
5822
+ }
5823
+ concat(other) {
5824
+ return this.lib.textBufferConcat(this.bufferPtr, other.bufferPtr);
5825
+ }
5826
+ setSelection(start, end, bgColor, fgColor) {
5827
+ this.lib.textBufferSetSelection(this.bufferPtr, start, end, bgColor || null, fgColor || null);
5828
+ }
5829
+ resetSelection() {
5830
+ this.lib.textBufferResetSelection(this.bufferPtr);
5831
+ }
5832
+ destroy() {
5833
+ this.lib.destroyTextBuffer(this.bufferPtr);
5834
+ }
5835
+ }
5836
+
5837
+ // src/zig.ts
5838
+ var module = await import(`@opentui/core-${process.platform}-${process.arch}/index.ts`);
5839
+ var targetLibPath = module.default;
5840
+ if (!existsSync(targetLibPath)) {
5841
+ throw new Error(`opentui is not supported on the current platform: ${process.platform}-${process.arch}`);
5842
+ }
5843
+ function getOpenTUILib(libPath) {
5844
+ const resolvedLibPath = libPath || targetLibPath;
5845
+ return dlopen(resolvedLibPath, {
5846
+ createRenderer: {
5847
+ args: ["u32", "u32"],
5848
+ returns: "ptr"
5849
+ },
5850
+ destroyRenderer: {
5851
+ args: ["ptr", "bool", "u32"],
5852
+ returns: "void"
5853
+ },
5854
+ setUseThread: {
5855
+ args: ["ptr", "bool"],
5856
+ returns: "void"
5857
+ },
5858
+ setBackgroundColor: {
5859
+ args: ["ptr", "ptr"],
5860
+ returns: "void"
5861
+ },
5862
+ setRenderOffset: {
5863
+ args: ["ptr", "u32"],
5864
+ returns: "void"
5865
+ },
5866
+ updateStats: {
5867
+ args: ["ptr", "f64", "u32", "f64"],
5868
+ returns: "void"
5869
+ },
5870
+ updateMemoryStats: {
5871
+ args: ["ptr", "u32", "u32", "u32"],
5872
+ returns: "void"
5873
+ },
5874
+ render: {
5875
+ args: ["ptr", "bool"],
5876
+ returns: "void"
5877
+ },
5878
+ getNextBuffer: {
5879
+ args: ["ptr"],
5880
+ returns: "ptr"
5881
+ },
5882
+ getCurrentBuffer: {
5883
+ args: ["ptr"],
5884
+ returns: "ptr"
5885
+ },
5886
+ createOptimizedBuffer: {
5887
+ args: ["u32", "u32", "bool"],
5888
+ returns: "ptr"
5889
+ },
5890
+ destroyOptimizedBuffer: {
5891
+ args: ["ptr"],
5892
+ returns: "void"
5893
+ },
5894
+ drawFrameBuffer: {
5895
+ args: ["ptr", "i32", "i32", "ptr", "u32", "u32", "u32", "u32"],
5896
+ returns: "void"
5897
+ },
5898
+ getBufferWidth: {
5899
+ args: ["ptr"],
5900
+ returns: "u32"
5901
+ },
5902
+ getBufferHeight: {
5903
+ args: ["ptr"],
5904
+ returns: "u32"
5905
+ },
5906
+ bufferClear: {
5907
+ args: ["ptr", "ptr"],
5908
+ returns: "void"
5909
+ },
5910
+ bufferGetCharPtr: {
5911
+ args: ["ptr"],
5912
+ returns: "ptr"
5913
+ },
5914
+ bufferGetFgPtr: {
5915
+ args: ["ptr"],
5916
+ returns: "ptr"
5917
+ },
5918
+ bufferGetBgPtr: {
5919
+ args: ["ptr"],
5920
+ returns: "ptr"
5921
+ },
5922
+ bufferGetAttributesPtr: {
5923
+ args: ["ptr"],
5924
+ returns: "ptr"
5925
+ },
5926
+ bufferGetRespectAlpha: {
5927
+ args: ["ptr"],
5928
+ returns: "bool"
5929
+ },
5930
+ bufferSetRespectAlpha: {
5931
+ args: ["ptr", "bool"],
5932
+ returns: "void"
5933
+ },
5934
+ bufferDrawText: {
5935
+ args: ["ptr", "ptr", "u32", "u32", "u32", "ptr", "ptr", "u8"],
5936
+ returns: "void"
5937
+ },
5938
+ bufferSetCellWithAlphaBlending: {
5939
+ args: ["ptr", "u32", "u32", "u32", "ptr", "ptr", "u8"],
5940
+ returns: "void"
5941
+ },
5942
+ bufferFillRect: {
5943
+ args: ["ptr", "u32", "u32", "u32", "u32", "ptr"],
5944
+ returns: "void"
5945
+ },
5946
+ bufferResize: {
5947
+ args: ["ptr", "u32", "u32"],
5948
+ returns: "void"
5949
+ },
5950
+ resizeRenderer: {
5951
+ args: ["ptr", "u32", "u32"],
5952
+ returns: "void"
5953
+ },
5954
+ setCursorPosition: {
5955
+ args: ["i32", "i32", "bool"],
5956
+ returns: "void"
5957
+ },
5958
+ setCursorStyle: {
5959
+ args: ["ptr", "u32", "bool"],
5960
+ returns: "void"
5961
+ },
5962
+ setCursorColor: {
5963
+ args: ["ptr"],
5964
+ returns: "void"
5965
+ },
5966
+ setDebugOverlay: {
5967
+ args: ["ptr", "bool", "u8"],
5968
+ returns: "void"
5969
+ },
5970
+ clearTerminal: {
5971
+ args: ["ptr"],
5972
+ returns: "void"
5973
+ },
5974
+ bufferDrawSuperSampleBuffer: {
5975
+ args: ["ptr", "u32", "u32", "ptr", "usize", "u8", "u32"],
5976
+ returns: "void"
5977
+ },
5978
+ bufferDrawPackedBuffer: {
5979
+ args: ["ptr", "ptr", "usize", "u32", "u32", "u32", "u32"],
5980
+ returns: "void"
5981
+ },
5982
+ bufferDrawBox: {
5983
+ args: ["ptr", "i32", "i32", "u32", "u32", "ptr", "u32", "ptr", "ptr", "ptr", "u32"],
5984
+ returns: "void"
5985
+ },
5986
+ addToHitGrid: {
5987
+ args: ["ptr", "i32", "i32", "u32", "u32", "u32"],
5988
+ returns: "void"
5989
+ },
5990
+ checkHit: {
5991
+ args: ["ptr", "u32", "u32"],
5992
+ returns: "u32"
5993
+ },
5994
+ dumpHitGrid: {
5995
+ args: ["ptr"],
5996
+ returns: "void"
5997
+ },
5998
+ dumpBuffers: {
5999
+ args: ["ptr", "i64"],
6000
+ returns: "void"
6001
+ },
6002
+ dumpStdoutBuffer: {
6003
+ args: ["ptr", "i64"],
6004
+ returns: "void"
6005
+ },
6006
+ enableMouse: {
6007
+ args: ["ptr", "bool"],
6008
+ returns: "void"
6009
+ },
6010
+ disableMouse: {
6011
+ args: ["ptr"],
6012
+ returns: "void"
6013
+ },
6014
+ createTextBuffer: {
6015
+ args: ["u32"],
6016
+ returns: "ptr"
6017
+ },
6018
+ destroyTextBuffer: {
6019
+ args: ["ptr"],
6020
+ returns: "void"
6021
+ },
6022
+ textBufferGetCharPtr: {
6023
+ args: ["ptr"],
6024
+ returns: "ptr"
6025
+ },
6026
+ textBufferGetFgPtr: {
6027
+ args: ["ptr"],
6028
+ returns: "ptr"
6029
+ },
6030
+ textBufferGetBgPtr: {
6031
+ args: ["ptr"],
6032
+ returns: "ptr"
6033
+ },
6034
+ textBufferGetAttributesPtr: {
6035
+ args: ["ptr"],
6036
+ returns: "ptr"
6037
+ },
6038
+ textBufferGetLength: {
6039
+ args: ["ptr"],
6040
+ returns: "u32"
6041
+ },
6042
+ textBufferSetCell: {
6043
+ args: ["ptr", "u32", "u32", "ptr", "ptr", "u16"],
6044
+ returns: "void"
6045
+ },
6046
+ textBufferConcat: {
6047
+ args: ["ptr", "ptr"],
6048
+ returns: "ptr"
6049
+ },
6050
+ textBufferResize: {
6051
+ args: ["ptr", "u32"],
6052
+ returns: "void"
6053
+ },
6054
+ textBufferReset: {
6055
+ args: ["ptr"],
6056
+ returns: "void"
6057
+ },
6058
+ textBufferSetSelection: {
6059
+ args: ["ptr", "u32", "u32", "ptr", "ptr"],
6060
+ returns: "void"
6061
+ },
6062
+ textBufferResetSelection: {
6063
+ args: ["ptr"],
6064
+ returns: "void"
6065
+ },
6066
+ textBufferSetDefaultFg: {
6067
+ args: ["ptr", "ptr"],
6068
+ returns: "void"
6069
+ },
6070
+ textBufferSetDefaultBg: {
6071
+ args: ["ptr", "ptr"],
6072
+ returns: "void"
6073
+ },
6074
+ textBufferSetDefaultAttributes: {
6075
+ args: ["ptr", "ptr"],
6076
+ returns: "void"
6077
+ },
6078
+ textBufferResetDefaults: {
6079
+ args: ["ptr"],
6080
+ returns: "void"
6081
+ },
6082
+ textBufferWriteChunk: {
6083
+ args: ["ptr", "ptr", "u32", "ptr", "ptr", "ptr"],
6084
+ returns: "u32"
6085
+ },
6086
+ textBufferGetCapacity: {
6087
+ args: ["ptr"],
6088
+ returns: "u32"
6089
+ },
6090
+ textBufferFinalizeLineInfo: {
6091
+ args: ["ptr"],
6092
+ returns: "void"
6093
+ },
6094
+ textBufferGetLineStartsPtr: {
6095
+ args: ["ptr"],
6096
+ returns: "ptr"
6097
+ },
6098
+ textBufferGetLineWidthsPtr: {
6099
+ args: ["ptr"],
6100
+ returns: "ptr"
6101
+ },
6102
+ textBufferGetLineCount: {
6103
+ args: ["ptr"],
6104
+ returns: "u32"
6105
+ },
6106
+ bufferDrawTextBuffer: {
6107
+ args: ["ptr", "ptr", "i32", "i32", "i32", "i32", "u32", "u32", "bool"],
6108
+ returns: "void"
6109
+ }
6110
+ });
6111
+ }
5276
6112
 
5277
- // src/lib/ascii.font.ts
5278
- var fonts = {
5279
- tiny: tiny_default,
5280
- block: block_default,
5281
- shade: shade_default,
5282
- slick: slick_default
5283
- };
5284
- var parsedFonts = {};
5285
- function parseColorTags(text) {
5286
- const segments = [];
5287
- let currentIndex = 0;
5288
- const colorTagRegex = /<c(\d+)>(.*?)<\/c\d+>/g;
5289
- let lastIndex = 0;
5290
- let match;
5291
- while ((match = colorTagRegex.exec(text)) !== null) {
5292
- if (match.index > lastIndex) {
5293
- const plainText = text.slice(lastIndex, match.index);
5294
- if (plainText) {
5295
- segments.push({ text: plainText, colorIndex: 0 });
5296
- }
6113
+ class FFIRenderLib {
6114
+ opentui;
6115
+ encoder = new TextEncoder;
6116
+ constructor(libPath) {
6117
+ this.opentui = getOpenTUILib(libPath);
6118
+ }
6119
+ createRenderer(width, height) {
6120
+ return this.opentui.symbols.createRenderer(width, height);
6121
+ }
6122
+ destroyRenderer(renderer, useAlternateScreen, splitHeight) {
6123
+ this.opentui.symbols.destroyRenderer(renderer, useAlternateScreen, splitHeight);
6124
+ }
6125
+ setUseThread(renderer, useThread) {
6126
+ this.opentui.symbols.setUseThread(renderer, useThread);
6127
+ }
6128
+ setBackgroundColor(renderer, color) {
6129
+ this.opentui.symbols.setBackgroundColor(renderer, color.buffer);
6130
+ }
6131
+ setRenderOffset(renderer, offset) {
6132
+ this.opentui.symbols.setRenderOffset(renderer, offset);
6133
+ }
6134
+ updateStats(renderer, time, fps, frameCallbackTime) {
6135
+ this.opentui.symbols.updateStats(renderer, time, fps, frameCallbackTime);
6136
+ }
6137
+ updateMemoryStats(renderer, heapUsed, heapTotal, arrayBuffers) {
6138
+ this.opentui.symbols.updateMemoryStats(renderer, heapUsed, heapTotal, arrayBuffers);
6139
+ }
6140
+ getNextBuffer(renderer) {
6141
+ const bufferPtr = this.opentui.symbols.getNextBuffer(renderer);
6142
+ if (!bufferPtr) {
6143
+ throw new Error("Failed to get next buffer");
5297
6144
  }
5298
- const colorIndex = parseInt(match[1]) - 1;
5299
- const taggedText = match[2];
5300
- segments.push({ text: taggedText, colorIndex: Math.max(0, colorIndex) });
5301
- lastIndex = match.index + match[0].length;
6145
+ const width = this.opentui.symbols.getBufferWidth(bufferPtr);
6146
+ const height = this.opentui.symbols.getBufferHeight(bufferPtr);
6147
+ const size = width * height;
6148
+ const buffers = this.getBuffer(bufferPtr, size);
6149
+ return new OptimizedBuffer(this, bufferPtr, buffers, width, height, {});
5302
6150
  }
5303
- if (lastIndex < text.length) {
5304
- const remainingText = text.slice(lastIndex);
5305
- if (remainingText) {
5306
- segments.push({ text: remainingText, colorIndex: 0 });
6151
+ getCurrentBuffer(renderer) {
6152
+ const bufferPtr = this.opentui.symbols.getCurrentBuffer(renderer);
6153
+ if (!bufferPtr) {
6154
+ throw new Error("Failed to get current buffer");
5307
6155
  }
6156
+ const width = this.opentui.symbols.getBufferWidth(bufferPtr);
6157
+ const height = this.opentui.symbols.getBufferHeight(bufferPtr);
6158
+ const size = width * height;
6159
+ const buffers = this.getBuffer(bufferPtr, size);
6160
+ return new OptimizedBuffer(this, bufferPtr, buffers, width, height, {});
5308
6161
  }
5309
- return segments;
5310
- }
5311
- function getParsedFont(fontKey) {
5312
- if (!parsedFonts[fontKey]) {
5313
- const fontDef = fonts[fontKey];
5314
- const parsedChars = {};
5315
- for (const [char, lines] of Object.entries(fontDef.chars)) {
5316
- parsedChars[char] = lines.map((line) => parseColorTags(line));
6162
+ getBuffer(bufferPtr, size) {
6163
+ const charPtr = this.opentui.symbols.bufferGetCharPtr(bufferPtr);
6164
+ const fgPtr = this.opentui.symbols.bufferGetFgPtr(bufferPtr);
6165
+ const bgPtr = this.opentui.symbols.bufferGetBgPtr(bufferPtr);
6166
+ const attributesPtr = this.opentui.symbols.bufferGetAttributesPtr(bufferPtr);
6167
+ if (!charPtr || !fgPtr || !bgPtr || !attributesPtr) {
6168
+ throw new Error("Failed to get buffer pointers");
5317
6169
  }
5318
- parsedFonts[fontKey] = {
5319
- ...fontDef,
5320
- colors: fontDef.colors || 1,
5321
- chars: parsedChars
6170
+ const buffers = {
6171
+ char: new Uint32Array(toArrayBuffer(charPtr, 0, size * 4)),
6172
+ fg: new Float32Array(toArrayBuffer(fgPtr, 0, size * 4 * 4)),
6173
+ bg: new Float32Array(toArrayBuffer(bgPtr, 0, size * 4 * 4)),
6174
+ attributes: new Uint8Array(toArrayBuffer(attributesPtr, 0, size))
5322
6175
  };
6176
+ return buffers;
5323
6177
  }
5324
- return parsedFonts[fontKey];
5325
- }
5326
- function measureText({ text, font = "tiny" }) {
5327
- const fontDef = getParsedFont(font);
5328
- if (!fontDef) {
5329
- console.warn(`Font '${font}' not found`);
5330
- return { width: 0, height: 0 };
5331
- }
5332
- let currentX = 0;
5333
- for (let i = 0;i < text.length; i++) {
5334
- const char = text[i].toUpperCase();
5335
- const charDef = fontDef.chars[char];
5336
- if (!charDef) {
5337
- const spaceChar = fontDef.chars[" "];
5338
- if (spaceChar && spaceChar[0]) {
5339
- let spaceWidth = 0;
5340
- for (const segment of spaceChar[0]) {
5341
- spaceWidth += segment.text.length;
5342
- }
5343
- currentX += spaceWidth;
5344
- } else {
5345
- currentX += 1;
5346
- }
5347
- continue;
5348
- }
5349
- let charWidth = 0;
5350
- if (charDef[0]) {
5351
- for (const segment of charDef[0]) {
5352
- charWidth += segment.text.length;
5353
- }
6178
+ getTextBuffer(bufferPtr, size) {
6179
+ const charPtr = this.opentui.symbols.textBufferGetCharPtr(bufferPtr);
6180
+ const fgPtr = this.opentui.symbols.textBufferGetFgPtr(bufferPtr);
6181
+ const bgPtr = this.opentui.symbols.textBufferGetBgPtr(bufferPtr);
6182
+ const attributesPtr = this.opentui.symbols.textBufferGetAttributesPtr(bufferPtr);
6183
+ if (!charPtr || !fgPtr || !bgPtr || !attributesPtr) {
6184
+ throw new Error("Failed to get text buffer pointers");
5354
6185
  }
5355
- currentX += charWidth;
5356
- if (i < text.length - 1) {
5357
- currentX += fontDef.letterspace_size;
6186
+ const buffers = {
6187
+ char: new Uint32Array(toArrayBuffer(charPtr, 0, size * 4)),
6188
+ fg: new Float32Array(toArrayBuffer(fgPtr, 0, size * 4 * 4)),
6189
+ bg: new Float32Array(toArrayBuffer(bgPtr, 0, size * 4 * 4)),
6190
+ attributes: new Uint16Array(toArrayBuffer(attributesPtr, 0, size * 2))
6191
+ };
6192
+ return buffers;
6193
+ }
6194
+ bufferGetCharPtr(buffer) {
6195
+ const ptr = this.opentui.symbols.bufferGetCharPtr(buffer);
6196
+ if (!ptr) {
6197
+ throw new Error("Failed to get char pointer");
5358
6198
  }
6199
+ return ptr;
5359
6200
  }
5360
- return {
5361
- width: currentX,
5362
- height: fontDef.lines
5363
- };
5364
- }
5365
- function getCharacterPositions(text, font = "tiny") {
5366
- const fontDef = getParsedFont(font);
5367
- if (!fontDef) {
5368
- return [0];
6201
+ bufferGetFgPtr(buffer) {
6202
+ const ptr = this.opentui.symbols.bufferGetFgPtr(buffer);
6203
+ if (!ptr) {
6204
+ throw new Error("Failed to get fg pointer");
6205
+ }
6206
+ return ptr;
5369
6207
  }
5370
- const positions = [0];
5371
- let currentX = 0;
5372
- for (let i = 0;i < text.length; i++) {
5373
- const char = text[i].toUpperCase();
5374
- const charDef = fontDef.chars[char];
5375
- let charWidth = 0;
5376
- if (!charDef) {
5377
- const spaceChar = fontDef.chars[" "];
5378
- if (spaceChar && spaceChar[0]) {
5379
- for (const segment of spaceChar[0]) {
5380
- charWidth += segment.text.length;
5381
- }
5382
- } else {
5383
- charWidth = 1;
5384
- }
5385
- } else if (charDef[0]) {
5386
- for (const segment of charDef[0]) {
5387
- charWidth += segment.text.length;
5388
- }
6208
+ bufferGetBgPtr(buffer) {
6209
+ const ptr = this.opentui.symbols.bufferGetBgPtr(buffer);
6210
+ if (!ptr) {
6211
+ throw new Error("Failed to get bg pointer");
5389
6212
  }
5390
- currentX += charWidth;
5391
- if (i < text.length - 1) {
5392
- currentX += fontDef.letterspace_size;
6213
+ return ptr;
6214
+ }
6215
+ bufferGetAttributesPtr(buffer) {
6216
+ const ptr = this.opentui.symbols.bufferGetAttributesPtr(buffer);
6217
+ if (!ptr) {
6218
+ throw new Error("Failed to get attributes pointer");
5393
6219
  }
5394
- positions.push(currentX);
6220
+ return ptr;
5395
6221
  }
5396
- return positions;
5397
- }
5398
- function coordinateToCharacterIndex(x, text, font = "tiny") {
5399
- const positions = getCharacterPositions(text, font);
5400
- if (x < 0) {
5401
- return 0;
6222
+ bufferGetRespectAlpha(buffer) {
6223
+ return this.opentui.symbols.bufferGetRespectAlpha(buffer);
6224
+ }
6225
+ bufferSetRespectAlpha(buffer, respectAlpha) {
6226
+ this.opentui.symbols.bufferSetRespectAlpha(buffer, respectAlpha);
6227
+ }
6228
+ getBufferWidth(buffer) {
6229
+ return this.opentui.symbols.getBufferWidth(buffer);
6230
+ }
6231
+ getBufferHeight(buffer) {
6232
+ return this.opentui.symbols.getBufferHeight(buffer);
6233
+ }
6234
+ bufferClear(buffer, color) {
6235
+ this.opentui.symbols.bufferClear(buffer, color.buffer);
6236
+ }
6237
+ bufferDrawText(buffer, text, x, y, color, bgColor, attributes) {
6238
+ const textBytes = this.encoder.encode(text);
6239
+ const textLength = textBytes.byteLength;
6240
+ const bg2 = bgColor ? bgColor.buffer : null;
6241
+ const fg2 = color.buffer;
6242
+ this.opentui.symbols.bufferDrawText(buffer, textBytes, textLength, x, y, fg2, bg2, attributes ?? 0);
6243
+ }
6244
+ bufferSetCellWithAlphaBlending(buffer, x, y, char, color, bgColor, attributes) {
6245
+ const charPtr = char.codePointAt(0) ?? " ".codePointAt(0);
6246
+ const bg2 = bgColor.buffer;
6247
+ const fg2 = color.buffer;
6248
+ this.opentui.symbols.bufferSetCellWithAlphaBlending(buffer, x, y, charPtr, fg2, bg2, attributes ?? 0);
6249
+ }
6250
+ bufferFillRect(buffer, x, y, width, height, color) {
6251
+ const bg2 = color.buffer;
6252
+ this.opentui.symbols.bufferFillRect(buffer, x, y, width, height, bg2);
6253
+ }
6254
+ bufferDrawSuperSampleBuffer(buffer, x, y, pixelDataPtr, pixelDataLength, format, alignedBytesPerRow) {
6255
+ const formatId = format === "bgra8unorm" ? 0 : 1;
6256
+ this.opentui.symbols.bufferDrawSuperSampleBuffer(buffer, x, y, pixelDataPtr, pixelDataLength, formatId, alignedBytesPerRow);
6257
+ }
6258
+ bufferDrawPackedBuffer(buffer, dataPtr, dataLen, posX, posY, terminalWidthCells, terminalHeightCells) {
6259
+ this.opentui.symbols.bufferDrawPackedBuffer(buffer, dataPtr, dataLen, posX, posY, terminalWidthCells, terminalHeightCells);
6260
+ }
6261
+ bufferDrawBox(buffer, x, y, width, height, borderChars, packedOptions, borderColor, backgroundColor, title) {
6262
+ const titleBytes = title ? this.encoder.encode(title) : null;
6263
+ const titleLen = title ? titleBytes.length : 0;
6264
+ const titlePtr = title ? titleBytes : null;
6265
+ this.opentui.symbols.bufferDrawBox(buffer, x, y, width, height, borderChars, packedOptions, borderColor.buffer, backgroundColor.buffer, titlePtr, titleLen);
6266
+ }
6267
+ bufferResize(buffer, width, height) {
6268
+ this.opentui.symbols.bufferResize(buffer, width, height);
6269
+ const buffers = this.getBuffer(buffer, width * height);
6270
+ return buffers;
6271
+ }
6272
+ resizeRenderer(renderer, width, height) {
6273
+ this.opentui.symbols.resizeRenderer(renderer, width, height);
5402
6274
  }
5403
- for (let i = 0;i < positions.length - 1; i++) {
5404
- const currentPos = positions[i];
5405
- const nextPos = positions[i + 1];
5406
- if (x >= currentPos && x < nextPos) {
5407
- const charMidpoint = currentPos + (nextPos - currentPos) / 2;
5408
- return x < charMidpoint ? i : i + 1;
5409
- }
6275
+ setCursorPosition(x, y, visible) {
6276
+ this.opentui.symbols.setCursorPosition(x, y, visible);
5410
6277
  }
5411
- if (positions.length > 0 && x >= positions[positions.length - 1]) {
5412
- return text.length;
6278
+ setCursorStyle(style, blinking) {
6279
+ const stylePtr = this.encoder.encode(style);
6280
+ this.opentui.symbols.setCursorStyle(stylePtr, style.length, blinking);
5413
6281
  }
5414
- return 0;
5415
- }
5416
- function renderFontToFrameBuffer(buffer, {
5417
- text,
5418
- x = 0,
5419
- y = 0,
5420
- fg = [RGBA.fromInts(255, 255, 255, 255)],
5421
- bg = RGBA.fromInts(0, 0, 0, 255),
5422
- font = "tiny"
5423
- }) {
5424
- const width = buffer.getWidth();
5425
- const height = buffer.getHeight();
5426
- const fontDef = getParsedFont(font);
5427
- if (!fontDef) {
5428
- console.warn(`Font '${font}' not found`);
5429
- return { width: 0, height: 0 };
6282
+ setCursorColor(color) {
6283
+ this.opentui.symbols.setCursorColor(color.buffer);
5430
6284
  }
5431
- const colors = Array.isArray(fg) ? fg : [fg];
5432
- if (y < 0 || y + fontDef.lines > height) {
5433
- return { width: 0, height: fontDef.lines };
6285
+ render(renderer, force) {
6286
+ this.opentui.symbols.render(renderer, force);
5434
6287
  }
5435
- let currentX = x;
5436
- const startX = x;
5437
- for (let i = 0;i < text.length; i++) {
5438
- const char = text[i].toUpperCase();
5439
- const charDef = fontDef.chars[char];
5440
- if (!charDef) {
5441
- const spaceChar = fontDef.chars[" "];
5442
- if (spaceChar && spaceChar[0]) {
5443
- let spaceWidth = 0;
5444
- for (const segment of spaceChar[0]) {
5445
- spaceWidth += segment.text.length;
5446
- }
5447
- currentX += spaceWidth;
5448
- } else {
5449
- currentX += 1;
5450
- }
5451
- continue;
5452
- }
5453
- let charWidth = 0;
5454
- if (charDef[0]) {
5455
- for (const segment of charDef[0]) {
5456
- charWidth += segment.text.length;
5457
- }
5458
- }
5459
- if (currentX >= width)
5460
- break;
5461
- if (currentX + charWidth < 0) {
5462
- currentX += charWidth + fontDef.letterspace_size;
5463
- continue;
5464
- }
5465
- for (let lineIdx = 0;lineIdx < fontDef.lines && lineIdx < charDef.length; lineIdx++) {
5466
- const segments = charDef[lineIdx];
5467
- const renderY = y + lineIdx;
5468
- if (renderY >= 0 && renderY < height) {
5469
- let segmentX = currentX;
5470
- for (const segment of segments) {
5471
- const segmentColor = colors[segment.colorIndex] || colors[0];
5472
- for (let charIdx = 0;charIdx < segment.text.length; charIdx++) {
5473
- const renderX = segmentX + charIdx;
5474
- if (renderX >= 0 && renderX < width) {
5475
- const fontChar = segment.text[charIdx];
5476
- if (fontChar !== " ") {
5477
- buffer.setCell(renderX, renderY, fontChar, segmentColor, bg);
5478
- }
5479
- }
5480
- }
5481
- segmentX += segment.text.length;
5482
- }
5483
- }
6288
+ createOptimizedBuffer(width, height, respectAlpha = false) {
6289
+ if (Number.isNaN(width) || Number.isNaN(height)) {
6290
+ console.error(new Error(`Invalid dimensions for OptimizedBuffer: ${width}x${height}`).stack);
5484
6291
  }
5485
- currentX += charWidth;
5486
- if (i < text.length - 1) {
5487
- currentX += fontDef.letterspace_size;
6292
+ const bufferPtr = this.opentui.symbols.createOptimizedBuffer(width, height, respectAlpha);
6293
+ if (!bufferPtr) {
6294
+ throw new Error(`Failed to create optimized buffer: ${width}x${height}`);
5488
6295
  }
6296
+ const size = width * height;
6297
+ const buffers = this.getBuffer(bufferPtr, size);
6298
+ return new OptimizedBuffer(this, bufferPtr, buffers, width, height, { respectAlpha });
5489
6299
  }
5490
- return {
5491
- width: currentX - startX,
5492
- height: fontDef.lines
5493
- };
5494
- }
5495
- // src/lib/styled-text.ts
5496
- var textEncoder = new TextEncoder;
5497
-
5498
- class StyledText {
5499
- chunks;
5500
- _plainText = "";
5501
- constructor(chunks) {
5502
- this.chunks = chunks;
5503
- for (let i = 0;i < chunks.length; i++) {
5504
- this._plainText += chunks[i].plainText;
5505
- }
6300
+ destroyOptimizedBuffer(bufferPtr) {
6301
+ this.opentui.symbols.destroyOptimizedBuffer(bufferPtr);
5506
6302
  }
5507
- toString() {
5508
- return this._plainText;
6303
+ drawFrameBuffer(targetBufferPtr, destX, destY, bufferPtr, sourceX, sourceY, sourceWidth, sourceHeight) {
6304
+ const srcX = sourceX ?? 0;
6305
+ const srcY = sourceY ?? 0;
6306
+ const srcWidth = sourceWidth ?? 0;
6307
+ const srcHeight = sourceHeight ?? 0;
6308
+ this.opentui.symbols.drawFrameBuffer(targetBufferPtr, destX, destY, bufferPtr, srcX, srcY, srcWidth, srcHeight);
5509
6309
  }
5510
- _chunksToPlainText() {
5511
- this._plainText = "";
5512
- for (const chunk of this.chunks) {
5513
- this._plainText += chunk.plainText;
5514
- }
6310
+ setDebugOverlay(renderer, enabled, corner) {
6311
+ this.opentui.symbols.setDebugOverlay(renderer, enabled, corner);
5515
6312
  }
5516
- insert(chunk, index) {
5517
- const originalLength = this.chunks.length;
5518
- if (index === undefined) {
5519
- this.chunks.push(chunk);
5520
- } else {
5521
- this.chunks.splice(index, 0, chunk);
5522
- }
5523
- if (index === undefined || index === originalLength) {
5524
- this._plainText += chunk.plainText;
5525
- } else {
5526
- this._chunksToPlainText();
5527
- }
6313
+ clearTerminal(renderer) {
6314
+ this.opentui.symbols.clearTerminal(renderer);
5528
6315
  }
5529
- remove(chunk) {
5530
- const originalLength = this.chunks.length;
5531
- const index = this.chunks.indexOf(chunk);
5532
- if (index === -1)
5533
- return;
5534
- this.chunks.splice(index, 1);
5535
- if (index === originalLength - 1) {
5536
- this._plainText = this._plainText.slice(0, this._plainText.length - chunk.plainText.length);
5537
- } else {
5538
- this._chunksToPlainText();
5539
- }
6316
+ addToHitGrid(renderer, x, y, width, height, id) {
6317
+ this.opentui.symbols.addToHitGrid(renderer, x, y, width, height, id);
5540
6318
  }
5541
- replace(chunk, oldChunk) {
5542
- const index = this.chunks.indexOf(oldChunk);
5543
- if (index === -1)
5544
- return;
5545
- this.chunks.splice(index, 1, chunk);
5546
- if (index === this.chunks.length - 1) {
5547
- this._plainText = this._plainText.slice(0, this._plainText.length - oldChunk.plainText.length) + chunk.plainText;
5548
- } else {
5549
- this._chunksToPlainText();
5550
- }
6319
+ checkHit(renderer, x, y) {
6320
+ return this.opentui.symbols.checkHit(renderer, x, y);
5551
6321
  }
5552
- }
5553
- function stringToStyledText(content) {
5554
- const textEncoder2 = new TextEncoder;
5555
- const chunk = {
5556
- __isChunk: true,
5557
- text: textEncoder2.encode(content),
5558
- plainText: content
5559
- };
5560
- return new StyledText([chunk]);
5561
- }
5562
- var templateCache = new WeakMap;
5563
- function applyStyle(input, style) {
5564
- if (typeof input === "object" && "__isChunk" in input) {
5565
- const existingChunk = input;
5566
- const fg = style.fg ? parseColor(style.fg) : existingChunk.fg;
5567
- const bg = style.bg ? parseColor(style.bg) : existingChunk.bg;
5568
- const newAttrs = createTextAttributes(style);
5569
- const mergedAttrs = existingChunk.attributes ? existingChunk.attributes | newAttrs : newAttrs;
5570
- return {
5571
- __isChunk: true,
5572
- text: existingChunk.text,
5573
- plainText: existingChunk.plainText,
5574
- fg,
5575
- bg,
5576
- attributes: mergedAttrs
5577
- };
5578
- } else {
5579
- const plainTextStr = String(input);
5580
- const text = textEncoder.encode(plainTextStr);
5581
- const fg = style.fg ? parseColor(style.fg) : undefined;
5582
- const bg = style.bg ? parseColor(style.bg) : undefined;
5583
- const attributes = createTextAttributes(style);
5584
- return {
5585
- __isChunk: true,
5586
- text,
5587
- plainText: plainTextStr,
5588
- fg,
5589
- bg,
5590
- attributes
5591
- };
6322
+ dumpHitGrid(renderer) {
6323
+ this.opentui.symbols.dumpHitGrid(renderer);
5592
6324
  }
5593
- }
5594
- var black = (input) => applyStyle(input, { fg: "black" });
5595
- var red = (input) => applyStyle(input, { fg: "red" });
5596
- var green = (input) => applyStyle(input, { fg: "green" });
5597
- var yellow = (input) => applyStyle(input, { fg: "yellow" });
5598
- var blue = (input) => applyStyle(input, { fg: "blue" });
5599
- var magenta = (input) => applyStyle(input, { fg: "magenta" });
5600
- var cyan = (input) => applyStyle(input, { fg: "cyan" });
5601
- var white = (input) => applyStyle(input, { fg: "white" });
5602
- var brightBlack = (input) => applyStyle(input, { fg: "brightBlack" });
5603
- var brightRed = (input) => applyStyle(input, { fg: "brightRed" });
5604
- var brightGreen = (input) => applyStyle(input, { fg: "brightGreen" });
5605
- var brightYellow = (input) => applyStyle(input, { fg: "brightYellow" });
5606
- var brightBlue = (input) => applyStyle(input, { fg: "brightBlue" });
5607
- var brightMagenta = (input) => applyStyle(input, { fg: "brightMagenta" });
5608
- var brightCyan = (input) => applyStyle(input, { fg: "brightCyan" });
5609
- var brightWhite = (input) => applyStyle(input, { fg: "brightWhite" });
5610
- var bgBlack = (input) => applyStyle(input, { bg: "black" });
5611
- var bgRed = (input) => applyStyle(input, { bg: "red" });
5612
- var bgGreen = (input) => applyStyle(input, { bg: "green" });
5613
- var bgYellow = (input) => applyStyle(input, { bg: "yellow" });
5614
- var bgBlue = (input) => applyStyle(input, { bg: "blue" });
5615
- var bgMagenta = (input) => applyStyle(input, { bg: "magenta" });
5616
- var bgCyan = (input) => applyStyle(input, { bg: "cyan" });
5617
- var bgWhite = (input) => applyStyle(input, { bg: "white" });
5618
- var bold = (input) => applyStyle(input, { bold: true });
5619
- var italic = (input) => applyStyle(input, { italic: true });
5620
- var underline = (input) => applyStyle(input, { underline: true });
5621
- var strikethrough = (input) => applyStyle(input, { strikethrough: true });
5622
- var dim = (input) => applyStyle(input, { dim: true });
5623
- var reverse = (input) => applyStyle(input, { reverse: true });
5624
- var blink = (input) => applyStyle(input, { blink: true });
5625
- var fg = (color) => (input) => applyStyle(input, { fg: color });
5626
- var bg = (color) => (input) => applyStyle(input, { bg: color });
5627
- function tn(strings, ...values) {
5628
- const chunks = [];
5629
- let length = 0;
5630
- let plainText = "";
5631
- for (let i = 0;i < strings.length; i++) {
5632
- const raw = strings[i];
5633
- if (raw) {
5634
- chunks.push({
5635
- __isChunk: true,
5636
- text: textEncoder.encode(raw),
5637
- plainText: raw,
5638
- attributes: 0
5639
- });
5640
- length += raw.length;
5641
- plainText += raw;
6325
+ dumpBuffers(renderer, timestamp) {
6326
+ const ts = timestamp ?? Date.now();
6327
+ this.opentui.symbols.dumpBuffers(renderer, ts);
6328
+ }
6329
+ dumpStdoutBuffer(renderer, timestamp) {
6330
+ const ts = timestamp ?? Date.now();
6331
+ this.opentui.symbols.dumpStdoutBuffer(renderer, ts);
6332
+ }
6333
+ enableMouse(renderer, enableMovement) {
6334
+ this.opentui.symbols.enableMouse(renderer, enableMovement);
6335
+ }
6336
+ disableMouse(renderer) {
6337
+ this.opentui.symbols.disableMouse(renderer);
6338
+ }
6339
+ createTextBuffer(capacity) {
6340
+ const bufferPtr = this.opentui.symbols.createTextBuffer(capacity);
6341
+ if (!bufferPtr) {
6342
+ throw new Error(`Failed to create TextBuffer with capacity ${capacity}`);
5642
6343
  }
5643
- const val = values[i];
5644
- if (typeof val === "object" && "__isChunk" in val) {
5645
- chunks.push(val);
5646
- length += val.plainText.length;
5647
- plainText += val.plainText;
5648
- } else if (val !== undefined) {
5649
- const plainTextStr = String(val);
5650
- chunks.push({
5651
- __isChunk: true,
5652
- text: textEncoder.encode(plainTextStr),
5653
- plainText: plainTextStr,
5654
- attributes: 0
5655
- });
5656
- length += plainTextStr.length;
5657
- plainText += plainTextStr;
6344
+ const charPtr = this.textBufferGetCharPtr(bufferPtr);
6345
+ const fgPtr = this.textBufferGetFgPtr(bufferPtr);
6346
+ const bgPtr = this.textBufferGetBgPtr(bufferPtr);
6347
+ const attributesPtr = this.textBufferGetAttributesPtr(bufferPtr);
6348
+ const buffer = {
6349
+ char: new Uint32Array(toArrayBuffer(charPtr, 0, capacity * 4)),
6350
+ fg: new Float32Array(toArrayBuffer(fgPtr, 0, capacity * 4 * 4)),
6351
+ bg: new Float32Array(toArrayBuffer(bgPtr, 0, capacity * 4 * 4)),
6352
+ attributes: new Uint16Array(toArrayBuffer(attributesPtr, 0, capacity * 2))
6353
+ };
6354
+ return new TextBuffer(this, bufferPtr, buffer, capacity);
6355
+ }
6356
+ destroyTextBuffer(buffer) {
6357
+ this.opentui.symbols.destroyTextBuffer(buffer);
6358
+ }
6359
+ textBufferGetCharPtr(buffer) {
6360
+ const ptr = this.opentui.symbols.textBufferGetCharPtr(buffer);
6361
+ if (!ptr) {
6362
+ throw new Error("Failed to get TextBuffer char pointer");
5658
6363
  }
6364
+ return ptr;
5659
6365
  }
5660
- return new StyledText(chunks);
5661
- }
5662
- function t(strings, ...values) {
5663
- let cachedStringChunks = templateCache.get(strings);
5664
- let length = 0;
5665
- let plainText = "";
5666
- if (!cachedStringChunks) {
5667
- cachedStringChunks = [];
5668
- for (let i = 0;i < strings.length; i++) {
5669
- const raw = strings[i];
5670
- if (raw) {
5671
- cachedStringChunks.push({
5672
- __isChunk: true,
5673
- text: textEncoder.encode(raw),
5674
- plainText: raw,
5675
- attributes: 0
5676
- });
5677
- } else {
5678
- cachedStringChunks.push(null);
5679
- }
6366
+ textBufferGetFgPtr(buffer) {
6367
+ const ptr = this.opentui.symbols.textBufferGetFgPtr(buffer);
6368
+ if (!ptr) {
6369
+ throw new Error("Failed to get TextBuffer fg pointer");
5680
6370
  }
5681
- templateCache.set(strings, cachedStringChunks);
6371
+ return ptr;
5682
6372
  }
5683
- const chunks = [];
5684
- for (let i = 0;i < strings.length; i++) {
5685
- const stringChunk = cachedStringChunks[i];
5686
- if (stringChunk) {
5687
- chunks.push(stringChunk);
5688
- length += stringChunk.plainText.length;
5689
- plainText += stringChunk.plainText;
6373
+ textBufferGetBgPtr(buffer) {
6374
+ const ptr = this.opentui.symbols.textBufferGetBgPtr(buffer);
6375
+ if (!ptr) {
6376
+ throw new Error("Failed to get TextBuffer bg pointer");
5690
6377
  }
5691
- const val = values[i];
5692
- if (typeof val === "object" && "__isChunk" in val) {
5693
- chunks.push(val);
5694
- length += val.plainText.length;
5695
- plainText += val.plainText;
5696
- } else if (val !== undefined) {
5697
- const plainTextStr = String(val);
5698
- chunks.push({
5699
- __isChunk: true,
5700
- text: textEncoder.encode(plainTextStr),
5701
- plainText: plainTextStr,
5702
- attributes: 0
5703
- });
5704
- length += plainTextStr.length;
5705
- plainText += plainTextStr;
6378
+ return ptr;
6379
+ }
6380
+ textBufferGetAttributesPtr(buffer) {
6381
+ const ptr = this.opentui.symbols.textBufferGetAttributesPtr(buffer);
6382
+ if (!ptr) {
6383
+ throw new Error("Failed to get TextBuffer attributes pointer");
5706
6384
  }
6385
+ return ptr;
5707
6386
  }
5708
- return new StyledText(chunks);
5709
- }
5710
-
5711
- // src/lib/hast-styled-text.ts
5712
- class SyntaxStyle {
5713
- styles;
5714
- mergedStyleCache;
5715
- constructor(styles) {
5716
- this.styles = styles;
5717
- this.mergedStyleCache = new Map;
6387
+ textBufferGetLength(buffer) {
6388
+ return this.opentui.symbols.textBufferGetLength(buffer);
5718
6389
  }
5719
- mergeStyles(...styleNames) {
5720
- const cacheKey = styleNames.join(":");
5721
- const cached = this.mergedStyleCache.get(cacheKey);
5722
- if (cached)
5723
- return cached;
5724
- const styleDefinition = {};
5725
- for (const name of styleNames) {
5726
- const style = this.styles[name];
5727
- if (!style)
5728
- continue;
5729
- if (style.fg)
5730
- styleDefinition.fg = style.fg;
5731
- if (style.bg)
5732
- styleDefinition.bg = style.bg;
5733
- if (style.bold !== undefined)
5734
- styleDefinition.bold = style.bold;
5735
- if (style.italic !== undefined)
5736
- styleDefinition.italic = style.italic;
5737
- if (style.underline !== undefined)
5738
- styleDefinition.underline = style.underline;
5739
- if (style.dim !== undefined)
5740
- styleDefinition.dim = style.dim;
6390
+ textBufferSetCell(buffer, index, char, fg2, bg2, attr) {
6391
+ this.opentui.symbols.textBufferSetCell(buffer, index, char, fg2, bg2, attr);
6392
+ }
6393
+ textBufferConcat(buffer1, buffer2) {
6394
+ const resultPtr = this.opentui.symbols.textBufferConcat(buffer1, buffer2);
6395
+ if (!resultPtr) {
6396
+ throw new Error("Failed to concatenate TextBuffers");
5741
6397
  }
5742
- const attributes = createTextAttributes({
5743
- bold: styleDefinition.bold,
5744
- italic: styleDefinition.italic,
5745
- underline: styleDefinition.underline,
5746
- dim: styleDefinition.dim
5747
- });
5748
- const merged = {
5749
- fg: styleDefinition.fg,
5750
- bg: styleDefinition.bg,
5751
- attributes
6398
+ const length = this.textBufferGetLength(resultPtr);
6399
+ const charPtr = this.textBufferGetCharPtr(resultPtr);
6400
+ const fgPtr = this.textBufferGetFgPtr(resultPtr);
6401
+ const bgPtr = this.textBufferGetBgPtr(resultPtr);
6402
+ const attributesPtr = this.textBufferGetAttributesPtr(resultPtr);
6403
+ const buffer = {
6404
+ char: new Uint32Array(toArrayBuffer(charPtr, 0, length * 4)),
6405
+ fg: new Float32Array(toArrayBuffer(fgPtr, 0, length * 4 * 4)),
6406
+ bg: new Float32Array(toArrayBuffer(bgPtr, 0, length * 4 * 4)),
6407
+ attributes: new Uint16Array(toArrayBuffer(attributesPtr, 0, length * 2))
5752
6408
  };
5753
- this.mergedStyleCache.set(cacheKey, merged);
5754
- return merged;
6409
+ return new TextBuffer(this, resultPtr, buffer, length);
5755
6410
  }
5756
- clearCache() {
5757
- this.mergedStyleCache.clear();
6411
+ textBufferResize(buffer, newLength) {
6412
+ this.opentui.symbols.textBufferResize(buffer, newLength);
6413
+ const buffers = this.getTextBuffer(buffer, newLength);
6414
+ return buffers;
5758
6415
  }
5759
- getCacheSize() {
5760
- return this.mergedStyleCache.size;
6416
+ textBufferReset(buffer) {
6417
+ this.opentui.symbols.textBufferReset(buffer);
5761
6418
  }
5762
- }
5763
- var textEncoder2 = new TextEncoder;
5764
- function hastToTextChunks(node, syntaxStyle, parentStyles = []) {
5765
- const chunks = [];
5766
- if (node.type === "text") {
5767
- const stylesToMerge = parentStyles.length > 0 ? parentStyles : ["default"];
5768
- const mergedStyle = syntaxStyle.mergeStyles(...stylesToMerge);
5769
- chunks.push({
5770
- __isChunk: true,
5771
- text: textEncoder2.encode(node.value),
5772
- plainText: node.value,
5773
- fg: mergedStyle.fg,
5774
- bg: mergedStyle.bg,
5775
- attributes: mergedStyle.attributes
5776
- });
5777
- } else if (node.type === "element") {
5778
- let currentStyles = [...parentStyles];
5779
- if (node.properties?.className) {
5780
- const classes = node.properties.className.split(" ");
5781
- for (const cls of classes) {
5782
- currentStyles.push(cls);
5783
- }
6419
+ textBufferSetSelection(buffer, start, end, bgColor, fgColor) {
6420
+ const bg2 = bgColor ? bgColor.buffer : null;
6421
+ const fg2 = fgColor ? fgColor.buffer : null;
6422
+ this.opentui.symbols.textBufferSetSelection(buffer, start, end, bg2, fg2);
6423
+ }
6424
+ textBufferResetSelection(buffer) {
6425
+ this.opentui.symbols.textBufferResetSelection(buffer);
6426
+ }
6427
+ textBufferSetDefaultFg(buffer, fg2) {
6428
+ const fgPtr = fg2 ? fg2.buffer : null;
6429
+ this.opentui.symbols.textBufferSetDefaultFg(buffer, fgPtr);
6430
+ }
6431
+ textBufferSetDefaultBg(buffer, bg2) {
6432
+ const bgPtr = bg2 ? bg2.buffer : null;
6433
+ this.opentui.symbols.textBufferSetDefaultBg(buffer, bgPtr);
6434
+ }
6435
+ textBufferSetDefaultAttributes(buffer, attributes) {
6436
+ const attrValue = attributes === null ? null : new Uint8Array([attributes]);
6437
+ this.opentui.symbols.textBufferSetDefaultAttributes(buffer, attrValue);
6438
+ }
6439
+ textBufferResetDefaults(buffer) {
6440
+ this.opentui.symbols.textBufferResetDefaults(buffer);
6441
+ }
6442
+ textBufferWriteChunk(buffer, textBytes, fg2, bg2, attributes) {
6443
+ const attrValue = attributes === null ? null : new Uint8Array([attributes]);
6444
+ return this.opentui.symbols.textBufferWriteChunk(buffer, textBytes, textBytes.length, fg2 ? fg2.buffer : null, bg2 ? bg2.buffer : null, attrValue);
6445
+ }
6446
+ textBufferGetCapacity(buffer) {
6447
+ return this.opentui.symbols.textBufferGetCapacity(buffer);
6448
+ }
6449
+ textBufferFinalizeLineInfo(buffer) {
6450
+ this.opentui.symbols.textBufferFinalizeLineInfo(buffer);
6451
+ }
6452
+ textBufferGetLineInfo(buffer) {
6453
+ const lineCount = this.opentui.symbols.textBufferGetLineCount(buffer);
6454
+ if (lineCount === 0) {
6455
+ return { lineStarts: [], lineWidths: [] };
5784
6456
  }
5785
- for (const child of node.children) {
5786
- chunks.push(...hastToTextChunks(child, syntaxStyle, currentStyles));
6457
+ const lineStartsPtr = this.opentui.symbols.textBufferGetLineStartsPtr(buffer);
6458
+ const lineWidthsPtr = this.opentui.symbols.textBufferGetLineWidthsPtr(buffer);
6459
+ if (!lineStartsPtr || !lineWidthsPtr) {
6460
+ return { lineStarts: [], lineWidths: [] };
5787
6461
  }
6462
+ const lineStartsArray = new Uint32Array(toArrayBuffer(lineStartsPtr, 0, lineCount * 4));
6463
+ const lineWidthsArray = new Uint32Array(toArrayBuffer(lineWidthsPtr, 0, lineCount * 4));
6464
+ const lineStarts = Array.from(lineStartsArray);
6465
+ const lineWidths = Array.from(lineWidthsArray);
6466
+ return { lineStarts, lineWidths };
6467
+ }
6468
+ getTextBufferArrays(buffer, size) {
6469
+ return this.getTextBuffer(buffer, size);
6470
+ }
6471
+ bufferDrawTextBuffer(buffer, textBuffer, x, y, clipRect) {
6472
+ const hasClipRect = clipRect !== undefined && clipRect !== null;
6473
+ const clipX = clipRect?.x ?? 0;
6474
+ const clipY = clipRect?.y ?? 0;
6475
+ const clipWidth = clipRect?.width ?? 0;
6476
+ const clipHeight = clipRect?.height ?? 0;
6477
+ this.opentui.symbols.bufferDrawTextBuffer(buffer, textBuffer, x, y, clipX, clipY, clipWidth, clipHeight, hasClipRect);
5788
6478
  }
5789
- return chunks;
5790
6479
  }
5791
- function hastToStyledText(hast, syntaxStyle) {
5792
- const chunks = hastToTextChunks(hast, syntaxStyle);
5793
- return new StyledText(chunks);
6480
+ var opentuiLibPath;
6481
+ var opentuiLib;
6482
+ function setRenderLibPath(libPath) {
6483
+ opentuiLibPath = libPath;
6484
+ }
6485
+ function resolveRenderLib() {
6486
+ if (!opentuiLib) {
6487
+ opentuiLib = new FFIRenderLib(opentuiLibPath);
6488
+ }
6489
+ return opentuiLib;
5794
6490
  }
6491
+
5795
6492
  // src/buffer.ts
5796
6493
  var fbIdCounter = 0;
5797
6494
  function isRGBAWithAlpha(color) {
@@ -5968,17 +6665,17 @@ class OptimizedBuffer {
5968
6665
  }
5969
6666
  this.setCell(x, y, char, fg2, bg2, attributes);
5970
6667
  }
5971
- drawText(text, x, y, fg2, bg2, attributes = 0, selection) {
5972
- if (!selection) {
6668
+ drawText(text, x, y, fg2, bg2, attributes = 0, selection2) {
6669
+ if (!selection2) {
5973
6670
  this.drawTextFFI.call(this, text, x, y, fg2, bg2, attributes);
5974
6671
  return;
5975
6672
  }
5976
- const { start, end } = selection;
6673
+ const { start, end } = selection2;
5977
6674
  let selectionBg;
5978
6675
  let selectionFg;
5979
- if (selection.bgColor) {
5980
- selectionBg = selection.bgColor;
5981
- selectionFg = selection.fgColor || fg2;
6676
+ if (selection2.bgColor) {
6677
+ selectionBg = selection2.bgColor;
6678
+ selectionFg = selection2.fgColor || fg2;
5982
6679
  } else {
5983
6680
  const defaultBg = bg2 || RGBA.fromValues(0, 0, 0, 0);
5984
6681
  selectionFg = defaultBg.a > 0 ? defaultBg : RGBA.fromValues(0, 0, 0, 1);
@@ -6972,451 +7669,204 @@ function evaluateTimelineSync(item, timelineTime, deltaTime = 0) {
6972
7669
  }
6973
7670
  function evaluateItem(item, timelineTime, deltaTime = 0) {
6974
7671
  if (item.type === "animation") {
6975
- evaluateAnimation(item, timelineTime, deltaTime);
6976
- } else if (item.type === "callback") {
6977
- evaluateCallback(item, timelineTime);
6978
- }
6979
- }
6980
-
6981
- class Timeline {
6982
- items = [];
6983
- subTimelines = [];
6984
- currentTime = 0;
6985
- isPlaying = false;
6986
- isComplete = false;
6987
- duration;
6988
- loop;
6989
- synced = false;
6990
- autoplay;
6991
- onComplete;
6992
- onPause;
6993
- constructor(options = {}) {
6994
- this.duration = options.duration || 1000;
6995
- this.loop = options.loop === true;
6996
- this.autoplay = options.autoplay !== false;
6997
- this.onComplete = options.onComplete;
6998
- this.onPause = options.onPause;
6999
- }
7000
- add(target, properties, startTime = 0) {
7001
- const resolvedStartTime = typeof startTime === "string" ? 0 : startTime;
7002
- const animationProperties = {};
7003
- for (const key in properties) {
7004
- if (!["duration", "ease", "onUpdate", "onComplete", "onStart", "onLoop", "loop", "loopDelay", "alternate"].includes(key)) {
7005
- if (typeof properties[key] === "number") {
7006
- animationProperties[key] = properties[key];
7007
- }
7008
- }
7009
- }
7010
- this.items.push({
7011
- type: "animation",
7012
- startTime: resolvedStartTime,
7013
- target: Array.isArray(target) ? target : [target],
7014
- properties: animationProperties,
7015
- initialValues: [],
7016
- duration: properties.duration !== undefined ? properties.duration : 1000,
7017
- ease: properties.ease || "linear",
7018
- loop: properties.loop,
7019
- loopDelay: properties.loopDelay || 0,
7020
- alternate: properties.alternate || false,
7021
- onUpdate: properties.onUpdate,
7022
- onComplete: properties.onComplete,
7023
- onStart: properties.onStart,
7024
- onLoop: properties.onLoop,
7025
- completed: false,
7026
- started: false,
7027
- currentLoop: 0,
7028
- once: properties.once ?? false
7029
- });
7030
- return this;
7031
- }
7032
- once(target, properties) {
7033
- this.add(target, {
7034
- ...properties,
7035
- once: true
7036
- }, this.currentTime);
7037
- return this;
7038
- }
7039
- call(callback, startTime = 0) {
7040
- const resolvedStartTime = typeof startTime === "string" ? 0 : startTime;
7041
- this.items.push({
7042
- type: "callback",
7043
- startTime: resolvedStartTime,
7044
- callback,
7045
- executed: false
7046
- });
7047
- return this;
7048
- }
7049
- sync(timeline, startTime = 0) {
7050
- if (timeline.synced) {
7051
- throw new Error("Timeline already synced");
7052
- }
7053
- this.subTimelines.push({
7054
- type: "timeline",
7055
- startTime,
7056
- timeline
7057
- });
7058
- timeline.synced = true;
7059
- return this;
7060
- }
7061
- play() {
7062
- if (this.isComplete) {
7063
- return this.restart();
7064
- }
7065
- this.subTimelines.forEach((subTimeline) => {
7066
- if (subTimeline.timelineStarted) {
7067
- subTimeline.timeline.play();
7068
- }
7069
- });
7070
- this.isPlaying = true;
7071
- return this;
7072
- }
7073
- pause() {
7074
- this.subTimelines.forEach((subTimeline) => {
7075
- subTimeline.timeline.pause();
7076
- });
7077
- this.isPlaying = false;
7078
- if (this.onPause) {
7079
- this.onPause();
7080
- }
7081
- return this;
7082
- }
7083
- resetItems() {
7084
- this.items.forEach((item) => {
7085
- if (item.type === "callback") {
7086
- item.executed = false;
7087
- } else if (item.type === "animation") {
7088
- item.completed = false;
7089
- item.started = false;
7090
- item.currentLoop = 0;
7091
- }
7092
- });
7093
- this.subTimelines.forEach((subTimeline) => {
7094
- subTimeline.timelineStarted = false;
7095
- if (subTimeline.timeline) {
7096
- subTimeline.timeline.restart();
7097
- subTimeline.timeline.pause();
7098
- }
7099
- });
7100
- }
7101
- restart() {
7102
- this.isComplete = false;
7103
- this.currentTime = 0;
7104
- this.isPlaying = true;
7105
- this.resetItems();
7106
- return this;
7107
- }
7108
- update(deltaTime) {
7109
- for (const subTimeline of this.subTimelines) {
7110
- evaluateTimelineSync(subTimeline, this.currentTime + deltaTime, deltaTime);
7111
- }
7112
- if (!this.isPlaying)
7113
- return;
7114
- this.currentTime += deltaTime;
7115
- for (const item of this.items) {
7116
- evaluateItem(item, this.currentTime, deltaTime);
7117
- }
7118
- for (let i = this.items.length - 1;i >= 0; i--) {
7119
- const item = this.items[i];
7120
- if (item.type === "animation" && item.once && item.completed) {
7121
- this.items.splice(i, 1);
7122
- }
7123
- }
7124
- if (this.loop && this.currentTime >= this.duration) {
7125
- const overshoot = this.currentTime % this.duration;
7126
- this.resetItems();
7127
- this.currentTime = 0;
7128
- if (overshoot > 0) {
7129
- this.update(overshoot);
7130
- }
7131
- } else if (!this.loop && this.currentTime >= this.duration) {
7132
- this.currentTime = this.duration;
7133
- this.isPlaying = false;
7134
- this.isComplete = true;
7135
- if (this.onComplete) {
7136
- this.onComplete();
7137
- }
7138
- }
7139
- }
7140
- }
7141
-
7142
- class TimelineEngine {
7143
- timelines = new Set;
7144
- defaults = {
7145
- frameRate: 60
7146
- };
7147
- register(timeline) {
7148
- this.timelines.add(timeline);
7149
- }
7150
- unregister(timeline) {
7151
- this.timelines.delete(timeline);
7152
- }
7153
- clear() {
7154
- this.timelines.clear();
7155
- }
7156
- update(deltaTime) {
7157
- for (const timeline of this.timelines) {
7158
- if (!timeline.synced) {
7159
- timeline.update(deltaTime);
7160
- }
7161
- }
7162
- }
7163
- }
7164
- var engine = new TimelineEngine;
7165
- function createTimeline(options = {}) {
7166
- const timeline = new Timeline(options);
7167
- if (options.autoplay !== false) {
7168
- timeline.play();
7169
- }
7170
- engine.register(timeline);
7171
- return timeline;
7172
- }
7173
- // src/lib/selection.ts
7174
- class Selection {
7175
- _anchor;
7176
- _focus;
7177
- _selectedRenderables = [];
7178
- constructor(anchor, focus) {
7179
- this._anchor = { ...anchor };
7180
- this._focus = { ...focus };
7181
- }
7182
- get anchor() {
7183
- return { ...this._anchor };
7184
- }
7185
- get focus() {
7186
- return { ...this._focus };
7187
- }
7188
- get bounds() {
7189
- return {
7190
- startX: Math.min(this._anchor.x, this._focus.x),
7191
- startY: Math.min(this._anchor.y, this._focus.y),
7192
- endX: Math.max(this._anchor.x, this._focus.x),
7193
- endY: Math.max(this._anchor.y, this._focus.y)
7194
- };
7195
- }
7196
- updateSelectedRenderables(selectedRenderables) {
7197
- this._selectedRenderables = selectedRenderables;
7198
- }
7199
- getSelectedText() {
7200
- const selectedTexts = this._selectedRenderables.sort((a, b) => {
7201
- const aY = a.y;
7202
- const bY = b.y;
7203
- if (aY !== bY) {
7204
- return aY - bY;
7205
- }
7206
- return a.x - b.x;
7207
- }).map((renderable) => renderable.getSelectedText()).filter((text) => text);
7208
- return selectedTexts.join(`
7209
- `);
7210
- }
7211
- }
7212
-
7213
- class TextSelectionHelper {
7214
- getX;
7215
- getY;
7216
- getTextLength;
7217
- getLineInfo;
7218
- localSelection = null;
7219
- cachedGlobalSelection = null;
7220
- constructor(getX, getY, getTextLength, getLineInfo) {
7221
- this.getX = getX;
7222
- this.getY = getY;
7223
- this.getTextLength = getTextLength;
7224
- this.getLineInfo = getLineInfo;
7225
- }
7226
- hasSelection() {
7227
- return this.localSelection !== null;
7672
+ evaluateAnimation(item, timelineTime, deltaTime);
7673
+ } else if (item.type === "callback") {
7674
+ evaluateCallback(item, timelineTime);
7228
7675
  }
7229
- getSelection() {
7230
- return this.localSelection;
7676
+ }
7677
+
7678
+ class Timeline {
7679
+ items = [];
7680
+ subTimelines = [];
7681
+ currentTime = 0;
7682
+ isPlaying = false;
7683
+ isComplete = false;
7684
+ duration;
7685
+ loop;
7686
+ synced = false;
7687
+ autoplay;
7688
+ onComplete;
7689
+ onPause;
7690
+ constructor(options = {}) {
7691
+ this.duration = options.duration || 1000;
7692
+ this.loop = options.loop === true;
7693
+ this.autoplay = options.autoplay !== false;
7694
+ this.onComplete = options.onComplete;
7695
+ this.onPause = options.onPause;
7231
7696
  }
7232
- reevaluateSelection(width, height = 1) {
7233
- if (!this.cachedGlobalSelection) {
7234
- return false;
7697
+ add(target, properties, startTime = 0) {
7698
+ const resolvedStartTime = typeof startTime === "string" ? 0 : startTime;
7699
+ const animationProperties = {};
7700
+ for (const key in properties) {
7701
+ if (!["duration", "ease", "onUpdate", "onComplete", "onStart", "onLoop", "loop", "loopDelay", "alternate"].includes(key)) {
7702
+ if (typeof properties[key] === "number") {
7703
+ animationProperties[key] = properties[key];
7704
+ }
7705
+ }
7235
7706
  }
7236
- return this.onSelectionChanged(this.cachedGlobalSelection, width, height);
7707
+ this.items.push({
7708
+ type: "animation",
7709
+ startTime: resolvedStartTime,
7710
+ target: Array.isArray(target) ? target : [target],
7711
+ properties: animationProperties,
7712
+ initialValues: [],
7713
+ duration: properties.duration !== undefined ? properties.duration : 1000,
7714
+ ease: properties.ease || "linear",
7715
+ loop: properties.loop,
7716
+ loopDelay: properties.loopDelay || 0,
7717
+ alternate: properties.alternate || false,
7718
+ onUpdate: properties.onUpdate,
7719
+ onComplete: properties.onComplete,
7720
+ onStart: properties.onStart,
7721
+ onLoop: properties.onLoop,
7722
+ completed: false,
7723
+ started: false,
7724
+ currentLoop: 0,
7725
+ once: properties.once ?? false
7726
+ });
7727
+ return this;
7237
7728
  }
7238
- shouldStartSelection(x, y, width, height) {
7239
- const localX = x - this.getX();
7240
- const localY = y - this.getY();
7241
- return localX >= 0 && localX < width && localY >= 0 && localY < height;
7729
+ once(target, properties) {
7730
+ this.add(target, {
7731
+ ...properties,
7732
+ once: true
7733
+ }, this.currentTime);
7734
+ return this;
7242
7735
  }
7243
- onSelectionChanged(selection, width, height = 1) {
7244
- this.cachedGlobalSelection = selection;
7245
- const previousSelection = this.localSelection;
7246
- if (!selection?.isActive) {
7247
- this.localSelection = null;
7248
- return previousSelection !== null;
7249
- }
7250
- const myY = this.getY();
7251
- const myEndY = myY + height - 1;
7252
- if (myEndY < selection.anchor.y || myY > selection.focus.y) {
7253
- this.localSelection = null;
7254
- return previousSelection !== null;
7255
- }
7256
- if (height === 1) {
7257
- this.localSelection = this.calculateSingleLineSelection(myY, selection.anchor.y, selection.focus.y, selection.anchor.x, selection.focus.x, width);
7258
- } else {
7259
- this.localSelection = this.calculateMultiLineSelection(myY, selection.anchor.y, selection.focus.y, selection.anchor.x, selection.focus.x);
7260
- }
7261
- return this.localSelection !== null !== (previousSelection !== null) || this.localSelection?.start !== previousSelection?.start || this.localSelection?.end !== previousSelection?.end;
7736
+ call(callback, startTime = 0) {
7737
+ const resolvedStartTime = typeof startTime === "string" ? 0 : startTime;
7738
+ this.items.push({
7739
+ type: "callback",
7740
+ startTime: resolvedStartTime,
7741
+ callback,
7742
+ executed: false
7743
+ });
7744
+ return this;
7262
7745
  }
7263
- calculateSingleLineSelection(lineY, anchorY, focusY, anchorX, focusX, width) {
7264
- const textLength = this.getTextLength();
7265
- const myX = this.getX();
7266
- if (lineY > anchorY && lineY < focusY) {
7267
- return { start: 0, end: textLength };
7268
- }
7269
- if (lineY === anchorY && lineY === focusY) {
7270
- const start = Math.max(0, Math.min(anchorX - myX, textLength));
7271
- const end = Math.max(0, Math.min(focusX - myX, textLength));
7272
- return start < end ? { start, end } : null;
7273
- }
7274
- if (lineY === anchorY) {
7275
- const start = Math.max(0, Math.min(anchorX - myX, textLength));
7276
- return start < textLength ? { start, end: textLength } : null;
7277
- }
7278
- if (lineY === focusY) {
7279
- const end = Math.max(0, Math.min(focusX - myX, textLength));
7280
- return end > 0 ? { start: 0, end } : null;
7746
+ sync(timeline, startTime = 0) {
7747
+ if (timeline.synced) {
7748
+ throw new Error("Timeline already synced");
7281
7749
  }
7282
- return null;
7750
+ this.subTimelines.push({
7751
+ type: "timeline",
7752
+ startTime,
7753
+ timeline
7754
+ });
7755
+ timeline.synced = true;
7756
+ return this;
7283
7757
  }
7284
- calculateMultiLineSelection(startY, anchorY, focusY, anchorX, focusX) {
7285
- const lineInfo = this.getLineInfo?.();
7286
- if (!lineInfo) {
7287
- return { start: 0, end: this.getTextLength() };
7758
+ play() {
7759
+ if (this.isComplete) {
7760
+ return this.restart();
7288
7761
  }
7289
- const myX = this.getX();
7290
- let selectionStart = null;
7291
- let selectionEnd = null;
7292
- for (let i = 0;i < lineInfo.lineStarts.length; i++) {
7293
- const lineY = startY + i;
7294
- if (lineY < anchorY || lineY > focusY)
7295
- continue;
7296
- const lineStart = lineInfo.lineStarts[i];
7297
- const lineEnd = i < lineInfo.lineStarts.length - 1 ? lineInfo.lineStarts[i + 1] - 1 : this.getTextLength();
7298
- const lineWidth = lineInfo.lineWidths[i];
7299
- if (lineY > anchorY && lineY < focusY) {
7300
- if (selectionStart === null)
7301
- selectionStart = lineStart;
7302
- selectionEnd = lineEnd;
7303
- } else if (lineY === anchorY && lineY === focusY) {
7304
- const localStartX = Math.max(0, Math.min(anchorX - myX, lineWidth));
7305
- const localEndX = Math.max(0, Math.min(focusX - myX, lineWidth));
7306
- if (localStartX < localEndX) {
7307
- selectionStart = lineStart + localStartX;
7308
- selectionEnd = lineStart + localEndX;
7309
- }
7310
- } else if (lineY === anchorY) {
7311
- const localStartX = Math.max(0, Math.min(anchorX - myX, lineWidth));
7312
- if (localStartX < lineWidth) {
7313
- selectionStart = lineStart + localStartX;
7314
- selectionEnd = lineEnd;
7315
- }
7316
- } else if (lineY === focusY) {
7317
- const localEndX = Math.max(0, Math.min(focusX - myX, lineWidth));
7318
- if (localEndX > 0) {
7319
- if (selectionStart === null)
7320
- selectionStart = lineStart;
7321
- selectionEnd = lineStart + localEndX;
7322
- }
7762
+ this.subTimelines.forEach((subTimeline) => {
7763
+ if (subTimeline.timelineStarted) {
7764
+ subTimeline.timeline.play();
7323
7765
  }
7324
- }
7325
- return selectionStart !== null && selectionEnd !== null && selectionStart < selectionEnd ? { start: selectionStart, end: selectionEnd } : null;
7326
- }
7327
- }
7328
-
7329
- class ASCIIFontSelectionHelper {
7330
- getX;
7331
- getY;
7332
- getText;
7333
- getFont;
7334
- localSelection = null;
7335
- cachedGlobalSelection = null;
7336
- constructor(getX, getY, getText, getFont) {
7337
- this.getX = getX;
7338
- this.getY = getY;
7339
- this.getText = getText;
7340
- this.getFont = getFont;
7766
+ });
7767
+ this.isPlaying = true;
7768
+ return this;
7341
7769
  }
7342
- hasSelection() {
7343
- return this.localSelection !== null;
7770
+ pause() {
7771
+ this.subTimelines.forEach((subTimeline) => {
7772
+ subTimeline.timeline.pause();
7773
+ });
7774
+ this.isPlaying = false;
7775
+ if (this.onPause) {
7776
+ this.onPause();
7777
+ }
7778
+ return this;
7344
7779
  }
7345
- getSelection() {
7346
- return this.localSelection;
7780
+ resetItems() {
7781
+ this.items.forEach((item) => {
7782
+ if (item.type === "callback") {
7783
+ item.executed = false;
7784
+ } else if (item.type === "animation") {
7785
+ item.completed = false;
7786
+ item.started = false;
7787
+ item.currentLoop = 0;
7788
+ }
7789
+ });
7790
+ this.subTimelines.forEach((subTimeline) => {
7791
+ subTimeline.timelineStarted = false;
7792
+ if (subTimeline.timeline) {
7793
+ subTimeline.timeline.restart();
7794
+ subTimeline.timeline.pause();
7795
+ }
7796
+ });
7347
7797
  }
7348
- shouldStartSelection(x, y, width, height) {
7349
- const localX = x - this.getX();
7350
- const localY = y - this.getY();
7351
- if (localX < 0 || localX >= width || localY < 0 || localY >= height) {
7352
- return false;
7353
- }
7354
- const text = this.getText();
7355
- const font = this.getFont();
7356
- const charIndex = coordinateToCharacterIndex(localX, text, font);
7357
- return charIndex >= 0 && charIndex <= text.length;
7798
+ restart() {
7799
+ this.isComplete = false;
7800
+ this.currentTime = 0;
7801
+ this.isPlaying = true;
7802
+ this.resetItems();
7803
+ return this;
7358
7804
  }
7359
- onSelectionChanged(selection, width, height) {
7360
- this.cachedGlobalSelection = selection;
7361
- const previousSelection = this.localSelection;
7362
- if (!selection?.isActive) {
7363
- this.localSelection = null;
7364
- return previousSelection !== null;
7365
- }
7366
- const myX = this.getX();
7367
- const myY = this.getY();
7368
- const myEndY = myY + height - 1;
7369
- const text = this.getText();
7370
- const font = this.getFont();
7371
- let selStart;
7372
- let selEnd;
7373
- if (selection.anchor.y < selection.focus.y || selection.anchor.y === selection.focus.y && selection.anchor.x <= selection.focus.x) {
7374
- selStart = selection.anchor;
7375
- selEnd = selection.focus;
7376
- } else {
7377
- selStart = selection.focus;
7378
- selEnd = selection.anchor;
7805
+ update(deltaTime) {
7806
+ for (const subTimeline of this.subTimelines) {
7807
+ evaluateTimelineSync(subTimeline, this.currentTime + deltaTime, deltaTime);
7379
7808
  }
7380
- if (myEndY < selStart.y || myY > selEnd.y) {
7381
- this.localSelection = null;
7382
- return previousSelection !== null;
7809
+ if (!this.isPlaying)
7810
+ return;
7811
+ this.currentTime += deltaTime;
7812
+ for (const item of this.items) {
7813
+ evaluateItem(item, this.currentTime, deltaTime);
7383
7814
  }
7384
- let startCharIndex = 0;
7385
- let endCharIndex = text.length;
7386
- if (selStart.y > myEndY) {
7387
- this.localSelection = null;
7388
- return previousSelection !== null;
7389
- } else if (selStart.y >= myY && selStart.y <= myEndY) {
7390
- const localX = selStart.x - myX;
7391
- if (localX > 0) {
7392
- startCharIndex = coordinateToCharacterIndex(localX, text, font);
7815
+ for (let i = this.items.length - 1;i >= 0; i--) {
7816
+ const item = this.items[i];
7817
+ if (item.type === "animation" && item.once && item.completed) {
7818
+ this.items.splice(i, 1);
7393
7819
  }
7394
7820
  }
7395
- if (selEnd.y < myY) {
7396
- this.localSelection = null;
7397
- return previousSelection !== null;
7398
- } else if (selEnd.y >= myY && selEnd.y <= myEndY) {
7399
- const localX = selEnd.x - myX;
7400
- if (localX >= 0) {
7401
- endCharIndex = coordinateToCharacterIndex(localX, text, font);
7402
- } else {
7403
- endCharIndex = 0;
7821
+ if (this.loop && this.currentTime >= this.duration) {
7822
+ const overshoot = this.currentTime % this.duration;
7823
+ this.resetItems();
7824
+ this.currentTime = 0;
7825
+ if (overshoot > 0) {
7826
+ this.update(overshoot);
7827
+ }
7828
+ } else if (!this.loop && this.currentTime >= this.duration) {
7829
+ this.currentTime = this.duration;
7830
+ this.isPlaying = false;
7831
+ this.isComplete = true;
7832
+ if (this.onComplete) {
7833
+ this.onComplete();
7404
7834
  }
7405
7835
  }
7406
- if (startCharIndex < endCharIndex && startCharIndex >= 0 && endCharIndex <= text.length) {
7407
- this.localSelection = { start: startCharIndex, end: endCharIndex };
7408
- } else {
7409
- this.localSelection = null;
7410
- }
7411
- return this.localSelection !== null !== (previousSelection !== null) || this.localSelection?.start !== previousSelection?.start || this.localSelection?.end !== previousSelection?.end;
7412
7836
  }
7413
- reevaluateSelection(width, height) {
7414
- if (!this.cachedGlobalSelection) {
7415
- return false;
7837
+ }
7838
+
7839
+ class TimelineEngine {
7840
+ timelines = new Set;
7841
+ defaults = {
7842
+ frameRate: 60
7843
+ };
7844
+ register(timeline) {
7845
+ this.timelines.add(timeline);
7846
+ }
7847
+ unregister(timeline) {
7848
+ this.timelines.delete(timeline);
7849
+ }
7850
+ clear() {
7851
+ this.timelines.clear();
7852
+ }
7853
+ update(deltaTime) {
7854
+ for (const timeline of this.timelines) {
7855
+ if (!timeline.synced) {
7856
+ timeline.update(deltaTime);
7857
+ }
7416
7858
  }
7417
- return this.onSelectionChanged(this.cachedGlobalSelection, width, height);
7418
7859
  }
7419
7860
  }
7861
+ var engine = new TimelineEngine;
7862
+ function createTimeline(options = {}) {
7863
+ const timeline = new Timeline(options);
7864
+ if (options.autoplay !== false) {
7865
+ timeline.play();
7866
+ }
7867
+ engine.register(timeline);
7868
+ return timeline;
7869
+ }
7420
7870
  // src/ansi.ts
7421
7871
  var ANSI = {
7422
7872
  switchToAlternateScreen: "\x1B[?1049h",
@@ -7442,7 +7892,10 @@ var ANSI = {
7442
7892
  enableAnyEventTracking: "\x1B[?1003h",
7443
7893
  disableAnyEventTracking: "\x1B[?1003l",
7444
7894
  enableSGRMouseMode: "\x1B[?1006h",
7445
- disableSGRMouseMode: "\x1B[?1006l"
7895
+ disableSGRMouseMode: "\x1B[?1006l",
7896
+ makeRoomForRenderer: (height) => `
7897
+ `.repeat(height) + `\x1B[${height}A`,
7898
+ clearRendererSpace: (height) => `\x1B[${height}A\x1B[1G\x1B[J`
7446
7899
  };
7447
7900
 
7448
7901
  // src/console.ts
@@ -8102,106 +8555,6 @@ class TerminalConsole extends EventEmitter5 {
8102
8555
  }
8103
8556
  }
8104
8557
 
8105
- // src/lib/parse.mouse.ts
8106
- class MouseParser {
8107
- mouseButtonsPressed = new Set;
8108
- static SCROLL_DIRECTIONS = {
8109
- 64: "up",
8110
- 65: "down",
8111
- 66: "left",
8112
- 67: "right"
8113
- };
8114
- reset() {
8115
- this.mouseButtonsPressed.clear();
8116
- }
8117
- parseMouseEvent(data) {
8118
- const str = data.toString();
8119
- const sgrMatch = str.match(/\x1b\[<(\d+);(\d+);(\d+)([Mm])/);
8120
- if (sgrMatch) {
8121
- const [, buttonCode, x, y, pressRelease] = sgrMatch;
8122
- const rawButtonCode = parseInt(buttonCode);
8123
- const scrollDirection = MouseParser.SCROLL_DIRECTIONS[rawButtonCode];
8124
- const isScroll = scrollDirection !== undefined;
8125
- const button = rawButtonCode & 3;
8126
- const isMotion = (rawButtonCode & 32) !== 0;
8127
- const modifiers = {
8128
- shift: (rawButtonCode & 4) !== 0,
8129
- alt: (rawButtonCode & 8) !== 0,
8130
- ctrl: (rawButtonCode & 16) !== 0
8131
- };
8132
- let type;
8133
- let scrollInfo;
8134
- if (isScroll && pressRelease === "M") {
8135
- type = "scroll";
8136
- scrollInfo = {
8137
- direction: scrollDirection,
8138
- delta: 1
8139
- };
8140
- } else if (isMotion) {
8141
- const isDragging = this.mouseButtonsPressed.size > 0;
8142
- if (button === 3) {
8143
- type = "move";
8144
- } else if (isDragging) {
8145
- type = "drag";
8146
- } else {
8147
- type = "move";
8148
- }
8149
- } else {
8150
- type = pressRelease === "M" ? "down" : "up";
8151
- if (type === "down" && button !== 3) {
8152
- this.mouseButtonsPressed.add(button);
8153
- } else if (type === "up") {
8154
- this.mouseButtonsPressed.clear();
8155
- }
8156
- }
8157
- return {
8158
- type,
8159
- button: button === 3 ? 0 : button,
8160
- x: parseInt(x) - 1,
8161
- y: parseInt(y) - 1,
8162
- modifiers,
8163
- scroll: scrollInfo
8164
- };
8165
- }
8166
- if (str.startsWith("\x1B[M") && str.length >= 6) {
8167
- const buttonByte = str.charCodeAt(3) - 32;
8168
- const x = str.charCodeAt(4) - 33;
8169
- const y = str.charCodeAt(5) - 33;
8170
- const scrollDirection = MouseParser.SCROLL_DIRECTIONS[buttonByte];
8171
- const isScroll = scrollDirection !== undefined;
8172
- const button = buttonByte & 3;
8173
- const modifiers = {
8174
- shift: (buttonByte & 4) !== 0,
8175
- alt: (buttonByte & 8) !== 0,
8176
- ctrl: (buttonByte & 16) !== 0
8177
- };
8178
- let type;
8179
- let actualButton;
8180
- let scrollInfo;
8181
- if (isScroll) {
8182
- type = "scroll";
8183
- actualButton = 0;
8184
- scrollInfo = {
8185
- direction: scrollDirection,
8186
- delta: 1
8187
- };
8188
- } else {
8189
- type = button === 3 ? "up" : "down";
8190
- actualButton = button === 3 ? 0 : button;
8191
- }
8192
- return {
8193
- type,
8194
- button: actualButton,
8195
- x,
8196
- y,
8197
- modifiers,
8198
- scroll: scrollInfo
8199
- };
8200
- }
8201
- return null;
8202
- }
8203
- }
8204
-
8205
8558
  // src/renderer.ts
8206
8559
  import { EventEmitter as EventEmitter6 } from "events";
8207
8560
 
@@ -8240,6 +8593,11 @@ var MouseButton;
8240
8593
  MouseButton2[MouseButton2["WHEEL_UP"] = 4] = "WHEEL_UP";
8241
8594
  MouseButton2[MouseButton2["WHEEL_DOWN"] = 5] = "WHEEL_DOWN";
8242
8595
  })(MouseButton ||= {});
8596
+ ["SIGINT", "SIGTERM", "SIGQUIT", "SIGABRT"].forEach((signal) => {
8597
+ process.on(signal, () => {
8598
+ process.exit();
8599
+ });
8600
+ });
8243
8601
  async function createCliRenderer(config = {}) {
8244
8602
  if (process.argv.includes("--delay-start")) {
8245
8603
  await new Promise((resolve) => setTimeout(resolve, 5000));
@@ -8276,7 +8634,6 @@ class CliRenderer extends EventEmitter6 {
8276
8634
  stdout;
8277
8635
  exitOnCtrlC;
8278
8636
  isDestroyed = false;
8279
- isShuttingDown = false;
8280
8637
  nextRenderBuffer;
8281
8638
  currentRenderBuffer;
8282
8639
  _isRunning = false;
@@ -8308,6 +8665,8 @@ class CliRenderer extends EventEmitter6 {
8308
8665
  targetFrameTime = 0;
8309
8666
  immediateRerenderRequested = false;
8310
8667
  updateScheduled = false;
8668
+ liveRequestCounter = 0;
8669
+ controlState = "idle" /* IDLE */;
8311
8670
  frameCallbacks = [];
8312
8671
  renderStats = {
8313
8672
  frameCount: 0,
@@ -8393,7 +8752,15 @@ class CliRenderer extends EventEmitter6 {
8393
8752
  this.nextRenderBuffer = this.lib.getNextBuffer(this.rendererPtr);
8394
8753
  this.currentRenderBuffer = this.lib.getCurrentBuffer(this.rendererPtr);
8395
8754
  this.postProcessFns = config.postProcessFns || [];
8396
- this.root = new RootRenderable(this.width, this.height, this.renderContext);
8755
+ const rootContext = {
8756
+ requestLive: () => {
8757
+ this.requestLive();
8758
+ },
8759
+ dropLive: () => {
8760
+ this.dropLive();
8761
+ }
8762
+ };
8763
+ this.root = new RootRenderable(this.width, this.height, this.renderContext, rootContext);
8397
8764
  this.setupTerminal();
8398
8765
  this.takeMemorySnapshot();
8399
8766
  if (this.memorySnapshotInterval > 0) {
@@ -8401,8 +8768,6 @@ class CliRenderer extends EventEmitter6 {
8401
8768
  }
8402
8769
  this.stdout.write = this.interceptStdoutWrite.bind(this);
8403
8770
  this.sigwinchHandler = () => {
8404
- if (this.isShuttingDown)
8405
- return;
8406
8771
  const width2 = this.stdout.columns || 80;
8407
8772
  const height2 = this.stdout.rows || 24;
8408
8773
  this.handleResize(width2, height2);
@@ -8410,6 +8775,7 @@ class CliRenderer extends EventEmitter6 {
8410
8775
  process.on("SIGWINCH", this.sigwinchHandler);
8411
8776
  const handleError = (error) => {
8412
8777
  this.stop();
8778
+ this.destroy();
8413
8779
  new Promise((resolve) => {
8414
8780
  setTimeout(() => {
8415
8781
  resolve(true);
@@ -8443,8 +8809,7 @@ Error details:
8443
8809
  };
8444
8810
  process.on("uncaughtException", handleError);
8445
8811
  process.on("unhandledRejection", handleError);
8446
- process.on("exit", (code) => {
8447
- this.stop();
8812
+ process.on("exit", () => {
8448
8813
  this.destroy();
8449
8814
  });
8450
8815
  this._console = new TerminalConsole(this, config.consoleOptions);
@@ -8463,6 +8828,13 @@ Error details:
8463
8828
  }
8464
8829
  global.window.requestAnimationFrame = requestAnimationFrame;
8465
8830
  this.queryPixelResolution();
8831
+ if (process.env.OTUI_NO_NATIVE_RENDER === "true") {
8832
+ this.renderNative = () => {
8833
+ if (this._splitHeight > 0) {
8834
+ this.flushStdoutCache(this._splitHeight);
8835
+ }
8836
+ };
8837
+ }
8466
8838
  }
8467
8839
  writeOut(chunk, encoding, callback) {
8468
8840
  return this.realStdoutWrite.call(this.stdout, chunk, encoding, callback);
@@ -8521,6 +8893,12 @@ Error details:
8521
8893
  get experimental_splitHeight() {
8522
8894
  return this._splitHeight;
8523
8895
  }
8896
+ get liveRequestCount() {
8897
+ return this.liveRequestCounter;
8898
+ }
8899
+ get currentControlState() {
8900
+ return this.controlState;
8901
+ }
8524
8902
  set experimental_splitHeight(splitHeight) {
8525
8903
  if (splitHeight < 0)
8526
8904
  splitHeight = 0;
@@ -8594,30 +8972,17 @@ Error details:
8594
8972
  return true;
8595
8973
  }
8596
8974
  enableMouse() {
8597
- this.writeOut(ANSI.enableSGRMouseMode);
8598
- this.writeOut(ANSI.enableMouseTracking);
8599
- this.writeOut(ANSI.enableButtonEventTracking);
8600
- if (this.enableMouseMovement) {
8601
- this.writeOut(ANSI.enableAnyEventTracking);
8602
- }
8975
+ this.lib.enableMouse(this.rendererPtr, this.enableMouseMovement);
8603
8976
  }
8604
8977
  disableMouse() {
8605
- if (this.enableMouseMovement) {
8606
- this.writeOut(ANSI.disableAnyEventTracking);
8607
- }
8608
- this.writeOut(ANSI.disableButtonEventTracking);
8609
- this.writeOut(ANSI.disableMouseTracking);
8610
- this.writeOut(ANSI.disableSGRMouseMode);
8611
8978
  this.capturedRenderable = undefined;
8612
8979
  this.mouseParser.reset();
8980
+ this.lib.disableMouse(this.rendererPtr);
8613
8981
  }
8614
8982
  set useThread(useThread) {
8615
8983
  this._useThread = useThread;
8616
8984
  this.lib.setUseThread(this.rendererPtr, useThread);
8617
8985
  }
8618
- setTerminalSize(width, height) {
8619
- this.handleResize(width, height);
8620
- }
8621
8986
  setupTerminal() {
8622
8987
  this.writeOut(ANSI.saveCursorState);
8623
8988
  if (this.stdin.setRawMode) {
@@ -8644,7 +9009,7 @@ Error details:
8644
9009
  }
8645
9010
  if (this.exitOnCtrlC && str === "\x03") {
8646
9011
  process.nextTick(() => {
8647
- process.exit(0);
9012
+ process.exit();
8648
9013
  });
8649
9014
  return;
8650
9015
  }
@@ -8655,6 +9020,8 @@ Error details:
8655
9020
  });
8656
9021
  if (this._useAlternateScreen) {
8657
9022
  this.writeOut(ANSI.switchToAlternateScreen);
9023
+ } else {
9024
+ this.writeOut(ANSI.makeRoomForRenderer(this.height - 1));
8658
9025
  }
8659
9026
  this.setCursorPosition(0, 0, false);
8660
9027
  }
@@ -8720,6 +9087,7 @@ Error details:
8720
9087
  if (this.capturedRenderable && mouseEvent.type === "up") {
8721
9088
  const event = new MouseEvent(this.capturedRenderable, { ...mouseEvent, type: "drag-end" });
8722
9089
  this.capturedRenderable.processMouseEvent(event);
9090
+ this.capturedRenderable.processMouseEvent(new MouseEvent(this.capturedRenderable, mouseEvent));
8723
9091
  if (maybeRenderable) {
8724
9092
  const event2 = new MouseEvent(maybeRenderable, {
8725
9093
  ...mouseEvent,
@@ -8733,7 +9101,7 @@ Error details:
8733
9101
  this.capturedRenderable = undefined;
8734
9102
  }
8735
9103
  if (maybeRenderable) {
8736
- if (mouseEvent.type === "down" && mouseEvent.button === 0 /* LEFT */) {
9104
+ if (mouseEvent.type === "drag" && mouseEvent.button === 0 /* LEFT */) {
8737
9105
  this.capturedRenderable = maybeRenderable;
8738
9106
  } else {
8739
9107
  this.capturedRenderable = undefined;
@@ -8776,7 +9144,7 @@ Error details:
8776
9144
  }
8777
9145
  }
8778
9146
  handleResize(width, height) {
8779
- if (this.isShuttingDown)
9147
+ if (this.isDestroyed)
8780
9148
  return;
8781
9149
  if (this._splitHeight > 0) {
8782
9150
  this.processResize(width, height);
@@ -8900,7 +9268,25 @@ Error details:
8900
9268
  clearFrameCallbacks() {
8901
9269
  this.frameCallbacks = [];
8902
9270
  }
9271
+ requestLive() {
9272
+ this.liveRequestCounter++;
9273
+ if (this.controlState === "idle" /* IDLE */ && this.liveRequestCounter > 0) {
9274
+ this.controlState = "auto_started" /* AUTO_STARTED */;
9275
+ this.internalStart();
9276
+ }
9277
+ }
9278
+ dropLive() {
9279
+ this.liveRequestCounter = Math.max(0, this.liveRequestCounter - 1);
9280
+ if (this.controlState === "auto_started" /* AUTO_STARTED */ && this.liveRequestCounter === 0) {
9281
+ this.controlState = "idle" /* IDLE */;
9282
+ this.internalPause();
9283
+ }
9284
+ }
8903
9285
  start() {
9286
+ this.controlState = "explicit_started" /* EXPLICIT_STARTED */;
9287
+ this.internalStart();
9288
+ }
9289
+ internalStart() {
8904
9290
  if (!this._isRunning && !this.isDestroyed) {
8905
9291
  this._isRunning = true;
8906
9292
  if (this.memorySnapshotInterval > 0) {
@@ -8910,47 +9296,42 @@ Error details:
8910
9296
  }
8911
9297
  }
8912
9298
  pause() {
9299
+ this.controlState = "explicit_paused" /* EXPLICIT_PAUSED */;
9300
+ this.internalPause();
9301
+ }
9302
+ internalPause() {
8913
9303
  this._isRunning = false;
8914
9304
  }
8915
9305
  stop() {
8916
- if (this.isShuttingDown)
9306
+ this.controlState = "explicit_stopped" /* EXPLICIT_STOPPED */;
9307
+ this.internalStop();
9308
+ }
9309
+ internalStop() {
9310
+ if (this.isRunning && !this.isDestroyed) {
9311
+ this._isRunning = false;
9312
+ if (this.memorySnapshotTimer) {
9313
+ clearInterval(this.memorySnapshotTimer);
9314
+ this.memorySnapshotTimer = null;
9315
+ }
9316
+ if (this.renderTimeout) {
9317
+ clearTimeout(this.renderTimeout);
9318
+ this.renderTimeout = null;
9319
+ }
9320
+ }
9321
+ }
9322
+ destroy() {
9323
+ if (this.isDestroyed)
8917
9324
  return;
8918
- this._isRunning = false;
8919
- this.isShuttingDown = true;
9325
+ this.isDestroyed = true;
8920
9326
  this.waitingForPixelResolution = false;
9327
+ this.capturedRenderable = undefined;
8921
9328
  if (this.sigwinchHandler) {
8922
9329
  process.removeListener("SIGWINCH", this.sigwinchHandler);
8923
9330
  this.sigwinchHandler = null;
8924
9331
  }
8925
9332
  this._console.deactivate();
9333
+ this.lib.destroyRenderer(this.rendererPtr, this._useAlternateScreen, this._splitHeight);
8926
9334
  this.disableStdoutInterception();
8927
- if (this.renderTimeout) {
8928
- clearTimeout(this.renderTimeout);
8929
- this.renderTimeout = null;
8930
- }
8931
- if (this.memorySnapshotTimer) {
8932
- clearInterval(this.memorySnapshotTimer);
8933
- this.memorySnapshotTimer = null;
8934
- }
8935
- if (this._splitHeight > 0) {
8936
- const consoleEndLine = this._terminalHeight - this._splitHeight;
8937
- this.writeOut(ANSI.moveCursor(consoleEndLine, 1));
8938
- }
8939
- this.capturedRenderable = undefined;
8940
- if (this._useMouse) {
8941
- this.disableMouse();
8942
- }
8943
- this.writeOut(ANSI.resetCursorColor);
8944
- this.writeOut(ANSI.showCursor);
8945
- if (this._useAlternateScreen) {
8946
- this.writeOut(ANSI.switchToMainScreen);
8947
- }
8948
- }
8949
- destroy() {
8950
- if (this.isDestroyed)
8951
- return;
8952
- this.lib.destroyRenderer(this.rendererPtr);
8953
- this.isDestroyed = true;
8954
9335
  }
8955
9336
  startRenderLoop() {
8956
9337
  if (!this._isRunning)
@@ -8963,7 +9344,7 @@ Error details:
8963
9344
  this.loop();
8964
9345
  }
8965
9346
  async loop() {
8966
- if (this.rendering)
9347
+ if (this.rendering || this.isDestroyed)
8967
9348
  return;
8968
9349
  this.rendering = true;
8969
9350
  if (this.renderTimeout) {
@@ -9346,9 +9727,8 @@ class TextRenderable extends Renderable {
9346
9727
  constructor(id, options) {
9347
9728
  super(id, options);
9348
9729
  this.selectionHelper = new TextSelectionHelper(() => this.x, () => this.y, () => this._plainText.length, () => this._lineInfo);
9349
- if (options.content) {
9350
- this._text = typeof options.content === "string" ? stringToStyledText(options.content) : options.content;
9351
- }
9730
+ const content = options.content ?? "";
9731
+ this._text = typeof content === "string" ? stringToStyledText(content) : content;
9352
9732
  this._defaultFg = options.fg ? parseColor(options.fg) : RGBA.fromValues(1, 1, 1, 1);
9353
9733
  this._defaultBg = options.bg ? parseColor(options.bg) : RGBA.fromValues(0, 0, 0, 0);
9354
9734
  this._defaultAttributes = options.attributes ?? 0;
@@ -9359,8 +9739,8 @@ class TextRenderable extends Renderable {
9359
9739
  this.textBuffer.setDefaultFg(this._defaultFg);
9360
9740
  this.textBuffer.setDefaultBg(this._defaultBg);
9361
9741
  this.textBuffer.setDefaultAttributes(this._defaultAttributes);
9362
- this.updateTextInfo();
9363
9742
  this.setupMeasureFunc();
9743
+ this.updateTextInfo();
9364
9744
  }
9365
9745
  get content() {
9366
9746
  return this._text;
@@ -9405,9 +9785,9 @@ class TextRenderable extends Renderable {
9405
9785
  }
9406
9786
  }
9407
9787
  syncSelectionToTextBuffer() {
9408
- const selection = this.selectionHelper.getSelection();
9409
- if (selection) {
9410
- this.textBuffer.setSelection(selection.start, selection.end, this._selectionBg, this._selectionFg);
9788
+ const selection2 = this.selectionHelper.getSelection();
9789
+ if (selection2) {
9790
+ this.textBuffer.setSelection(selection2.start, selection2.end, this._selectionBg, this._selectionFg);
9411
9791
  } else {
9412
9792
  this.textBuffer.resetSelection();
9413
9793
  }
@@ -9419,49 +9799,49 @@ class TextRenderable extends Renderable {
9419
9799
  this._lineInfo.lineStarts = lineInfo.lineStarts;
9420
9800
  this._lineInfo.lineWidths = lineInfo.lineWidths;
9421
9801
  const numLines = this._lineInfo.lineStarts.length;
9422
- if (this._height === "auto") {
9423
- this.height = numLines;
9802
+ if (this._positionType === "absolute" && this._height === "auto") {
9803
+ this._heightValue = numLines;
9804
+ this.layoutNode.yogaNode.markDirty();
9424
9805
  }
9425
9806
  const maxLineWidth = Math.max(...this._lineInfo.lineWidths);
9426
9807
  if (this._positionType === "absolute" && this._width === "auto") {
9427
- this.width = maxLineWidth;
9808
+ this._widthValue = maxLineWidth;
9809
+ this.layoutNode.yogaNode.markDirty();
9428
9810
  }
9429
9811
  const changed = this.selectionHelper.reevaluateSelection(this.width, this.height);
9430
9812
  if (changed) {
9431
9813
  this.syncSelectionToTextBuffer();
9432
- this.needsUpdate();
9433
9814
  }
9815
+ this.needsUpdate();
9434
9816
  }
9435
9817
  setupMeasureFunc() {
9436
- if (this._positionType === "relative" && this._width === "auto") {
9437
- const measureFunc = (width, widthMode, height, heightMode) => {
9438
- const maxLineWidth = Math.max(...this._lineInfo.lineWidths, 0);
9439
- const numLines = this._lineInfo.lineStarts.length || 1;
9440
- let measuredWidth = maxLineWidth;
9441
- let measuredHeight = numLines;
9442
- if (widthMode === MeasureMode.Exactly) {
9443
- measuredWidth = width;
9444
- } else if (widthMode === MeasureMode.AtMost) {
9445
- measuredWidth = Math.min(maxLineWidth, width);
9446
- }
9447
- if (heightMode === MeasureMode.Exactly) {
9448
- measuredHeight = height;
9449
- } else if (heightMode === MeasureMode.AtMost) {
9450
- measuredHeight = Math.min(numLines, height);
9451
- }
9452
- return {
9453
- width: Math.max(1, measuredWidth),
9454
- height: Math.max(1, measuredHeight)
9455
- };
9818
+ const measureFunc = (width, widthMode, height, heightMode) => {
9819
+ const maxLineWidth = Math.max(...this._lineInfo.lineWidths, 0);
9820
+ const numLines = this._lineInfo.lineStarts.length || 1;
9821
+ let measuredWidth = maxLineWidth;
9822
+ let measuredHeight = numLines;
9823
+ if (widthMode === MeasureMode.Exactly) {
9824
+ measuredWidth = width;
9825
+ } else if (widthMode === MeasureMode.AtMost) {
9826
+ measuredWidth = Math.min(maxLineWidth, width);
9827
+ }
9828
+ if (heightMode === MeasureMode.Exactly) {
9829
+ measuredHeight = height;
9830
+ } else if (heightMode === MeasureMode.AtMost) {
9831
+ measuredHeight = Math.min(numLines, height);
9832
+ }
9833
+ return {
9834
+ width: Math.max(1, measuredWidth),
9835
+ height: Math.max(1, measuredHeight)
9456
9836
  };
9457
- this.layoutNode.yogaNode.setMeasureFunc(measureFunc);
9458
- }
9837
+ };
9838
+ this.layoutNode.yogaNode.setMeasureFunc(measureFunc);
9459
9839
  }
9460
9840
  shouldStartSelection(x, y) {
9461
9841
  return this.selectionHelper.shouldStartSelection(x, y, this.width, this.height);
9462
9842
  }
9463
- onSelectionChanged(selection) {
9464
- const changed = this.selectionHelper.onSelectionChanged(selection, this.width, this.height);
9843
+ onSelectionChanged(selection2) {
9844
+ const changed = this.selectionHelper.onSelectionChanged(selection2, this.width, this.height);
9465
9845
  if (changed) {
9466
9846
  this.syncSelectionToTextBuffer();
9467
9847
  this.needsUpdate();
@@ -9469,10 +9849,10 @@ class TextRenderable extends Renderable {
9469
9849
  return this.selectionHelper.hasSelection();
9470
9850
  }
9471
9851
  getSelectedText() {
9472
- const selection = this.selectionHelper.getSelection();
9473
- if (!selection)
9852
+ const selection2 = this.selectionHelper.getSelection();
9853
+ if (!selection2)
9474
9854
  return "";
9475
- return this._plainText.slice(selection.start, selection.end);
9855
+ return this._plainText.slice(selection2.start, selection2.end);
9476
9856
  }
9477
9857
  hasSelection() {
9478
9858
  return this.selectionHelper.hasSelection();
@@ -9574,8 +9954,8 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
9574
9954
  shouldStartSelection(x, y) {
9575
9955
  return this.selectionHelper.shouldStartSelection(x, y, this.width, this.height);
9576
9956
  }
9577
- onSelectionChanged(selection) {
9578
- const changed = this.selectionHelper.onSelectionChanged(selection, this.width, this.height);
9957
+ onSelectionChanged(selection2) {
9958
+ const changed = this.selectionHelper.onSelectionChanged(selection2, this.width, this.height);
9579
9959
  if (changed) {
9580
9960
  this.renderFontToBuffer();
9581
9961
  this.needsUpdate();
@@ -9583,10 +9963,10 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
9583
9963
  return this.selectionHelper.hasSelection();
9584
9964
  }
9585
9965
  getSelectedText() {
9586
- const selection = this.selectionHelper.getSelection();
9587
- if (!selection)
9966
+ const selection2 = this.selectionHelper.getSelection();
9967
+ if (!selection2)
9588
9968
  return "";
9589
- return this._text.slice(selection.start, selection.end);
9969
+ return this._text.slice(selection2.start, selection2.end);
9590
9970
  }
9591
9971
  hasSelection() {
9592
9972
  return this.selectionHelper.hasSelection();
@@ -9605,20 +9985,20 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
9605
9985
  bg: this._bg,
9606
9986
  font: this._font
9607
9987
  });
9608
- const selection = this.selectionHelper.getSelection();
9609
- if (selection && (this._selectionBg || this._selectionFg)) {
9610
- this.renderSelectionHighlight(selection);
9988
+ const selection2 = this.selectionHelper.getSelection();
9989
+ if (selection2 && (this._selectionBg || this._selectionFg)) {
9990
+ this.renderSelectionHighlight(selection2);
9611
9991
  }
9612
9992
  }
9613
- renderSelectionHighlight(selection) {
9993
+ renderSelectionHighlight(selection2) {
9614
9994
  if (!this._selectionBg && !this._selectionFg)
9615
9995
  return;
9616
- const selectedText = this._text.slice(selection.start, selection.end);
9996
+ const selectedText = this._text.slice(selection2.start, selection2.end);
9617
9997
  if (!selectedText)
9618
9998
  return;
9619
9999
  const positions = getCharacterPositions(this._text, this._font);
9620
- const startX = positions[selection.start] || 0;
9621
- const endX = selection.end < positions.length ? positions[selection.end] : measureText({ text: this._text, font: this._font }).width;
10000
+ const startX = positions[selection2.start] || 0;
10001
+ const endX = selection2.end < positions.length ? positions[selection2.end] : measureText({ text: this._text, font: this._font }).width;
9622
10002
  if (this._selectionBg) {
9623
10003
  this.frameBuffer.fillRect(startX, 0, endX - startX, this.height, this._selectionBg);
9624
10004
  }
@@ -10421,13 +10801,29 @@ export {
10421
10801
  resolveRenderLib,
10422
10802
  renderFontToFrameBuffer,
10423
10803
  red,
10804
+ parseWrap,
10805
+ parseUnit,
10806
+ parsePositionType,
10807
+ parseOverflow,
10808
+ parseMeasureMode,
10809
+ parseLogLevel,
10424
10810
  parseKeypress,
10811
+ parseJustify,
10812
+ parseGutter,
10813
+ parseFlexDirection,
10814
+ parseEdge,
10815
+ parseDisplay,
10816
+ parseDirection,
10817
+ parseDimension,
10425
10818
  parseColor,
10819
+ parseBoxSizing,
10820
+ parseAlign,
10426
10821
  nonAlphanumericKeys,
10427
10822
  measureText,
10428
10823
  magenta,
10429
10824
  italic,
10430
10825
  isSizeType,
10826
+ isPostionTypeType,
10431
10827
  isPositionType,
10432
10828
  isPaddingType,
10433
10829
  isMarginType,
@@ -10501,6 +10897,7 @@ export {
10501
10897
  Renderable,
10502
10898
  RGBA,
10503
10899
  OptimizedBuffer,
10900
+ MouseParser,
10504
10901
  MouseEvent,
10505
10902
  MouseButton,
10506
10903
  LayoutEvents,
@@ -10523,3 +10920,6 @@ export {
10523
10920
  ASCIIFontSelectionHelper,
10524
10921
  ASCIIFontRenderable
10525
10922
  };
10923
+ export { __toESM, __commonJS, __export, __require };
10924
+ //# debugId=D2D08A0277CDE28864756E2164756E21
10925
+ //# sourceMappingURL=index.js.map