@opentui/core 0.1.79 → 0.1.80

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.d.ts CHANGED
@@ -11,6 +11,7 @@ export * from "./post/filters";
11
11
  export * from "./animation/Timeline";
12
12
  export * from "./lib";
13
13
  export * from "./renderer";
14
+ export * from "./NativeSpanFeed";
14
15
  export * from "./renderables";
15
16
  export * from "./zig";
16
17
  export * from "./console";
package/index.js CHANGED
@@ -33,6 +33,7 @@ import {
33
33
  RendererControlState,
34
34
  RootRenderable,
35
35
  Selection,
36
+ SpanInfoStruct,
36
37
  StdinBuffer,
37
38
  StyledText,
38
39
  TerminalConsole,
@@ -152,7 +153,7 @@ import {
152
153
  white,
153
154
  wrapWithDelegates,
154
155
  yellow
155
- } from "./index-zrvzvh6r.js";
156
+ } from "./index-vnvba6q9.js";
156
157
  // src/text-buffer-view.ts
157
158
  class TextBufferView {
158
159
  lib;
@@ -2064,6 +2065,266 @@ function createTimeline(options = {}) {
2064
2065
  engine.register(timeline);
2065
2066
  return timeline;
2066
2067
  }
2068
+ // src/NativeSpanFeed.ts
2069
+ import { toArrayBuffer } from "bun:ffi";
2070
+ function toPointer(value) {
2071
+ if (typeof value === "bigint") {
2072
+ if (value > BigInt(Number.MAX_SAFE_INTEGER)) {
2073
+ throw new Error("Pointer exceeds safe integer range");
2074
+ }
2075
+ return Number(value);
2076
+ }
2077
+ return value;
2078
+ }
2079
+ function toNumber(value) {
2080
+ return typeof value === "bigint" ? Number(value) : value;
2081
+ }
2082
+
2083
+ class NativeSpanFeed {
2084
+ static create(options) {
2085
+ const lib = resolveRenderLib();
2086
+ const streamPtr = lib.createNativeSpanFeed(options);
2087
+ const stream = new NativeSpanFeed(streamPtr);
2088
+ lib.registerNativeSpanFeedStream(streamPtr, stream.eventHandler);
2089
+ const status = lib.attachNativeSpanFeed(streamPtr);
2090
+ if (status !== 0) {
2091
+ lib.unregisterNativeSpanFeedStream(streamPtr);
2092
+ lib.destroyNativeSpanFeed(streamPtr);
2093
+ throw new Error(`Failed to attach stream: ${status}`);
2094
+ }
2095
+ return stream;
2096
+ }
2097
+ static attach(streamPtr, _options) {
2098
+ const lib = resolveRenderLib();
2099
+ const ptr = toPointer(streamPtr);
2100
+ const stream = new NativeSpanFeed(ptr);
2101
+ lib.registerNativeSpanFeedStream(ptr, stream.eventHandler);
2102
+ const status = lib.attachNativeSpanFeed(ptr);
2103
+ if (status !== 0) {
2104
+ lib.unregisterNativeSpanFeedStream(ptr);
2105
+ throw new Error(`Failed to attach stream: ${status}`);
2106
+ }
2107
+ return stream;
2108
+ }
2109
+ streamPtr;
2110
+ lib = resolveRenderLib();
2111
+ eventHandler;
2112
+ chunkMap = new Map;
2113
+ chunkSizes = new Map;
2114
+ dataHandlers = new Set;
2115
+ errorHandlers = new Set;
2116
+ drainBuffer = null;
2117
+ stateBuffer = null;
2118
+ closed = false;
2119
+ destroyed = false;
2120
+ draining = false;
2121
+ pendingDataAvailable = false;
2122
+ pendingClose = false;
2123
+ closing = false;
2124
+ pendingAsyncHandlers = 0;
2125
+ inCallback = false;
2126
+ closeQueued = false;
2127
+ constructor(streamPtr) {
2128
+ this.streamPtr = streamPtr;
2129
+ this.eventHandler = (eventId, arg0, arg1) => {
2130
+ this.handleEvent(eventId, arg0, arg1);
2131
+ };
2132
+ this.ensureDrainBuffer();
2133
+ }
2134
+ ensureDrainBuffer() {
2135
+ if (this.drainBuffer)
2136
+ return;
2137
+ const capacity = 256;
2138
+ this.drainBuffer = new Uint8Array(capacity * SpanInfoStruct.size);
2139
+ }
2140
+ onData(handler) {
2141
+ this.dataHandlers.add(handler);
2142
+ if (this.pendingDataAvailable) {
2143
+ this.pendingDataAvailable = false;
2144
+ this.drainAll();
2145
+ }
2146
+ return () => this.dataHandlers.delete(handler);
2147
+ }
2148
+ onError(handler) {
2149
+ this.errorHandlers.add(handler);
2150
+ return () => this.errorHandlers.delete(handler);
2151
+ }
2152
+ close() {
2153
+ if (this.destroyed)
2154
+ return;
2155
+ if (this.inCallback || this.draining || this.pendingAsyncHandlers > 0) {
2156
+ this.pendingClose = true;
2157
+ if (!this.closeQueued) {
2158
+ this.closeQueued = true;
2159
+ queueMicrotask(() => {
2160
+ this.closeQueued = false;
2161
+ this.processPendingClose();
2162
+ });
2163
+ }
2164
+ return;
2165
+ }
2166
+ this.performClose();
2167
+ }
2168
+ processPendingClose() {
2169
+ if (!this.pendingClose || this.destroyed)
2170
+ return;
2171
+ if (this.inCallback || this.draining || this.pendingAsyncHandlers > 0)
2172
+ return;
2173
+ this.pendingClose = false;
2174
+ this.performClose();
2175
+ }
2176
+ performClose() {
2177
+ if (this.closing)
2178
+ return;
2179
+ this.closing = true;
2180
+ if (!this.closed) {
2181
+ const status = this.lib.streamClose(this.streamPtr);
2182
+ if (status !== 0) {
2183
+ this.closing = false;
2184
+ return;
2185
+ }
2186
+ this.closed = true;
2187
+ }
2188
+ this.finalizeDestroy();
2189
+ }
2190
+ finalizeDestroy() {
2191
+ if (this.destroyed)
2192
+ return;
2193
+ this.lib.unregisterNativeSpanFeedStream(this.streamPtr);
2194
+ this.lib.destroyNativeSpanFeed(this.streamPtr);
2195
+ this.destroyed = true;
2196
+ this.chunkMap.clear();
2197
+ this.chunkSizes.clear();
2198
+ this.stateBuffer = null;
2199
+ this.drainBuffer = null;
2200
+ this.dataHandlers.clear();
2201
+ this.errorHandlers.clear();
2202
+ this.pendingDataAvailable = false;
2203
+ }
2204
+ handleEvent(eventId, arg0, arg1) {
2205
+ this.inCallback = true;
2206
+ try {
2207
+ switch (eventId) {
2208
+ case 8 /* StateBuffer */: {
2209
+ const len = toNumber(arg1);
2210
+ if (len > 0 && arg0) {
2211
+ const buffer = toArrayBuffer(arg0, 0, len);
2212
+ this.stateBuffer = new Uint8Array(buffer);
2213
+ }
2214
+ break;
2215
+ }
2216
+ case 7 /* DataAvailable */: {
2217
+ if (this.closing)
2218
+ break;
2219
+ if (this.dataHandlers.size === 0) {
2220
+ this.pendingDataAvailable = true;
2221
+ break;
2222
+ }
2223
+ this.drainAll();
2224
+ break;
2225
+ }
2226
+ case 2 /* ChunkAdded */: {
2227
+ const chunkLen = toNumber(arg1);
2228
+ if (chunkLen > 0 && arg0) {
2229
+ if (!this.chunkMap.has(arg0)) {
2230
+ const buffer = toArrayBuffer(arg0, 0, chunkLen);
2231
+ this.chunkMap.set(arg0, buffer);
2232
+ }
2233
+ this.chunkSizes.set(arg0, chunkLen);
2234
+ }
2235
+ break;
2236
+ }
2237
+ case 6 /* Error */: {
2238
+ const code = arg0;
2239
+ for (const handler of this.errorHandlers)
2240
+ handler(code);
2241
+ break;
2242
+ }
2243
+ case 5 /* Closed */: {
2244
+ this.closed = true;
2245
+ break;
2246
+ }
2247
+ default:
2248
+ break;
2249
+ }
2250
+ } finally {
2251
+ this.inCallback = false;
2252
+ }
2253
+ }
2254
+ decrementRefcount(chunkIndex) {
2255
+ if (this.stateBuffer && chunkIndex < this.stateBuffer.length) {
2256
+ const prev = this.stateBuffer[chunkIndex];
2257
+ this.stateBuffer[chunkIndex] = prev > 0 ? prev - 1 : 0;
2258
+ }
2259
+ }
2260
+ drainOnce() {
2261
+ if (!this.drainBuffer || this.draining || this.pendingClose)
2262
+ return 0;
2263
+ const capacity = Math.floor(this.drainBuffer.byteLength / SpanInfoStruct.size);
2264
+ if (capacity === 0)
2265
+ return 0;
2266
+ const count = this.lib.streamDrainSpans(this.streamPtr, this.drainBuffer, capacity);
2267
+ if (count === 0)
2268
+ return 0;
2269
+ this.draining = true;
2270
+ const spans = SpanInfoStruct.unpackList(this.drainBuffer.buffer, count);
2271
+ let firstError = null;
2272
+ try {
2273
+ for (const span of spans) {
2274
+ if (span.len === 0)
2275
+ continue;
2276
+ let buffer = this.chunkMap.get(span.chunkPtr);
2277
+ if (!buffer) {
2278
+ const size = this.chunkSizes.get(span.chunkPtr);
2279
+ if (!size)
2280
+ continue;
2281
+ buffer = toArrayBuffer(span.chunkPtr, 0, size);
2282
+ this.chunkMap.set(span.chunkPtr, buffer);
2283
+ }
2284
+ if (span.offset + span.len > buffer.byteLength)
2285
+ continue;
2286
+ const slice = new Uint8Array(buffer, span.offset, span.len);
2287
+ let asyncResults = null;
2288
+ for (const handler of this.dataHandlers) {
2289
+ try {
2290
+ const result = handler(slice);
2291
+ if (result && typeof result.then === "function") {
2292
+ asyncResults ??= [];
2293
+ asyncResults.push(result);
2294
+ }
2295
+ } catch (e) {
2296
+ firstError ??= e;
2297
+ }
2298
+ }
2299
+ const shouldStopAfterThisSpan = this.pendingClose;
2300
+ if (asyncResults) {
2301
+ const chunkIndex = span.chunkIndex;
2302
+ this.pendingAsyncHandlers += 1;
2303
+ Promise.allSettled(asyncResults).then(() => {
2304
+ this.decrementRefcount(chunkIndex);
2305
+ this.pendingAsyncHandlers -= 1;
2306
+ this.processPendingClose();
2307
+ });
2308
+ } else {
2309
+ this.decrementRefcount(span.chunkIndex);
2310
+ }
2311
+ if (shouldStopAfterThisSpan)
2312
+ break;
2313
+ }
2314
+ } finally {
2315
+ this.draining = false;
2316
+ }
2317
+ if (firstError)
2318
+ throw firstError;
2319
+ return count;
2320
+ }
2321
+ drainAll() {
2322
+ let count = this.drainOnce();
2323
+ while (count > 0) {
2324
+ count = this.drainOnce();
2325
+ }
2326
+ }
2327
+ }
2067
2328
  // src/renderables/FrameBuffer.ts
2068
2329
  class FrameBufferRenderable extends Renderable {
2069
2330
  frameBuffer;
@@ -3856,6 +4117,23 @@ class LineNumberRenderable extends Renderable {
3856
4117
  getLineNumbers() {
3857
4118
  return this._lineNumbers;
3858
4119
  }
4120
+ highlightLines(startLine, endLine, color) {
4121
+ for (let i = startLine;i <= endLine; i++) {
4122
+ this.parseLineColor(i, color);
4123
+ }
4124
+ if (this.gutter) {
4125
+ this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent);
4126
+ }
4127
+ }
4128
+ clearHighlightLines(startLine, endLine) {
4129
+ for (let i = startLine;i <= endLine; i++) {
4130
+ this._lineColorsGutter.delete(i);
4131
+ this._lineColorsContent.delete(i);
4132
+ }
4133
+ if (this.gutter) {
4134
+ this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent);
4135
+ }
4136
+ }
3859
4137
  }
3860
4138
 
3861
4139
  // ../../node_modules/.bun/diff@8.0.2/node_modules/diff/libesm/diff/base.js
@@ -5580,6 +5858,30 @@ class DiffRenderable extends Renderable {
5580
5858
  }
5581
5859
  }
5582
5860
  }
5861
+ setLineColor(line, color) {
5862
+ this.leftSide?.setLineColor(line, color);
5863
+ this.rightSide?.setLineColor(line, color);
5864
+ }
5865
+ clearLineColor(line) {
5866
+ this.leftSide?.clearLineColor(line);
5867
+ this.rightSide?.clearLineColor(line);
5868
+ }
5869
+ setLineColors(lineColors) {
5870
+ this.leftSide?.setLineColors(lineColors);
5871
+ this.rightSide?.setLineColors(lineColors);
5872
+ }
5873
+ clearAllLineColors() {
5874
+ this.leftSide?.clearAllLineColors();
5875
+ this.rightSide?.clearAllLineColors();
5876
+ }
5877
+ highlightLines(startLine, endLine, color) {
5878
+ this.leftSide?.highlightLines(startLine, endLine, color);
5879
+ this.rightSide?.highlightLines(startLine, endLine, color);
5880
+ }
5881
+ clearHighlightLines(startLine, endLine) {
5882
+ this.leftSide?.clearHighlightLines(startLine, endLine);
5883
+ this.rightSide?.clearHighlightLines(startLine, endLine);
5884
+ }
5583
5885
  }
5584
5886
  // src/renderables/EditBufferRenderable.ts
5585
5887
  class EditBufferRenderable extends Renderable {
@@ -6011,13 +6313,11 @@ class EditBufferRenderable extends Renderable {
6011
6313
  const cursorX = this.x + visualCursor.visualCol + 1;
6012
6314
  const cursorY = this.y + visualCursor.visualRow + 1;
6013
6315
  this._ctx.setCursorPosition(cursorX, cursorY, true);
6014
- this._ctx.setCursorColor(this._cursorColor);
6015
- this._ctx.setCursorStyle(this._cursorStyle.style, this._cursorStyle.blinking);
6316
+ this._ctx.setCursorStyle({ ...this._cursorStyle, color: this._cursorColor });
6016
6317
  }
6017
6318
  focus() {
6018
6319
  super.focus();
6019
- this._ctx.setCursorStyle(this._cursorStyle.style, this._cursorStyle.blinking);
6020
- this._ctx.setCursorColor(this._cursorColor);
6320
+ this._ctx.setCursorStyle({ ...this._cursorStyle, color: this._cursorColor });
6021
6321
  this.requestRender();
6022
6322
  }
6023
6323
  blur() {
@@ -8181,7 +8481,8 @@ class MarkdownRenderable extends Renderable {
8181
8481
  constructor(ctx, options) {
8182
8482
  super(ctx, {
8183
8483
  ...options,
8184
- flexDirection: "column"
8484
+ flexDirection: "column",
8485
+ flexShrink: options.flexShrink ?? 0
8185
8486
  });
8186
8487
  this._syntaxStyle = options.syntaxStyle;
8187
8488
  this._conceal = options.conceal ?? this._contentDefaultOptions.conceal;
@@ -8225,8 +8526,7 @@ class MarkdownRenderable extends Renderable {
8225
8526
  set streaming(value) {
8226
8527
  if (this._streaming !== value) {
8227
8528
  this._streaming = value;
8228
- this.updateBlocks();
8229
- this.requestRender();
8529
+ this.clearCache();
8230
8530
  }
8231
8531
  }
8232
8532
  getStyle(group) {
@@ -10851,6 +11151,7 @@ export {
10851
11151
  RGBA,
10852
11152
  PasteEvent,
10853
11153
  OptimizedBuffer,
11154
+ NativeSpanFeed,
10854
11155
  MouseParser,
10855
11156
  MouseEvent,
10856
11157
  MouseButton,
@@ -10897,5 +11198,5 @@ export {
10897
11198
  ASCIIFont
10898
11199
  };
10899
11200
 
10900
- //# debugId=20BF116F533C5D6664756E2164756E21
11201
+ //# debugId=3CB381A14248B1EF64756E2164756E21
10901
11202
  //# sourceMappingURL=index.js.map