@nghyane/arcane-tui 0.1.3 → 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/package.json CHANGED
@@ -1,72 +1,72 @@
1
1
  {
2
- "type": "module",
3
- "name": "@nghyane/arcane-tui",
4
- "version": "0.1.3",
5
- "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
6
- "homepage": "https://github.com/nghyane/arcane",
7
- "author": "Can Bölük",
8
- "contributors": [
9
- "Mario Zechner"
10
- ],
11
- "license": "GPL-3.0-or-later",
12
- "publishConfig": {
13
- "access": "public"
14
- },
15
- "repository": {
16
- "type": "git",
17
- "url": "git+https://github.com/nghyane/arcane.git",
18
- "directory": "packages/tui"
19
- },
20
- "bugs": {
21
- "url": "https://github.com/nghyane/arcane/issues"
22
- },
23
- "keywords": [
24
- "tui",
25
- "terminal",
26
- "ui",
27
- "text-editor",
28
- "differential-rendering",
29
- "typescript",
30
- "cli"
31
- ],
32
- "main": "./src/index.ts",
33
- "types": "./src/index.ts",
34
- "scripts": {
35
- "check": "tsgo -p tsconfig.json",
36
- "test": "bun test test/*.test.ts"
37
- },
38
- "dependencies": {
39
- "@nghyane/arcane-natives": "workspace:*",
40
- "@nghyane/arcane-utils": "workspace:*",
41
- "@types/mime-types": "^3.0.1",
42
- "chalk": "^5.6.2",
43
- "marked": "^17.0.2",
44
- "mime-types": "^3.0.2"
45
- },
46
- "devDependencies": {
47
- "@xterm/headless": "^6.0.0",
48
- "@xterm/xterm": "^6.0.0"
49
- },
50
- "engines": {
51
- "bun": ">=1.3.7"
52
- },
53
- "files": [
54
- "src",
55
- "README.md",
56
- "CHANGELOG.md"
57
- ],
58
- "exports": {
59
- ".": {
60
- "types": "./src/index.ts",
61
- "import": "./src/index.ts"
62
- },
63
- "./*": {
64
- "types": "./src/*.ts",
65
- "import": "./src/*.ts"
66
- },
67
- "./components/*": {
68
- "types": "./src/components/*.ts",
69
- "import": "./src/components/*.ts"
70
- }
71
- }
2
+ "type": "module",
3
+ "name": "@nghyane/arcane-tui",
4
+ "version": "0.1.8",
5
+ "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
6
+ "homepage": "https://github.com/nghyane/arcane",
7
+ "author": "Can Bölük",
8
+ "contributors": [
9
+ "Mario Zechner"
10
+ ],
11
+ "license": "GPL-3.0-or-later",
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/nghyane/arcane.git",
18
+ "directory": "packages/tui"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/nghyane/arcane/issues"
22
+ },
23
+ "keywords": [
24
+ "tui",
25
+ "terminal",
26
+ "ui",
27
+ "text-editor",
28
+ "differential-rendering",
29
+ "typescript",
30
+ "cli"
31
+ ],
32
+ "main": "./src/index.ts",
33
+ "types": "./src/index.ts",
34
+ "scripts": {
35
+ "check": "tsgo -p tsconfig.json",
36
+ "test": "bun test test/*.test.ts"
37
+ },
38
+ "dependencies": {
39
+ "@nghyane/arcane-natives": "^0.1.7",
40
+ "@nghyane/arcane-utils": "^0.1.6",
41
+ "@types/mime-types": "^3.0.1",
42
+ "chalk": "^5.6.2",
43
+ "marked": "^17.0.2",
44
+ "mime-types": "^3.0.2"
45
+ },
46
+ "devDependencies": {
47
+ "@xterm/headless": "^6.0.0",
48
+ "@xterm/xterm": "^6.0.0"
49
+ },
50
+ "engines": {
51
+ "bun": ">=1.3.7"
52
+ },
53
+ "files": [
54
+ "src",
55
+ "README.md",
56
+ "CHANGELOG.md"
57
+ ],
58
+ "exports": {
59
+ ".": {
60
+ "types": "./src/index.ts",
61
+ "import": "./src/index.ts"
62
+ },
63
+ "./*": {
64
+ "types": "./src/*.ts",
65
+ "import": "./src/*.ts"
66
+ },
67
+ "./components/*": {
68
+ "types": "./src/components/*.ts",
69
+ "import": "./src/components/*.ts"
70
+ }
71
+ }
72
72
  }
@@ -93,6 +93,10 @@ function wordWrapLine(line: string, maxWidth: number): TextChunk[] {
93
93
 
94
94
  // Skip leading whitespace at line start
95
95
  if (atLineStart && token.isWhitespace) {
96
+ // Extend previous chunk's range to cover the skipped whitespace (no cursor gap)
97
+ if (chunks.length > 0) {
98
+ chunks[chunks.length - 1]!.endIndex = token.endIndex;
99
+ }
96
100
  chunkStartIndex = token.endIndex;
97
101
  continue;
98
102
  }
@@ -162,6 +166,10 @@ function wordWrapLine(line: string, maxWidth: number): TextChunk[] {
162
166
  // Start new line - skip leading whitespace
163
167
  atLineStart = true;
164
168
  if (token.isWhitespace) {
169
+ // Extend the just-pushed chunk's range to cover this whitespace (no cursor gap)
170
+ if (chunks.length > 0) {
171
+ chunks[chunks.length - 1]!.endIndex = token.endIndex;
172
+ }
165
173
  currentChunk = "";
166
174
  currentWidth = 0;
167
175
  chunkStartIndex = token.endIndex;
package/src/tui.ts CHANGED
@@ -646,6 +646,7 @@ export class TUI extends Container {
646
646
  this.#selectionActive = false;
647
647
  this.#selectionAnchor = null;
648
648
  this.#selectionEnd = null;
649
+ this.requestRender();
649
650
  }
650
651
 
651
652
  #getSelectionRange(): { startRow: number; startCol: number; endRow: number; endCol: number } | null {
@@ -713,7 +714,9 @@ export class TUI extends Container {
713
714
 
714
715
  // Output only the changed cells
715
716
  let out = "\x1b[?2026h"; // Synchronized output
717
+ out += "\x1b7"; // Save cursor position
716
718
  out += renderDiff(changes, width);
719
+ out += "\x1b8"; // Restore cursor position
717
720
  out += "\x1b[?2026l";
718
721
  this.terminal.write(out);
719
722
  }
@@ -733,11 +736,12 @@ export class TUI extends Container {
733
736
  const line = cache[row];
734
737
  if (TERMINAL.isImageLine(line)) continue;
735
738
  const lineStart = row === startRow ? startCol : 0;
736
- const lineEnd = row === endRow ? endCol : visibleWidth(line);
739
+ const isFullLine = row !== endRow;
740
+ const lineEnd = isFullLine ? visibleWidth(line) : endCol;
737
741
  const sliced = sliceByColumn(line, lineStart, lineEnd - lineStart, true);
738
742
  // Strip ANSI from the sliced segment
739
743
  const plain = sliced.replace(/\x1b\[[^a-zA-Z]*[a-zA-Z]|\x1b\][^\x07]*\x07|\x1b_[^\x07]*\x07/g, "");
740
- textLines.push(plain);
744
+ textLines.push(isFullLine ? plain.trimEnd() : plain);
741
745
  }
742
746
 
743
747
  const text = textLines.join("\n");