promptgraph-mcp 2.2.4 → 2.2.6
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 +1 -1
- package/tui.js +28 -7
package/package.json
CHANGED
package/tui.js
CHANGED
|
@@ -85,7 +85,7 @@ function render(state, installedSet = new Set()) {
|
|
|
85
85
|
const skills = items.filter(i => i.type === 'skill').length;
|
|
86
86
|
const bundles = items.filter(i => i.type === 'bundle').length;
|
|
87
87
|
|
|
88
|
-
write('\x1b[H
|
|
88
|
+
write('\x1b[H'); // go home — screen already cleared on init, just reposition
|
|
89
89
|
|
|
90
90
|
// ── header ─────────────────────────────────────────────────────────────────
|
|
91
91
|
// Row 1: title bar
|
|
@@ -153,9 +153,9 @@ function render(state, installedSet = new Set()) {
|
|
|
153
153
|
? item.skillCount
|
|
154
154
|
? blue((item.skillCount + ' sk').padEnd(8))
|
|
155
155
|
: item.repo_url
|
|
156
|
-
?
|
|
156
|
+
? chalk.hex('#3B82F6')('↗ GitHub')
|
|
157
157
|
: dim(((item.skills?.length || 0) + ' sk').padEnd(8))
|
|
158
|
-
:
|
|
158
|
+
: chalk.hex('#A78BFA')((item.code || '').padEnd(10));
|
|
159
159
|
const desc = dim(truncate(item.description, Math.max(10, DESC_W)));
|
|
160
160
|
|
|
161
161
|
write(bg + ` ${arrow} ${type} ${badge} ${nameCol} ${extra} ${desc}` + reset + CLEAR_EOL + '\n');
|
|
@@ -188,16 +188,37 @@ function render(state, installedSet = new Set()) {
|
|
|
188
188
|
|
|
189
189
|
// ── clamp scroll ─────────────────────────────────────────────────────────────
|
|
190
190
|
|
|
191
|
+
// Count how many screen rows items[start..end] occupy (including category headers)
|
|
192
|
+
function countVisibleRows(items, start, end) {
|
|
193
|
+
let rows = 0;
|
|
194
|
+
let lastCat = start > 0 ? items[start - 1]?.category : null;
|
|
195
|
+
for (let i = start; i < end && i < items.length; i++) {
|
|
196
|
+
if (items[i].category !== lastCat) { rows++; lastCat = items[i].category; }
|
|
197
|
+
rows++;
|
|
198
|
+
}
|
|
199
|
+
return rows;
|
|
200
|
+
}
|
|
201
|
+
|
|
191
202
|
function clampScroll(state) {
|
|
192
203
|
const { rows } = termSize();
|
|
193
204
|
const HEADER_ROWS = 4, FOOTER_ROWS = 3;
|
|
194
205
|
const LIST_ROWS = rows - HEADER_ROWS - FOOTER_ROWS;
|
|
195
206
|
const { cursor, items } = state;
|
|
196
207
|
|
|
197
|
-
// ensure cursor visible — approximate (category headers add extra rows)
|
|
198
|
-
if (cursor < state.scroll) state.scroll = cursor;
|
|
199
|
-
if (cursor >= state.scroll + LIST_ROWS - 2) state.scroll = cursor - LIST_ROWS + 3;
|
|
200
208
|
if (state.scroll < 0) state.scroll = 0;
|
|
209
|
+
if (state.scroll > cursor) state.scroll = cursor;
|
|
210
|
+
|
|
211
|
+
// Check if cursor is visible from current scroll
|
|
212
|
+
const visibleRows = countVisibleRows(items, state.scroll, cursor + 1);
|
|
213
|
+
if (visibleRows > LIST_ROWS - 1) {
|
|
214
|
+
// Cursor is below visible area — scroll forward until it fits
|
|
215
|
+
while (state.scroll < cursor) {
|
|
216
|
+
state.scroll++;
|
|
217
|
+
const v = countVisibleRows(items, state.scroll, cursor + 1);
|
|
218
|
+
if (v <= LIST_ROWS - 1) break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
201
222
|
if (state.scroll >= items.length) state.scroll = Math.max(0, items.length - 1);
|
|
202
223
|
}
|
|
203
224
|
|
|
@@ -225,7 +246,7 @@ export async function runTUI(allSkills, allBundles, installFn, installedSet = ne
|
|
|
225
246
|
}
|
|
226
247
|
|
|
227
248
|
// Setup terminal
|
|
228
|
-
write(HIDE + CLEAR);
|
|
249
|
+
write(HIDE + CLEAR + '\x1b[H\x1b[J');
|
|
229
250
|
readline.emitKeypressEvents(process.stdin);
|
|
230
251
|
if (process.stdin.isTTY) process.stdin.setRawMode(true);
|
|
231
252
|
|