@opentui/core 0.5.7 → 0.5.9

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/README.md CHANGED
@@ -1,63 +1,70 @@
1
- # OpenTUI Core
1
+ <!-- Keep the project introduction aligned with the repository README and opentui.com. -->
2
2
 
3
- OpenTUI is a native terminal UI core written in Zig with TypeScript bindings. The native core exposes a C ABI and can be used from any language. OpenTUI powers OpenCode in production today and will also power terminal.shop. It is an extensible core with a focus on correctness, stability, and high performance. It provides a component-based architecture with flexible layout capabilities, allowing you to create complex terminal applications.
3
+ <p align="center">
4
+ <a href="https://opentui.com">
5
+ <img alt="OpenTUI logo" src="https://opentui.com/opentui-logo-auto.svg" width="270" />
6
+ </a>
7
+ </p>
4
8
 
5
- ## Documentation
9
+ <div align="center">
10
+ <a href="https://www.npmjs.com/package/@opentui/core"><img alt="npm version" src="https://img.shields.io/npm/v/@opentui/core?style=flat-square" /></a>
11
+ <a href="https://github.com/anomalyco/opentui/actions/workflows/build-core.yml"><img alt="Core build status" src="https://img.shields.io/github/actions/workflow/status/anomalyco/opentui/build-core.yml?style=flat-square&branch=main" /></a>
12
+ </div>
6
13
 
7
- - [Getting Started](https://opentui.com/docs/getting-started) - API and usage guide
8
- - [Development Guide](docs/development.md) - Building, testing, and contributing
9
- - [Tree-Sitter](https://opentui.com/docs/reference/tree-sitter) - Syntax highlighting integration
10
- - [Renderables](https://opentui.com/docs/core-concepts/renderables) - Understanding the component model
11
- - [Environment Variables](https://opentui.com/docs/reference/env-vars) - Configuration options
14
+ OpenTUI is a library to build terminal user interfaces.
12
15
 
13
- ## Install
16
+ - It is written in Zig.
17
+ - You write TypeScript directly or through React and Solid.
18
+ - You arrange boxes and text with flexbox.
19
+ - You add selects, inputs, and scroll boxes with keyboard and mouse controls.
20
+ - You can play sounds, show images, and render 3D graphics.
14
21
 
15
- ```bash
16
- bun install @opentui/core
17
- ```
22
+ OpenCode uses OpenTUI in production for millions of users.
18
23
 
19
- ## Build
24
+ [Website](https://opentui.com) | [Documentation](https://opentui.com/docs) | [Packages](https://opentui.com/packages)
20
25
 
21
- ```bash
22
- bun run build
23
- ```
26
+ ## OpenTUI Core
24
27
 
25
- This creates platform-specific libraries that are automatically loaded by the TypeScript layer.
28
+ `@opentui/core` supplies the renderer and TypeScript API. You use imperative renderables and events directly. The
29
+ TypeScript packages call native Zig through an internal foreign function interface (FFI) boundary.
26
30
 
27
- ## Examples
31
+ ```typescript
32
+ import { TextRenderable, createCliRenderer } from "@opentui/core"
28
33
 
29
- ```bash
30
- bun install
31
- cd ../examples
32
- bun run dev
34
+ const renderer = await createCliRenderer({ exitOnCtrlC: true })
35
+
36
+ renderer.root.add(new TextRenderable(renderer, { content: "Hello, OpenTUI!" }))
33
37
  ```
34
38
 
35
- ## Benchmarks
39
+ `exitOnCtrlC: true` calls `renderer.destroy()` when the user presses Ctrl+C. The code that creates the renderer must
40
+ call `renderer.destroy()` on every other shutdown path.
36
41
 
37
- Run native performance benchmarks:
42
+ Install the package:
38
43
 
39
44
  ```bash
40
- bun run bench:native
45
+ bun add @opentui/core
41
46
  ```
42
47
 
43
- See [the native benchmark runner](../native/src/bench.zig) for options such as `--filter` and `--mem`.
48
+ Then build your first app with the [quickstart](https://opentui.com/docs/getting-started/quickstart).
44
49
 
45
- NativeSpanFeed TypeScript benchmarks:
50
+ ## Runtime and platform support
46
51
 
47
- - [src/benchmark/native-span-feed-benchmark.md](src/benchmark/native-span-feed-benchmark.md)
52
+ `@opentui/core` runs on Bun 1.3.0 or later, or on Node.js 26.4.0 or later with ECMAScript modules (ESM) and
53
+ `--experimental-ffi`.
48
54
 
49
- ## CLI Renderer
55
+ The native ABI and the generated platform packages, such as `@opentui/core-linux-x64`, are internal distribution
56
+ surfaces, not application APIs.
50
57
 
51
- ### Renderables
58
+ ## AI agent skill
52
59
 
53
- Renderables are hierarchical objects that can be positioned, nested, styled and rendered to the terminal:
60
+ Install the OpenTUI documentation as a skill for your AI coding assistant with [`npx skills`](https://skills.sh):
54
61
 
55
- ```typescript
56
- import { createCliRenderer, TextRenderable } from "@opentui/core"
62
+ ```bash
63
+ npx skills add anomalyco/opentui --skill opentui
64
+ ```
57
65
 
58
- const renderer = await createCliRenderer()
66
+ Add `-g` to install the skill globally.
59
67
 
60
- const obj = new TextRenderable(renderer, { id: "my-obj", content: "Hello, world!" })
68
+ ## License
61
69
 
62
- renderer.root.add(obj)
63
- ```
70
+ OpenTUI is licensed under the [MIT License](https://github.com/anomalyco/opentui/blob/main/LICENSE).
@@ -5965,7 +5965,7 @@ class MouseParser {
5965
5965
  if (type === "down" && button !== 3) {
5966
5966
  this.mouseButtonsPressed.add(button);
5967
5967
  } else if (type === "up") {
5968
- this.mouseButtonsPressed.clear();
5968
+ this.mouseButtonsPressed.delete(button);
5969
5969
  }
5970
5970
  }
5971
5971
  return {
@@ -11576,7 +11576,6 @@ class TextBuffer {
11576
11576
  bufferPtr;
11577
11577
  _length = 0;
11578
11578
  _byteSize = 0;
11579
- _lineInfo;
11580
11579
  _destroyed = false;
11581
11580
  _syntaxStyle;
11582
11581
  _textBytes;
@@ -11605,7 +11604,6 @@ class TextBuffer {
11605
11604
  this.lib.textBufferSetTextFromMem(this.bufferPtr, this._memId);
11606
11605
  this._length = this.lib.textBufferGetLength(this.bufferPtr);
11607
11606
  this._byteSize = this.lib.textBufferGetByteSize(this.bufferPtr);
11608
- this._lineInfo = undefined;
11609
11607
  this._appendedChunks = [];
11610
11608
  }
11611
11609
  append(text) {
@@ -11615,7 +11613,6 @@ class TextBuffer {
11615
11613
  this.lib.textBufferAppend(this.bufferPtr, textBytes);
11616
11614
  this._length = this.lib.textBufferGetLength(this.bufferPtr);
11617
11615
  this._byteSize = this.lib.textBufferGetByteSize(this.bufferPtr);
11618
- this._lineInfo = undefined;
11619
11616
  }
11620
11617
  loadFile(path3) {
11621
11618
  this.guard();
@@ -11625,7 +11622,6 @@ class TextBuffer {
11625
11622
  }
11626
11623
  this._length = this.lib.textBufferGetLength(this.bufferPtr);
11627
11624
  this._byteSize = this.lib.textBufferGetByteSize(this.bufferPtr);
11628
- this._lineInfo = undefined;
11629
11625
  this._textBytes = undefined;
11630
11626
  }
11631
11627
  setStyledText(text) {
@@ -11633,7 +11629,6 @@ class TextBuffer {
11633
11629
  this.lib.textBufferSetStyledText(this.bufferPtr, text.chunks);
11634
11630
  this._length = this.lib.textBufferGetLength(this.bufferPtr);
11635
11631
  this._byteSize = this.lib.textBufferGetByteSize(this.bufferPtr);
11636
- this._lineInfo = undefined;
11637
11632
  }
11638
11633
  setDefaultFg(fg2) {
11639
11634
  this.guard();
@@ -11728,6 +11723,7 @@ class TextBuffer {
11728
11723
  setTabWidth(width) {
11729
11724
  this.guard();
11730
11725
  this.lib.textBufferSetTabWidth(this.bufferPtr, width);
11726
+ this._length = this.lib.textBufferGetLength(this.bufferPtr);
11731
11727
  }
11732
11728
  getTabWidth() {
11733
11729
  this.guard();
@@ -11738,7 +11734,6 @@ class TextBuffer {
11738
11734
  this.lib.textBufferClear(this.bufferPtr);
11739
11735
  this._length = 0;
11740
11736
  this._byteSize = 0;
11741
- this._lineInfo = undefined;
11742
11737
  this._textBytes = undefined;
11743
11738
  this._appendedChunks = [];
11744
11739
  }
@@ -11747,7 +11742,6 @@ class TextBuffer {
11747
11742
  this.lib.textBufferReset(this.bufferPtr);
11748
11743
  this._length = 0;
11749
11744
  this._byteSize = 0;
11750
- this._lineInfo = undefined;
11751
11745
  this._textBytes = undefined;
11752
11746
  this._memId = undefined;
11753
11747
  this._appendedChunks = [];
@@ -13120,7 +13114,7 @@ var VisualCursorStruct = defineStruct([
13120
13114
  ["logicalCol", "u32"],
13121
13115
  ["offset", "u32"]
13122
13116
  ]);
13123
- var UnicodeMethodEnum = defineEnum({ wcwidth: 0, unicode: 1 }, "u8");
13117
+ var UnicodeMethodEnum = defineEnum({ wcwidth: 0, unicode: 1, "unicode-wide": 3 }, "u8");
13124
13118
  var TerminalMultiplexerEnum = defineEnum({ none: 0, tmux: 1, zellij: 2, screen: 3, unknown: 4 }, "u8");
13125
13119
  var Osc52SupportEnum = defineEnum({ unknown: 0, supported: 1, unsupported: 2 }, "u8");
13126
13120
  var ImageProtocolEnum = defineEnum({ auto: 0, kitty: 1, sixel: 2, blocks: 3 }, "u8");
@@ -13594,6 +13588,14 @@ function selectionBehaviorByte(behavior) {
13594
13588
  function editorLocalSelectionFlags(updateCursor, followCursor, behavior) {
13595
13589
  return ffiBool(updateCursor) | ffiBool(followCursor) << 1 | selectionBehaviorByte(behavior) << 2;
13596
13590
  }
13591
+ function widthMethodCode(widthMethod) {
13592
+ return widthMethod === "wcwidth" ? 0 : widthMethod === "unicode-wide" ? 3 : 1;
13593
+ }
13594
+ function widthMethodFromCode(code) {
13595
+ if (code === 0)
13596
+ return "wcwidth";
13597
+ return code === 3 ? "unicode-wide" : "unicode";
13598
+ }
13597
13599
  function getOpenTUILib(libPath) {
13598
13600
  const resolvedLibPath = libPath || targetLibPath;
13599
13601
  if (!resolvedLibPath) {
@@ -13804,6 +13806,10 @@ function getOpenTUILib(libPath) {
13804
13806
  args: ["u32"],
13805
13807
  returns: "u32"
13806
13808
  },
13809
+ getBufferWidthMethod: {
13810
+ args: ["u32"],
13811
+ returns: "u8"
13812
+ },
13807
13813
  bufferClear: {
13808
13814
  args: ["u32", "buffer"],
13809
13815
  returns: "void"
@@ -14421,7 +14427,7 @@ function getOpenTUILib(libPath) {
14421
14427
  },
14422
14428
  editorViewGetViewport: {
14423
14429
  args: ["u32", "buffer", "buffer", "buffer", "buffer"],
14424
- returns: "void"
14430
+ returns: "bool"
14425
14431
  },
14426
14432
  editorViewSetScrollMargin: {
14427
14433
  args: ["u32", "f32"],
@@ -14551,6 +14557,10 @@ function getOpenTUILib(libPath) {
14551
14557
  args: ["u32"],
14552
14558
  returns: "u32"
14553
14559
  },
14560
+ editBufferSetTabWidth: {
14561
+ args: ["u32", "u8"],
14562
+ returns: "void"
14563
+ },
14554
14564
  editBufferDebugLogRope: {
14555
14565
  args: ["u32"],
14556
14566
  returns: "void"
@@ -15780,7 +15790,8 @@ class FFIRenderLib {
15780
15790
  }
15781
15791
  const width = this.opentui.symbols.getBufferWidth(bufferPtr);
15782
15792
  const height = this.opentui.symbols.getBufferHeight(bufferPtr);
15783
- return new OptimizedBuffer(this, bufferPtr, width, height, { id: "next buffer", widthMethod: "unicode" });
15793
+ const widthMethod = widthMethodFromCode(this.opentui.symbols.getBufferWidthMethod(bufferPtr));
15794
+ return new OptimizedBuffer(this, bufferPtr, width, height, { id: "next buffer", widthMethod });
15784
15795
  }
15785
15796
  getCurrentBuffer(renderer) {
15786
15797
  const bufferPtr = this.opentui.symbols.getCurrentBuffer(renderer);
@@ -15789,7 +15800,8 @@ class FFIRenderLib {
15789
15800
  }
15790
15801
  const width = this.opentui.symbols.getBufferWidth(bufferPtr);
15791
15802
  const height = this.opentui.symbols.getBufferHeight(bufferPtr);
15792
- return new OptimizedBuffer(this, bufferPtr, width, height, { id: "current buffer", widthMethod: "unicode" });
15803
+ const widthMethod = widthMethodFromCode(this.opentui.symbols.getBufferWidthMethod(bufferPtr));
15804
+ return new OptimizedBuffer(this, bufferPtr, width, height, { id: "current buffer", widthMethod });
15793
15805
  }
15794
15806
  rendererSetPaletteState(renderer, palette, defaultForeground, defaultBackground, paletteEpoch) {
15795
15807
  const paletteBuffer = new Uint16Array(palette.length * 4);
@@ -15993,10 +16005,9 @@ class FFIRenderLib {
15993
16005
  if (Number.isNaN(width) || Number.isNaN(height)) {
15994
16006
  console.error(new Error(`Invalid dimensions for OptimizedBuffer: ${width}x${height}`).stack);
15995
16007
  }
15996
- const widthMethodCode = widthMethod === "wcwidth" ? 0 : 1;
15997
16008
  const idToUse = id || "unnamed buffer";
15998
16009
  const idBytes = this.encoder.encode(idToUse);
15999
- const bufferPtr = this.opentui.symbols.createOptimizedBuffer(width, height, ffiBool(respectAlpha), widthMethodCode, idBytes, idBytes.byteLength);
16010
+ const bufferPtr = this.opentui.symbols.createOptimizedBuffer(width, height, ffiBool(respectAlpha), widthMethodCode(widthMethod), idBytes, idBytes.byteLength);
16000
16011
  if (!bufferPtr) {
16001
16012
  throw new Error(`Failed to create optimized buffer: ${width}x${height}`);
16002
16013
  }
@@ -16386,8 +16397,7 @@ class FFIRenderLib {
16386
16397
  });
16387
16398
  }
16388
16399
  createTextBuffer(widthMethod) {
16389
- const widthMethodCode = widthMethod === "wcwidth" ? 0 : 1;
16390
- const bufferPtr = this.opentui.symbols.createTextBuffer(widthMethodCode);
16400
+ const bufferPtr = this.opentui.symbols.createTextBuffer(widthMethodCode(widthMethod));
16391
16401
  if (!bufferPtr) {
16392
16402
  throw new Error(`Failed to create TextBuffer`);
16393
16403
  }
@@ -16789,8 +16799,7 @@ class FFIRenderLib {
16789
16799
  };
16790
16800
  }
16791
16801
  createEditBuffer(widthMethod) {
16792
- const widthMethodCode = widthMethod === "wcwidth" ? 0 : 1;
16793
- const bufferPtr = this.opentui.symbols.createEditBuffer(widthMethodCode, this.eventSinkPtr ?? 0);
16802
+ const bufferPtr = this.opentui.symbols.createEditBuffer(widthMethodCode(widthMethod), this.eventSinkPtr ?? 0);
16794
16803
  if (!bufferPtr) {
16795
16804
  throw new Error("Failed to create EditBuffer");
16796
16805
  }
@@ -16882,6 +16891,9 @@ class FFIRenderLib {
16882
16891
  }
16883
16892
  return result;
16884
16893
  }
16894
+ editBufferSetTabWidth(buffer, width) {
16895
+ this.opentui.symbols.editBufferSetTabWidth(buffer, width);
16896
+ }
16885
16897
  editBufferDebugLogRope(buffer) {
16886
16898
  this.opentui.symbols.editBufferDebugLogRope(buffer);
16887
16899
  }
@@ -17145,10 +17157,9 @@ class FFIRenderLib {
17145
17157
  }
17146
17158
  encodeUnicode(text, widthMethod) {
17147
17159
  const textBytes = this.encoder.encode(text);
17148
- const widthMethodCode = widthMethod === "wcwidth" ? 0 : 1;
17149
17160
  const outPtrBuffer = new ArrayBuffer(8);
17150
17161
  const outLenBuffer = new ArrayBuffer(8);
17151
- const success = this.opentui.symbols.encodeUnicode(viewOrNull(textBytes), textBytes.byteLength, outPtrBuffer, outLenBuffer, widthMethodCode);
17162
+ const success = this.opentui.symbols.encodeUnicode(viewOrNull(textBytes), textBytes.byteLength, outPtrBuffer, outLenBuffer, widthMethodCode(widthMethod));
17152
17163
  if (!success) {
17153
17164
  return null;
17154
17165
  }
@@ -18599,5 +18610,5 @@ var yoga_default = Yoga;
18599
18610
 
18600
18611
  export { toArrayBuffer, singleton, envRegistry, registerEnvVar, clearEnvCache, generateEnvMarkdown, generateEnvColored, env, sleep, stringWidth2 as stringWidth, resolveBundledFilePath, DEFAULT_FOREGROUND_RGB, DEFAULT_BACKGROUND_RGB, normalizeIndexedColorIndex, ansi256IndexToRgb, RGBA, normalizeColorValue, hexToRgb, rgbToHex, hsvToRgb, parseColor, isValidBorderStyle, parseBorderStyle, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, KeyEvent, PasteEvent, KeyHandler, InternalKeyHandler, fonts, measureText, getCharacterPositions, coordinateToCharacterIndex, renderFontToFrameBuffer, TextAttributes, ATTRIBUTE_BASE_BITS, ATTRIBUTE_BASE_MASK, getBaseAttributes, DebugOverlayCorner, TargetChannel, createTextAttributes, attributesWithLink, getLinkId, visualizeRenderableTree, isStyledText, StyledText, stringToStyledText, black, red, green, yellow, blue, magenta, cyan, white, brightBlack, brightRed, brightGreen, brightYellow, brightBlue, brightMagenta, brightCyan, brightWhite, bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite, bold, italic, underline, strikethrough, dim, reverse, blink, fg, bg, link, t, hastToStyledText, SystemClock, nonAlphanumericKeys, terminalNamedSingleStrokeKeys, parseKeypress, LinearScrollAccel, MacOSScrollAccel, parseAlign, parseAlignItems, parseBoxSizing, parseDimension, parseDirection, parseDisplay, parseEdge, parseFlexDirection, parseGutter, parseJustify, parseLogLevel, parseMeasureMode, parseOverflow, parsePositionType, parseUnit, parseWrap, MouseParser, Selection, convertGlobalToLocalSelection, ASCIIFontSelectionHelper, StdinParser, treeSitterToTextChunks, treeSitterToStyledText, addDefaultParsers, TreeSitterClient, DataPathsManager, getDataPaths, extensionToFiletype, basenameToFiletype, extToFiletype, pathToFiletype, infoStringToFiletype, getTreeSitterClient, destroyTreeSitterClient, ExtmarksController, createExtmarksController, TerminalPalette, createTerminalPalette, normalizeTerminalPalette, buildTerminalPaletteSignature, decodePasteBytes, stripAnsiSequences, createHostClipboard, createClipboard, ClipboardTarget, createRendererClipboardAdapter, Clipboard, detectLinks, OptimizedBuffer, TextBuffer, SpanInfoStruct, NativeAudioStreamFormat, NativeAudioStreamState, NativeAudioStreamStateNames, NativeAudioStreamCloseReason, NativeAudioStreamState2 as NativeAudioStreamState1, NativeAudioStreamCloseReason2 as NativeAudioStreamCloseReason1, NativeAudioStreamFormat2 as NativeAudioStreamFormat1, NativeClipboardOperationStatus, NativeClipboardStartStatus, NativeClipboardCancelStatus, NativeClipboardCopyStatus, NativeClipboardDestroyStatus, NativeClipboardShutdownStatus, LogLevel2 as LogLevel, NativeMeasureTargetKind, setRenderLibPath, resolveRenderLib, Align, BoxSizing, Dimension, Direction, Display, Edge, Errata, ExperimentalFeature, FlexDirection, Gutter, Justify, LogLevel as LogLevel1, MeasureMode, NodeType, Overflow, PositionType, Unit, Wrap, ALIGN_AUTO, ALIGN_FLEX_START, ALIGN_CENTER, ALIGN_FLEX_END, ALIGN_STRETCH, ALIGN_BASELINE, ALIGN_SPACE_BETWEEN, ALIGN_SPACE_AROUND, ALIGN_SPACE_EVENLY, BOX_SIZING_BORDER_BOX, BOX_SIZING_CONTENT_BOX, DIMENSION_WIDTH, DIMENSION_HEIGHT, DIRECTION_INHERIT, DIRECTION_LTR, DIRECTION_RTL, DISPLAY_FLEX, DISPLAY_NONE, DISPLAY_CONTENTS, EDGE_LEFT, EDGE_TOP, EDGE_RIGHT, EDGE_BOTTOM, EDGE_START, EDGE_END, EDGE_HORIZONTAL, EDGE_VERTICAL, EDGE_ALL, ERRATA_NONE, ERRATA_STRETCH_FLEX_BASIS, ERRATA_ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING, ERRATA_ABSOLUTE_PERCENT_AGAINST_INNER_SIZE, ERRATA_ALL, ERRATA_CLASSIC, EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS, FLEX_DIRECTION_COLUMN, FLEX_DIRECTION_COLUMN_REVERSE, FLEX_DIRECTION_ROW, FLEX_DIRECTION_ROW_REVERSE, GUTTER_COLUMN, GUTTER_ROW, GUTTER_ALL, JUSTIFY_FLEX_START, JUSTIFY_CENTER, JUSTIFY_FLEX_END, JUSTIFY_SPACE_BETWEEN, JUSTIFY_SPACE_AROUND, JUSTIFY_SPACE_EVENLY, LOG_LEVEL_ERROR, LOG_LEVEL_WARN, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_VERBOSE, LOG_LEVEL_FATAL, MEASURE_MODE_UNDEFINED, MEASURE_MODE_EXACTLY, MEASURE_MODE_AT_MOST, NODE_TYPE_DEFAULT, NODE_TYPE_TEXT, OVERFLOW_VISIBLE, OVERFLOW_HIDDEN, OVERFLOW_SCROLL, POSITION_TYPE_STATIC, POSITION_TYPE_RELATIVE, POSITION_TYPE_ABSOLUTE, UNIT_UNDEFINED, UNIT_POINT, UNIT_PERCENT, UNIT_AUTO, WRAP_NO_WRAP, WRAP_WRAP, WRAP_WRAP_REVERSE, Config, Node, exports_yoga, yoga_default };
18601
18612
 
18602
- //# debugId=CCD1F52D948CB76B64756E2164756E21
18603
- //# sourceMappingURL=chunk-bun-xmsp0nqq.js.map
18613
+ //# debugId=A1152A2EED56A71564756E2164756E21
18614
+ //# sourceMappingURL=chunk-bun-b0662dgp.js.map