@dui-toolkit/plugin-tui 0.1.1-next.3 → 0.1.1-next.4
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/dist/index.mjs +30 -17
- package/package.json +5 -2
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { stripAnsi, truncateByCells, visibleLength } from "@bdocs/dui";
|
|
1
|
+
import { splitGraphemes, stripAnsi, truncateByCells, visibleLength } from "@bdocs/dui";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
//#region src/widget.ts
|
|
4
4
|
var BaseWidget = class {
|
|
@@ -72,8 +72,11 @@ var TextInput = class extends BaseWidget {
|
|
|
72
72
|
/** Set the text value programmatically. */
|
|
73
73
|
setValue(value) {
|
|
74
74
|
const max = this.data.maxLength;
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
if (max > 0) {
|
|
76
|
+
const g = splitGraphemes(value);
|
|
77
|
+
this.data.value = g.slice(0, max).join("");
|
|
78
|
+
} else this.data.value = value;
|
|
79
|
+
this.cursorPos = splitGraphemes(this.data.value).length;
|
|
77
80
|
this.data.onChange?.(this.data.value);
|
|
78
81
|
}
|
|
79
82
|
/** Get the current text value. */
|
|
@@ -86,16 +89,18 @@ var TextInput = class extends BaseWidget {
|
|
|
86
89
|
const value = this.data.mask ? this.data.mask.repeat(this.data.value.length) : this.data.value;
|
|
87
90
|
const display = value || this.data.placeholder;
|
|
88
91
|
const isEmpty = !value;
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
let
|
|
92
|
-
let
|
|
92
|
+
const graphemes = splitGraphemes(display);
|
|
93
|
+
const cursorInDisplay = Math.min(this.cursorPos, graphemes.length);
|
|
94
|
+
let before = graphemes.slice(0, cursorInDisplay).join("");
|
|
95
|
+
let cursor = graphemes[cursorInDisplay] || " ";
|
|
96
|
+
let after = graphemes.slice(cursorInDisplay + 1).join("");
|
|
97
|
+
graphemes.slice(cursorInDisplay + 1);
|
|
93
98
|
const maxVisible = width - 4;
|
|
94
99
|
if (visibleLength(display) > maxVisible) {
|
|
95
100
|
const start = Math.max(0, cursorInDisplay - Math.floor(maxVisible / 2));
|
|
96
|
-
before =
|
|
97
|
-
cursor =
|
|
98
|
-
after =
|
|
101
|
+
before = graphemes.slice(start, cursorInDisplay).join("");
|
|
102
|
+
cursor = graphemes[cursorInDisplay] || " ";
|
|
103
|
+
after = graphemes.slice(cursorInDisplay + 1, start + maxVisible).join("");
|
|
99
104
|
}
|
|
100
105
|
const lines = [];
|
|
101
106
|
lines.push(`┌${"─".repeat(width - 2)}┐`);
|
|
@@ -138,14 +143,18 @@ var TextInput = class extends BaseWidget {
|
|
|
138
143
|
return true;
|
|
139
144
|
case "Backspace":
|
|
140
145
|
if (this.cursorPos > 0) {
|
|
141
|
-
|
|
142
|
-
this.cursorPos
|
|
146
|
+
const g = splitGraphemes(this.data.value);
|
|
147
|
+
const pos = Math.min(this.cursorPos, g.length);
|
|
148
|
+
this.data.value = g.slice(0, pos - 1).join("") + g.slice(pos).join("");
|
|
149
|
+
this.cursorPos = pos - 1;
|
|
143
150
|
this.data.onChange?.(this.data.value);
|
|
144
151
|
}
|
|
145
152
|
return true;
|
|
146
153
|
case "Delete":
|
|
147
154
|
if (this.cursorPos < this.data.value.length) {
|
|
148
|
-
|
|
155
|
+
const g = splitGraphemes(this.data.value);
|
|
156
|
+
const pos = Math.min(this.cursorPos, g.length);
|
|
157
|
+
this.data.value = g.slice(0, pos).join("") + g.slice(pos + 1).join("");
|
|
149
158
|
this.data.onChange?.(this.data.value);
|
|
150
159
|
}
|
|
151
160
|
return true;
|
|
@@ -175,9 +184,13 @@ var TextInput = class extends BaseWidget {
|
|
|
175
184
|
}
|
|
176
185
|
if (char && char.length === 1 && char >= " ") {
|
|
177
186
|
const max = this.data.maxLength;
|
|
178
|
-
if (max > 0
|
|
179
|
-
|
|
180
|
-
|
|
187
|
+
if (max > 0) {
|
|
188
|
+
if (splitGraphemes(this.data.value).length >= max) return true;
|
|
189
|
+
}
|
|
190
|
+
const g = splitGraphemes(this.data.value);
|
|
191
|
+
const pos = Math.min(this.cursorPos, g.length);
|
|
192
|
+
this.data.value = g.slice(0, pos).join("") + char + g.slice(pos).join("");
|
|
193
|
+
this.cursorPos = pos + 1;
|
|
181
194
|
this.data.onChange?.(this.data.value);
|
|
182
195
|
return true;
|
|
183
196
|
}
|
|
@@ -280,7 +293,7 @@ var SelectList = class extends BaseWidget {
|
|
|
280
293
|
if (!this.focused) return false;
|
|
281
294
|
const { key, char, ctrl } = event;
|
|
282
295
|
const items = this.getFilteredItems();
|
|
283
|
-
const maxVisible = Math.max(1, this.viewportHeight - 2);
|
|
296
|
+
const maxVisible = Math.max(1, this.viewportHeight - (this.data.filterActive ? 4 : 2));
|
|
284
297
|
if (this.data.filterActive) {
|
|
285
298
|
if (key === "Escape") {
|
|
286
299
|
this.data.filterActive = false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dui-toolkit/plugin-tui",
|
|
3
|
-
"version": "0.1.1-next.
|
|
3
|
+
"version": "0.1.1-next.4",
|
|
4
4
|
"description": "TUI widget toolkit plugin for @bdocs/dui — text inputs, select lists, modals, status bars, and more.",
|
|
5
5
|
"main": "dist/index.mjs",
|
|
6
6
|
"types": "dist/index.d.mts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"type": "module",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@bdocs/dui": "0.7.0-next.
|
|
31
|
+
"@bdocs/dui": "0.7.0-next.6"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/node": "^22.0.0",
|
|
@@ -36,6 +36,9 @@
|
|
|
36
36
|
"typescript": "^5.9.3",
|
|
37
37
|
"vitest": "^3.0.0"
|
|
38
38
|
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@bdocs/dui": "0.7.0-next.6"
|
|
41
|
+
},
|
|
39
42
|
"scripts": {
|
|
40
43
|
"build": "tsdown --config-loader unrun",
|
|
41
44
|
"dev": "tsdown --watch --config-loader unrun",
|