linecraft 0.2.0 → 0.2.2
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/LICENSE +0 -1
- package/README.md +34 -8
- package/lib/component.d.ts +34 -0
- package/lib/component.d.ts.map +1 -0
- package/lib/component.js +42 -0
- package/lib/component.js.map +1 -0
- package/lib/components/code-debug.d.ts +35 -0
- package/lib/components/code-debug.d.ts.map +1 -0
- package/lib/components/code-debug.js +294 -0
- package/lib/components/code-debug.js.map +1 -0
- package/lib/components/fill.d.ts +15 -0
- package/lib/components/fill.d.ts.map +1 -0
- package/lib/components/fill.js +37 -0
- package/lib/components/fill.js.map +1 -0
- package/lib/components/index.d.ts +2 -2
- package/lib/components/index.d.ts.map +1 -1
- package/lib/components/index.js +2 -2
- package/lib/components/index.js.map +1 -1
- package/lib/components/progress-bar-grid.d.ts +1 -1
- package/lib/components/progress-bar-grid.d.ts.map +1 -1
- package/lib/components/progress-bar-grid.js +6 -6
- package/lib/components/progress-bar-grid.js.map +1 -1
- package/lib/components/prompt.d.ts +4 -5
- package/lib/components/prompt.d.ts.map +1 -1
- package/lib/components/prompt.js +17 -69
- package/lib/components/prompt.js.map +1 -1
- package/lib/components/section.d.ts +33 -0
- package/lib/components/section.d.ts.map +1 -0
- package/lib/components/section.js +178 -0
- package/lib/components/section.js.map +1 -0
- package/lib/components/segments.d.ts +26 -0
- package/lib/components/segments.d.ts.map +1 -0
- package/lib/components/segments.js +105 -0
- package/lib/components/segments.js.map +1 -0
- package/lib/components/spinner.d.ts +18 -16
- package/lib/components/spinner.d.ts.map +1 -1
- package/lib/components/spinner.js +63 -47
- package/lib/components/spinner.js.map +1 -1
- package/lib/components/style.test.js +11 -11
- package/lib/components/style.test.js.map +1 -1
- package/lib/components/styled.d.ts +17 -0
- package/lib/components/styled.d.ts.map +1 -0
- package/lib/components/styled.js +107 -0
- package/lib/components/styled.js.map +1 -0
- package/lib/components/styled.test.d.ts +2 -0
- package/lib/components/styled.test.d.ts.map +1 -0
- package/lib/components/styled.test.js +135 -0
- package/lib/components/styled.test.js.map +1 -0
- package/lib/index.d.ts +17 -13
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +13 -13
- package/lib/index.js.map +1 -1
- package/lib/index.test.js +17 -11
- package/lib/index.test.js.map +1 -1
- package/lib/layout/grid.d.ts +31 -35
- package/lib/layout/grid.d.ts.map +1 -1
- package/lib/layout/grid.js +437 -216
- package/lib/layout/grid.js.map +1 -1
- package/lib/layout/grid.test.js +332 -36
- package/lib/layout/grid.test.js.map +1 -1
- package/lib/native/ansi.d.ts +9 -0
- package/lib/native/ansi.d.ts.map +1 -1
- package/lib/native/ansi.js +9 -0
- package/lib/native/ansi.js.map +1 -1
- package/lib/native/diff.d.ts +5 -1
- package/lib/native/diff.d.ts.map +1 -1
- package/lib/native/diff.js +25 -7
- package/lib/native/diff.js.map +1 -1
- package/lib/native/region-renderer-debug.test.d.ts +2 -0
- package/lib/native/region-renderer-debug.test.d.ts.map +1 -0
- package/lib/native/region-renderer-debug.test.js +45 -0
- package/lib/native/region-renderer-debug.test.js.map +1 -0
- package/lib/native/region-renderer.d.ts +57 -148
- package/lib/native/region-renderer.d.ts.map +1 -1
- package/lib/native/region-renderer.js +455 -1124
- package/lib/native/region-renderer.js.map +1 -1
- package/lib/native/region.test.js +2 -20
- package/lib/native/region.test.js.map +1 -1
- package/lib/region-resize.test.d.ts +2 -0
- package/lib/region-resize.test.d.ts.map +1 -0
- package/lib/region-resize.test.js +124 -0
- package/lib/region-resize.test.js.map +1 -0
- package/lib/region.d.ts +97 -9
- package/lib/region.d.ts.map +1 -1
- package/lib/region.js +591 -185
- package/lib/region.js.map +1 -1
- package/lib/region.test.js +3 -3
- package/lib/region.test.js.map +1 -1
- package/lib/types.d.ts +9 -0
- package/lib/types.d.ts.map +1 -1
- package/lib/utils/file-link.d.ts +16 -0
- package/lib/utils/file-link.d.ts.map +1 -0
- package/lib/utils/file-link.js +23 -0
- package/lib/utils/file-link.js.map +1 -0
- package/lib/utils/prompt.d.ts +15 -0
- package/lib/utils/prompt.d.ts.map +1 -0
- package/lib/utils/prompt.js +128 -0
- package/lib/utils/prompt.js.map +1 -0
- package/lib/utils/terminal-theme.d.ts +36 -0
- package/lib/utils/terminal-theme.d.ts.map +1 -0
- package/lib/utils/terminal-theme.js +61 -0
- package/lib/utils/terminal-theme.js.map +1 -0
- package/lib/utils/text.d.ts +53 -3
- package/lib/utils/text.d.ts.map +1 -1
- package/lib/utils/text.js +194 -36
- package/lib/utils/text.js.map +1 -1
- package/lib/utils/wait-for-spacebar.d.ts.map +1 -1
- package/lib/utils/wait-for-spacebar.js +9 -6
- package/lib/utils/wait-for-spacebar.js.map +1 -1
- package/package.json +17 -13
package/lib/utils/text.js
CHANGED
|
@@ -1,73 +1,228 @@
|
|
|
1
1
|
// Text utilities for handling overflow, ellipsis, etc.
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Strip ANSI escape codes from a string to get plain text
|
|
4
|
+
*
|
|
5
|
+
* This removes all ANSI escape sequences (e.g., color codes, cursor movements)
|
|
6
|
+
* from the input string, returning only the visible characters.
|
|
7
|
+
*
|
|
8
|
+
* @param text - String that may contain ANSI escape codes
|
|
9
|
+
* @returns Plain text with all ANSI codes removed
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* stripAnsi('\x1b[31mHello\x1b[0m') // 'Hello'
|
|
13
|
+
*/
|
|
14
|
+
export function stripAnsi(text) {
|
|
15
|
+
const ansiRegex = /\x1b\[[0-9;]*m/g;
|
|
16
|
+
return text.replace(ansiRegex, '');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Truncate text to a maximum visual width while preserving ANSI escape codes
|
|
20
|
+
*
|
|
21
|
+
* This function truncates text based on its visual width (ignoring ANSI codes),
|
|
22
|
+
* but preserves all ANSI escape sequences in the output. This is the base function
|
|
23
|
+
* used by all other truncate functions.
|
|
24
|
+
*
|
|
25
|
+
* @param text - Text that may contain ANSI escape codes
|
|
26
|
+
* @param maxWidth - Maximum visual width (number of visible characters)
|
|
27
|
+
* @returns Truncated text with ANSI codes preserved (no ellipsis added)
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* truncateToWidth('\x1b[31mHello World\x1b[0m', 8) // '\x1b[31mHello Wo\x1b[0m'
|
|
31
|
+
*/
|
|
32
|
+
export function truncateToWidth(text, maxWidth) {
|
|
33
|
+
if (maxWidth <= 0) {
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
36
|
+
// Quick check: if plain text fits, no truncation needed
|
|
37
|
+
const plain = stripAnsi(text);
|
|
38
|
+
if (plain.length <= maxWidth) {
|
|
39
|
+
return text;
|
|
40
|
+
}
|
|
41
|
+
// Truncate while preserving ANSI codes
|
|
42
|
+
// We iterate through the string, counting visual characters while skipping ANSI sequences
|
|
43
|
+
let visual = 0; // Count of visible characters seen so far
|
|
44
|
+
let idx = 0; // Current position in the string
|
|
45
|
+
while (idx < text.length && visual < maxWidth) {
|
|
46
|
+
if (text[idx] === '\x1b') {
|
|
47
|
+
// Found start of ANSI escape sequence - skip to the end
|
|
48
|
+
// ANSI codes follow pattern: \x1b[...m where ... can contain numbers, semicolons
|
|
49
|
+
let end = idx + 1;
|
|
50
|
+
while (end < text.length && text[end] !== 'm') {
|
|
51
|
+
end++;
|
|
52
|
+
}
|
|
53
|
+
// Include the 'm' if found
|
|
54
|
+
if (end < text.length) {
|
|
55
|
+
end++;
|
|
56
|
+
}
|
|
57
|
+
idx = end;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Regular character - count it and advance
|
|
61
|
+
idx++;
|
|
62
|
+
visual++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Return substring up to the truncation point
|
|
66
|
+
return text.substring(0, idx);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Truncate text with ellipsis at the end, preserving ANSI escape codes
|
|
70
|
+
*
|
|
71
|
+
* @param text - Text that may contain ANSI escape codes
|
|
72
|
+
* @param maxWidth - Maximum visual width (number of visible characters)
|
|
73
|
+
* @returns Truncated text with '...' at the end, ANSI codes preserved
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* truncateEnd('\x1b[31mHello World\x1b[0m', 8) // '\x1b[31mHello...\x1b[0m'
|
|
4
77
|
*/
|
|
5
78
|
export function truncateEnd(text, maxWidth) {
|
|
6
|
-
|
|
79
|
+
const plain = stripAnsi(text);
|
|
80
|
+
if (plain.length <= maxWidth) {
|
|
7
81
|
return text;
|
|
8
82
|
}
|
|
9
83
|
if (maxWidth <= 3) {
|
|
10
84
|
return '.'.repeat(maxWidth);
|
|
11
85
|
}
|
|
12
|
-
|
|
86
|
+
// Truncate to make room for ellipsis, then add ellipsis
|
|
87
|
+
const truncated = truncateToWidth(text, maxWidth - 3);
|
|
88
|
+
return truncated + '...';
|
|
13
89
|
}
|
|
14
90
|
/**
|
|
15
|
-
* Truncate text with ellipsis at the beginning
|
|
91
|
+
* Truncate text with ellipsis at the beginning, preserving ANSI escape codes
|
|
92
|
+
*
|
|
93
|
+
* @param text - Text that may contain ANSI escape codes
|
|
94
|
+
* @param maxWidth - Maximum visual width (number of visible characters)
|
|
95
|
+
* @returns Truncated text with '...' at the beginning, ANSI codes preserved
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* truncateStart('\x1b[31mHello World\x1b[0m', 8) // '...\x1b[31mWorld\x1b[0m'
|
|
16
99
|
*/
|
|
17
100
|
export function truncateStart(text, maxWidth) {
|
|
18
|
-
|
|
101
|
+
const plain = stripAnsi(text);
|
|
102
|
+
if (plain.length <= maxWidth) {
|
|
19
103
|
return text;
|
|
20
104
|
}
|
|
21
105
|
if (maxWidth <= 3) {
|
|
22
106
|
return '.'.repeat(maxWidth);
|
|
23
107
|
}
|
|
24
|
-
|
|
108
|
+
// We need to truncate from the start, preserving ANSI codes
|
|
109
|
+
// This is trickier - we need to work backwards
|
|
110
|
+
const availableWidth = maxWidth - 3;
|
|
111
|
+
const startIdx = plain.length - availableWidth;
|
|
112
|
+
// Find the actual start position in the original string (accounting for ANSI codes)
|
|
113
|
+
let visual = 0;
|
|
114
|
+
let idx = 0;
|
|
115
|
+
while (idx < text.length && visual < startIdx) {
|
|
116
|
+
if (text[idx] === '\x1b') {
|
|
117
|
+
let end = idx + 1;
|
|
118
|
+
while (end < text.length && text[end] !== 'm') {
|
|
119
|
+
end++;
|
|
120
|
+
}
|
|
121
|
+
if (end < text.length) {
|
|
122
|
+
end++;
|
|
123
|
+
}
|
|
124
|
+
idx = end;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
idx++;
|
|
128
|
+
visual++;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return '...' + text.substring(idx);
|
|
25
132
|
}
|
|
26
133
|
/**
|
|
27
|
-
* Truncate text with ellipsis in the middle
|
|
134
|
+
* Truncate text with ellipsis in the middle, preserving ANSI escape codes
|
|
135
|
+
*
|
|
136
|
+
* @param text - Text that may contain ANSI escape codes
|
|
137
|
+
* @param maxWidth - Maximum visual width (number of visible characters)
|
|
138
|
+
* @returns Truncated text with '...' in the middle, ANSI codes preserved
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* truncateMiddle('\x1b[31mHello World\x1b[0m', 8) // '\x1b[31mHel...ld\x1b[0m'
|
|
28
142
|
*/
|
|
29
143
|
export function truncateMiddle(text, maxWidth) {
|
|
30
|
-
|
|
144
|
+
const plain = stripAnsi(text);
|
|
145
|
+
if (plain.length <= maxWidth) {
|
|
31
146
|
return text;
|
|
32
147
|
}
|
|
33
148
|
if (maxWidth <= 3) {
|
|
34
149
|
return '.'.repeat(maxWidth);
|
|
35
150
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
151
|
+
// Calculate how many characters we can show on each side
|
|
152
|
+
// Total: start + 3 (ellipsis) + end = maxWidth
|
|
153
|
+
const availableChars = maxWidth - 3; // Characters available for text (excluding ellipsis)
|
|
154
|
+
const startChars = Math.floor(availableChars / 2);
|
|
155
|
+
const endChars = availableChars - startChars;
|
|
156
|
+
// Get start portion
|
|
157
|
+
const startPortion = truncateToWidth(text, startChars);
|
|
158
|
+
// Get end portion - work backwards from the end
|
|
159
|
+
const endStartIdx = plain.length - endChars;
|
|
160
|
+
// Find the actual start position in the original string (accounting for ANSI codes)
|
|
161
|
+
let visual = 0;
|
|
162
|
+
let idx = 0;
|
|
163
|
+
while (idx < text.length && visual < endStartIdx) {
|
|
164
|
+
if (text[idx] === '\x1b') {
|
|
165
|
+
let end = idx + 1;
|
|
166
|
+
while (end < text.length && text[end] !== 'm') {
|
|
167
|
+
end++;
|
|
168
|
+
}
|
|
169
|
+
if (end < text.length) {
|
|
170
|
+
end++;
|
|
171
|
+
}
|
|
172
|
+
idx = end;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
idx++;
|
|
176
|
+
visual++;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const endPortion = text.substring(idx);
|
|
180
|
+
return startPortion + '...' + endPortion;
|
|
39
181
|
}
|
|
40
182
|
/**
|
|
41
183
|
* Wrap text to fit within a width, breaking on spaces
|
|
42
184
|
*/
|
|
43
185
|
export function wrapText(text, width) {
|
|
186
|
+
if (!Number.isFinite(width) || width <= 0) {
|
|
187
|
+
return text.length > 0 ? [text] : [''];
|
|
188
|
+
}
|
|
44
189
|
const lines = [];
|
|
45
|
-
const
|
|
46
|
-
let
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
190
|
+
const length = text.length;
|
|
191
|
+
let index = 0;
|
|
192
|
+
while (index < length) {
|
|
193
|
+
// Skip leading spaces
|
|
194
|
+
while (index < length && text[index] === ' ') {
|
|
195
|
+
index++;
|
|
50
196
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
197
|
+
if (index >= length) {
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
let end = Math.min(length, index + width);
|
|
201
|
+
if (end === length) {
|
|
202
|
+
lines.push(text.slice(index));
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
let breakPoint = -1;
|
|
206
|
+
for (let i = end; i > index; i--) {
|
|
207
|
+
const char = text[i - 1];
|
|
208
|
+
if (char === ' ') {
|
|
209
|
+
breakPoint = i - 1;
|
|
210
|
+
break;
|
|
63
211
|
}
|
|
64
|
-
|
|
65
|
-
|
|
212
|
+
if (char === '-') {
|
|
213
|
+
breakPoint = i;
|
|
214
|
+
break;
|
|
66
215
|
}
|
|
67
216
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
217
|
+
if (breakPoint === -1) {
|
|
218
|
+
breakPoint = end;
|
|
219
|
+
}
|
|
220
|
+
const line = text.slice(index, breakPoint).trimEnd();
|
|
221
|
+
lines.push(line);
|
|
222
|
+
index = breakPoint;
|
|
223
|
+
while (index < length && text[index] === ' ') {
|
|
224
|
+
index++;
|
|
225
|
+
}
|
|
71
226
|
}
|
|
72
227
|
return lines.length > 0 ? lines : [''];
|
|
73
228
|
}
|
|
@@ -75,8 +230,11 @@ export function wrapText(text, width) {
|
|
|
75
230
|
* Get the visual width of text (accounting for ANSI codes)
|
|
76
231
|
*/
|
|
77
232
|
export function getTextWidth(text) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
233
|
+
return stripAnsi(text).length;
|
|
234
|
+
}
|
|
235
|
+
export function getTrimmedTextWidth(text) {
|
|
236
|
+
const plain = stripAnsi(text);
|
|
237
|
+
const trimmed = plain.replace(/\s+$/u, '');
|
|
238
|
+
return trimmed.length;
|
|
81
239
|
}
|
|
82
240
|
//# sourceMappingURL=text.js.map
|
package/lib/utils/text.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/utils/text.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/utils/text.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,SAAS,GAAG,iBAAiB,CAAC;IACpC,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,QAAgB;IAC5D,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAClB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,wDAAwD;IACxD,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uCAAuC;IACvC,0FAA0F;IAC1F,IAAI,MAAM,GAAG,CAAC,CAAC,CAAE,0CAA0C;IAC3D,IAAI,GAAG,GAAG,CAAC,CAAC,CAAK,iCAAiC;IAElD,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,GAAG,QAAQ,EAAE,CAAC;QAC9C,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,MAAM,EAAE,CAAC;YACzB,wDAAwD;YACxD,iFAAiF;YACjF,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;YAClB,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC9C,GAAG,EAAE,CAAC;YACR,CAAC;YACD,2BAA2B;YAC3B,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;gBACtB,GAAG,EAAE,CAAC;YACR,CAAC;YACD,GAAG,GAAG,GAAG,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,2CAA2C;YAC3C,GAAG,EAAE,CAAC;YACN,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC;IAED,8CAA8C;IAC9C,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,QAAgB;IACxD,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAClB,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IACD,wDAAwD;IACxD,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC;IACtD,OAAO,SAAS,GAAG,KAAK,CAAC;AAC3B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,QAAgB;IAC1D,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAClB,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IACD,4DAA4D;IAC5D,+CAA+C;IAC/C,MAAM,cAAc,GAAG,QAAQ,GAAG,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,GAAG,cAAc,CAAC;IAE/C,oFAAoF;IACpF,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,GAAG,QAAQ,EAAE,CAAC;QAC9C,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,MAAM,EAAE,CAAC;YACzB,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;YAClB,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC9C,GAAG,EAAE,CAAC;YACR,CAAC;YACD,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;gBACtB,GAAG,EAAE,CAAC;YACR,CAAC;YACD,GAAG,GAAG,GAAG,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,GAAG,EAAE,CAAC;YACN,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC;IAED,OAAO,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,QAAgB;IAC3D,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAClB,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IACD,yDAAyD;IACzD,+CAA+C;IAC/C,MAAM,cAAc,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,qDAAqD;IAC1F,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,cAAc,GAAG,UAAU,CAAC;IAE7C,oBAAoB;IACpB,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAEvD,gDAAgD;IAChD,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC;IAE5C,oFAAoF;IACpF,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,GAAG,WAAW,EAAE,CAAC;QACjD,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,MAAM,EAAE,CAAC;YACzB,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;YAClB,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC9C,GAAG,EAAE,CAAC;YACR,CAAC;YACD,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;gBACtB,GAAG,EAAE,CAAC;YACR,CAAC;YACD,GAAG,GAAG,GAAG,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,GAAG,EAAE,CAAC;YACN,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAEvC,OAAO,YAAY,GAAG,KAAK,GAAG,UAAU,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,KAAa;IAClD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC3B,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,KAAK,GAAG,MAAM,EAAE,CAAC;QACtB,sBAAsB;QACtB,OAAO,KAAK,GAAG,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;YAC7C,KAAK,EAAE,CAAC;QACV,CAAC;QACD,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;YACpB,MAAM;QACR,CAAC;QAED,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC;QAE1C,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YAC9B,MAAM;QACR,CAAC;QAED,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC;QACpB,KAAK,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACjB,UAAU,GAAG,CAAC,GAAG,CAAC,CAAC;gBACnB,MAAM;YACR,CAAC;YACD,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACjB,UAAU,GAAG,CAAC,CAAC;gBACf,MAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;YACtB,UAAU,GAAG,GAAG,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEjB,KAAK,GAAG,UAAU,CAAC;QACnB,OAAO,KAAK,GAAG,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;YAC7C,KAAK,EAAE,CAAC;QACV,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC3C,OAAO,OAAO,CAAC,MAAM,CAAC;AACxB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait-for-spacebar.d.ts","sourceRoot":"","sources":["../../src/utils/wait-for-spacebar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGhD;;;;;;GAMG;AACH,
|
|
1
|
+
{"version":3,"file":"wait-for-spacebar.d.ts","sourceRoot":"","sources":["../../src/utils/wait-for-spacebar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGhD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,MAAwC,GAChD,OAAO,CAAC,IAAI,CAAC,CAuEf"}
|
|
@@ -6,14 +6,16 @@ import { logToFile } from './debug-log';
|
|
|
6
6
|
* Adds the prompt as part of the region by expanding it, ensuring everything
|
|
7
7
|
* is managed by the region and avoiding scrolling/positioning issues.
|
|
8
8
|
*/
|
|
9
|
-
export function waitForSpacebar(region, message = 'Press SPACEBAR to continue...') {
|
|
9
|
+
export async function waitForSpacebar(region, message = 'Press SPACEBAR to continue...') {
|
|
10
|
+
// Prepare prompt inside region before listening for input
|
|
11
|
+
logToFile(`[waitForSpacebar] CALLED, isTTY=${process.stdin.isTTY}, isRaw=${process.stdin.isRaw}`);
|
|
12
|
+
region.add(['', message]);
|
|
13
|
+
await region.flush();
|
|
14
|
+
const promptLineNumber = region.height;
|
|
15
|
+
const promptColumn = message.length + 1;
|
|
16
|
+
region.showCursorAt(promptLineNumber, promptColumn);
|
|
10
17
|
return new Promise((resolve) => {
|
|
11
18
|
// DEBUG: Log when waitForSpacebar is called
|
|
12
|
-
logToFile(`[waitForSpacebar] CALLED, isTTY=${process.stdin.isTTY}, isRaw=${process.stdin.isRaw}`);
|
|
13
|
-
// CRITICAL: Use add() to properly append the prompt to the region
|
|
14
|
-
// This ensures the cursor is positioned at the end of the region correctly
|
|
15
|
-
// and all rendering/positioning is handled properly
|
|
16
|
-
region.add(['', message]);
|
|
17
19
|
// Set stdin to raw mode to capture individual keypresses
|
|
18
20
|
if (!process.stdin.isTTY) {
|
|
19
21
|
// If not a TTY, just resolve immediately
|
|
@@ -62,6 +64,7 @@ export function waitForSpacebar(region, message = 'Press SPACEBAR to continue...
|
|
|
62
64
|
// CRITICAL: Remove SIGINT listener to prevent memory leak
|
|
63
65
|
// Each call to waitForSpacebar adds a SIGINT listener, so we must remove it
|
|
64
66
|
process.removeListener('SIGINT', onSIGINT);
|
|
67
|
+
region.hideCursor();
|
|
65
68
|
};
|
|
66
69
|
// Handle Ctrl+C explicitly
|
|
67
70
|
process.on('SIGINT', onSIGINT);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait-for-spacebar.js","sourceRoot":"","sources":["../../src/utils/wait-for-spacebar.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,
|
|
1
|
+
{"version":3,"file":"wait-for-spacebar.js","sourceRoot":"","sources":["../../src/utils/wait-for-spacebar.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "linecraft",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "High-performance terminal UI library for Node.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -18,7 +18,22 @@
|
|
|
18
18
|
"files": [
|
|
19
19
|
"lib/**/*"
|
|
20
20
|
],
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/matthew-dean/linecraft.git"
|
|
24
|
+
},
|
|
21
25
|
"license": "MIT",
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build:ts": "tsc -p tsconfig.build.json",
|
|
28
|
+
"build": "pnpm build:ts",
|
|
29
|
+
"dev": "pnpm build:ts --watch",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"test": "vitest",
|
|
32
|
+
"test:ts": "vitest",
|
|
33
|
+
"example": "node scripts/run-example.js",
|
|
34
|
+
"record": "vhs",
|
|
35
|
+
"record:all": "node scripts/record-all.js"
|
|
36
|
+
},
|
|
22
37
|
"keywords": [
|
|
23
38
|
"terminal",
|
|
24
39
|
"tui",
|
|
@@ -34,16 +49,5 @@
|
|
|
34
49
|
},
|
|
35
50
|
"engines": {
|
|
36
51
|
"node": ">=18.0.0"
|
|
37
|
-
},
|
|
38
|
-
"scripts": {
|
|
39
|
-
"build:ts": "tsc -p tsconfig.build.json",
|
|
40
|
-
"build": "pnpm build:ts",
|
|
41
|
-
"dev": "pnpm build:ts --watch",
|
|
42
|
-
"typecheck": "tsc --noEmit",
|
|
43
|
-
"test": "vitest",
|
|
44
|
-
"test:ts": "vitest",
|
|
45
|
-
"example": "node scripts/run-example.js",
|
|
46
|
-
"record": "vhs",
|
|
47
|
-
"record:all": "node scripts/record-all.js"
|
|
48
52
|
}
|
|
49
|
-
}
|
|
53
|
+
}
|