@nmakarov/cli-toolkit 0.69.0 → 0.71.0
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/cli-runner.cjs +386 -192
- package/dist/cli-runner.cjs.map +1 -1
- package/dist/cli-runner.js +386 -192
- package/dist/cli-runner.js.map +1 -1
- package/dist/index.cjs +440 -208
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +430 -208
- package/dist/index.js.map +1 -1
- package/dist/init.cjs +129 -91
- package/dist/init.cjs.map +1 -1
- package/dist/init.js +129 -91
- package/dist/init.js.map +1 -1
- package/dist/screen.cjs +124 -90
- package/dist/screen.cjs.map +1 -1
- package/dist/screen.js +121 -90
- package/dist/screen.js.map +1 -1
- package/dist/tasks.cjs +308 -117
- package/dist/tasks.cjs.map +1 -1
- package/dist/tasks.js +301 -117
- package/dist/tasks.js.map +1 -1
- package/package.json +2 -2
package/dist/screen.js
CHANGED
|
@@ -84,7 +84,43 @@ function ScreenFooter({ lines, textStyle }) {
|
|
|
84
84
|
// src/screen/list-components.js
|
|
85
85
|
import React, { useState, useEffect, useRef, createElement } from "react";
|
|
86
86
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
87
|
+
|
|
88
|
+
// src/screen/scrollbar.js
|
|
89
|
+
var BAR_THUMB = "#";
|
|
90
|
+
var BAR_TRACK = "|";
|
|
91
|
+
function scrollbarGlyphs(viewportRows, totalLines, scrollTop) {
|
|
92
|
+
const view = Math.max(1, Math.floor(viewportRows));
|
|
93
|
+
const total = Math.max(0, Math.floor(totalLines));
|
|
94
|
+
if (total <= view) return null;
|
|
95
|
+
const maxScroll = total - view;
|
|
96
|
+
const thumbSize = Math.max(1, Math.round(view / total * view));
|
|
97
|
+
const travel = Math.max(0, view - thumbSize);
|
|
98
|
+
const s = Math.min(Math.max(0, Math.floor(scrollTop)), maxScroll);
|
|
99
|
+
const thumbStart = maxScroll === 0 ? 0 : Math.round(s / maxScroll * travel);
|
|
100
|
+
const glyphs = [];
|
|
101
|
+
for (let i = 0; i < view; i++) {
|
|
102
|
+
glyphs.push(i >= thumbStart && i < thumbStart + thumbSize ? BAR_THUMB : BAR_TRACK);
|
|
103
|
+
}
|
|
104
|
+
return glyphs;
|
|
105
|
+
}
|
|
106
|
+
var PAGE_SCROLL_KEY_BINDINGS = [
|
|
107
|
+
{ key: "upArrow", meta: true, caption: "page", action: "pageUp", order: 0 },
|
|
108
|
+
{ key: "downArrow", meta: true, caption: "page", action: "pageDown", order: 0 },
|
|
109
|
+
{ key: "upArrow", ctrl: true, caption: "page", action: "pageUp", order: 0 },
|
|
110
|
+
{ key: "downArrow", ctrl: true, caption: "page", action: "pageDown", order: 0 },
|
|
111
|
+
{ key: "pageUp", caption: "page", action: "pageUp", order: 0 },
|
|
112
|
+
{ key: "pageDown", caption: "page", action: "pageDown", order: 0 }
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
// src/screen/list-components.js
|
|
87
116
|
var h2 = createElement;
|
|
117
|
+
function clipNameForScrollbar(name, needsBar) {
|
|
118
|
+
if (!needsBar || name == null) return name;
|
|
119
|
+
const s = String(name);
|
|
120
|
+
if (s.length <= 1) return s;
|
|
121
|
+
if (/\s$/.test(s)) return s.slice(0, -1);
|
|
122
|
+
return s;
|
|
123
|
+
}
|
|
88
124
|
function MultiColumnListComponent({ items, ctx, selectedIndexRef }) {
|
|
89
125
|
const [, forceUpdate] = useState({});
|
|
90
126
|
const termWidth = (process.stdout.columns || 80) - 8;
|
|
@@ -298,17 +334,42 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
|
|
|
298
334
|
});
|
|
299
335
|
ctx.setAction("scrollUp", () => {
|
|
300
336
|
const { scrollOffset: currentScrollOffset } = scrollStateRef.current;
|
|
301
|
-
|
|
302
|
-
setScrollOffset(newScrollOffset);
|
|
337
|
+
setScrollOffset(Math.max(0, currentScrollOffset - 1));
|
|
303
338
|
forceUpdate({});
|
|
304
339
|
});
|
|
305
340
|
ctx.setAction("scrollDown", () => {
|
|
306
341
|
const { scrollOffset: currentScrollOffset, maxHeight: currentMaxHeight, totalItems } = scrollStateRef.current;
|
|
307
342
|
const currentMaxScrollOffset = Math.max(0, totalItems - currentMaxHeight);
|
|
308
|
-
|
|
309
|
-
|
|
343
|
+
setScrollOffset(Math.min(currentMaxScrollOffset, currentScrollOffset + 1));
|
|
344
|
+
forceUpdate({});
|
|
345
|
+
});
|
|
346
|
+
ctx.setAction("pageUp", () => {
|
|
347
|
+
const { maxHeight: vh } = scrollStateRef.current;
|
|
348
|
+
const page = Math.max(1, vh || 1);
|
|
349
|
+
const newIndex = Math.max(0, selectedIndexRef.current - page);
|
|
350
|
+
selectedIndexRef.current = newIndex;
|
|
351
|
+
const list = displayItemsRef.current;
|
|
352
|
+
onSelectionChangeRef.current?.(newIndex, list[newIndex]);
|
|
353
|
+
setScrollOffset(newIndex);
|
|
310
354
|
forceUpdate({});
|
|
311
355
|
});
|
|
356
|
+
ctx.setAction("pageDown", () => {
|
|
357
|
+
const { maxHeight: vh, totalItems } = scrollStateRef.current;
|
|
358
|
+
const page = Math.max(1, vh || 1);
|
|
359
|
+
const maxIndex = Math.max(0, totalItems - 1);
|
|
360
|
+
const newIndex = Math.min(maxIndex, selectedIndexRef.current + page);
|
|
361
|
+
selectedIndexRef.current = newIndex;
|
|
362
|
+
const list = displayItemsRef.current;
|
|
363
|
+
onSelectionChangeRef.current?.(newIndex, list[newIndex]);
|
|
364
|
+
const maxScroll = Math.max(0, totalItems - page);
|
|
365
|
+
setScrollOffset(Math.min(maxScroll, Math.max(0, newIndex - page + 1)));
|
|
366
|
+
forceUpdate({});
|
|
367
|
+
});
|
|
368
|
+
const navBindings = [
|
|
369
|
+
{ key: "upArrow", caption: "navigate", action: "moveUp", order: 0 },
|
|
370
|
+
{ key: "downArrow", caption: "navigate", action: "moveDown", order: 0 },
|
|
371
|
+
...PAGE_SCROLL_KEY_BINDINGS
|
|
372
|
+
];
|
|
312
373
|
if (sortable) {
|
|
313
374
|
ctx.setAction("toggleSort", () => {
|
|
314
375
|
const nextSort = sortOrder === "none" ? "asc" : sortOrder === "asc" ? "desc" : "none";
|
|
@@ -355,8 +416,7 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
|
|
|
355
416
|
}
|
|
356
417
|
};
|
|
357
418
|
ctx.setKeyBinding([
|
|
358
|
-
|
|
359
|
-
{ key: "downArrow", caption: "navigate", action: "moveDown", order: 0 },
|
|
419
|
+
...navBindings,
|
|
360
420
|
{
|
|
361
421
|
key: "s",
|
|
362
422
|
caption: sortCaption,
|
|
@@ -366,47 +426,47 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
|
|
|
366
426
|
]);
|
|
367
427
|
ctx.update();
|
|
368
428
|
} else {
|
|
369
|
-
ctx.setKeyBinding(
|
|
370
|
-
{ key: "upArrow", caption: "navigate", action: "moveUp", order: 0 },
|
|
371
|
-
{ key: "downArrow", caption: "navigate", action: "moveDown", order: 0 }
|
|
372
|
-
]);
|
|
429
|
+
ctx.setKeyBinding(navBindings);
|
|
373
430
|
}
|
|
374
431
|
}, [sortOrder, sortable]);
|
|
375
432
|
const selectedIndex = selectedIndexRef.current;
|
|
433
|
+
const needsBar = displayItems.length > effectiveMaxHeight;
|
|
434
|
+
const barGlyphs = needsBar ? scrollbarGlyphs(effectiveMaxHeight, displayItems.length, clampedScrollOffset) : null;
|
|
435
|
+
const appendBar = (rowContent, displayIndex) => {
|
|
436
|
+
if (!barGlyphs) return rowContent;
|
|
437
|
+
const glyph = barGlyphs[displayIndex] ?? BAR_TRACK;
|
|
438
|
+
return h2(
|
|
439
|
+
Box2,
|
|
440
|
+
{ flexDirection: "row" },
|
|
441
|
+
rowContent,
|
|
442
|
+
h2(Text2, { color: glyph === BAR_THUMB ? "cyan" : "gray" }, glyph)
|
|
443
|
+
);
|
|
444
|
+
};
|
|
376
445
|
const defaultRenderItem = (item, isSelected, displayIndex, actualIndex) => {
|
|
377
446
|
const isFirstVisible = displayIndex === 0;
|
|
378
447
|
const isLastVisible = displayIndex === visibleItems.length - 1;
|
|
379
|
-
let arrowPrefix = "";
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
arrowPrefix = "\
|
|
383
|
-
} else if (isLastVisible && canScrollDown) {
|
|
384
|
-
arrowPrefix = "\u2193 ";
|
|
385
|
-
} else {
|
|
386
|
-
arrowPrefix = " ";
|
|
387
|
-
}
|
|
388
|
-
if (isSelected) {
|
|
389
|
-
selectionPrefix = selectionMarker;
|
|
390
|
-
} else {
|
|
391
|
-
selectionPrefix = " ".repeat(selectionMarker.length);
|
|
448
|
+
let arrowPrefix = " ";
|
|
449
|
+
if (!needsBar) {
|
|
450
|
+
if (isFirstVisible && canScrollUp) arrowPrefix = "\u2191 ";
|
|
451
|
+
else if (isLastVisible && canScrollDown) arrowPrefix = "\u2193 ";
|
|
392
452
|
}
|
|
453
|
+
const selectionPrefix = isSelected ? selectionMarker : " ".repeat(selectionMarker.length);
|
|
454
|
+
const label = clipNameForScrollbar(item.name, needsBar);
|
|
393
455
|
return h2(
|
|
394
456
|
Box2,
|
|
395
457
|
{ flexDirection: "row" },
|
|
396
|
-
|
|
397
|
-
h2(Text2, {
|
|
398
|
-
key: `arrow-${actualIndex}`,
|
|
399
|
-
color: "white"
|
|
400
|
-
}, arrowPrefix),
|
|
401
|
-
// Selection marker space (always same width, not highlighted)
|
|
458
|
+
h2(Text2, { key: `arrow-${actualIndex}`, color: "white" }, arrowPrefix),
|
|
402
459
|
h2(Text2, { key: `marker-${actualIndex}`, color: "white" }, selectionPrefix),
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
460
|
+
h2(
|
|
461
|
+
Text2,
|
|
462
|
+
{
|
|
463
|
+
key: `name-${actualIndex}`,
|
|
464
|
+
color: isSelected ? "black" : "white",
|
|
465
|
+
backgroundColor: isSelected ? "cyan" : void 0,
|
|
466
|
+
bold: isSelected
|
|
467
|
+
},
|
|
468
|
+
label
|
|
469
|
+
)
|
|
410
470
|
);
|
|
411
471
|
};
|
|
412
472
|
const itemRenderer = renderItem || defaultRenderItem;
|
|
@@ -419,42 +479,32 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
|
|
|
419
479
|
if (renderItem) {
|
|
420
480
|
const isFirstVisible = displayIndex === 0;
|
|
421
481
|
const isLastVisible = displayIndex === visibleItems.length - 1;
|
|
422
|
-
let arrowPrefix = "";
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
arrowPrefix = "\
|
|
426
|
-
} else if (isLastVisible && canScrollDown) {
|
|
427
|
-
arrowPrefix = "\u2193 ";
|
|
428
|
-
} else {
|
|
429
|
-
arrowPrefix = " ";
|
|
430
|
-
}
|
|
431
|
-
if (isSelected) {
|
|
432
|
-
selectionPrefix = selectionMarker;
|
|
433
|
-
} else {
|
|
434
|
-
selectionPrefix = " ".repeat(selectionMarker.length);
|
|
482
|
+
let arrowPrefix = " ";
|
|
483
|
+
if (!needsBar) {
|
|
484
|
+
if (isFirstVisible && canScrollUp) arrowPrefix = "\u2191 ";
|
|
485
|
+
else if (isLastVisible && canScrollDown) arrowPrefix = "\u2193 ";
|
|
435
486
|
}
|
|
487
|
+
const selectionPrefix = isSelected ? selectionMarker : " ".repeat(selectionMarker.length);
|
|
488
|
+
const clipped = needsBar ? { ...item, name: clipNameForScrollbar(item.name, true) } : item;
|
|
489
|
+
const row = h2(
|
|
490
|
+
Box2,
|
|
491
|
+
{ flexDirection: "row" },
|
|
492
|
+
h2(Text2, { key: `arrow-${actualIndex}`, color: "white" }, arrowPrefix),
|
|
493
|
+
h2(Text2, { key: `marker-${actualIndex}`, color: "white" }, selectionPrefix),
|
|
494
|
+
renderItem(clipped, isSelected, displayIndex)
|
|
495
|
+
);
|
|
436
496
|
return h2(ScreenRow, {
|
|
437
497
|
key: `item-${actualIndex}`,
|
|
438
|
-
children:
|
|
439
|
-
Box2,
|
|
440
|
-
{ flexDirection: "row" },
|
|
441
|
-
// Arrow (clickable if functional, not highlighted)
|
|
442
|
-
h2(Text2, {
|
|
443
|
-
key: `arrow-${actualIndex}`,
|
|
444
|
-
color: "white"
|
|
445
|
-
}, arrowPrefix),
|
|
446
|
-
// Selection marker space (always same width, not highlighted)
|
|
447
|
-
h2(Text2, { key: `marker-${actualIndex}`, color: "white" }, selectionPrefix),
|
|
448
|
-
// Custom rendered content
|
|
449
|
-
renderItem(item, isSelected, displayIndex)
|
|
450
|
-
)
|
|
451
|
-
});
|
|
452
|
-
} else {
|
|
453
|
-
return h2(ScreenRow, {
|
|
454
|
-
key: `item-${actualIndex}`,
|
|
455
|
-
children: itemRenderer(item, isSelected, displayIndex, actualIndex)
|
|
498
|
+
children: appendBar(row, displayIndex)
|
|
456
499
|
});
|
|
457
500
|
}
|
|
501
|
+
return h2(ScreenRow, {
|
|
502
|
+
key: `item-${actualIndex}`,
|
|
503
|
+
children: appendBar(
|
|
504
|
+
itemRenderer(item, isSelected, displayIndex, actualIndex),
|
|
505
|
+
displayIndex
|
|
506
|
+
)
|
|
507
|
+
});
|
|
458
508
|
})
|
|
459
509
|
);
|
|
460
510
|
}
|
|
@@ -914,8 +964,6 @@ function InputField({ prompt, value, onChange: _onChange, onSubmit: _onSubmit })
|
|
|
914
964
|
import { useState as useState3, useEffect as useEffect2, useMemo, useRef as useRef2, createElement as createElement2 } from "react";
|
|
915
965
|
import { Box as Box4, Text as Text5 } from "ink";
|
|
916
966
|
var h5 = createElement2;
|
|
917
|
-
var BAR_THUMB = "#";
|
|
918
|
-
var BAR_TRACK = "|";
|
|
919
967
|
function wrapTextLines(text, cols) {
|
|
920
968
|
const w = Math.max(1, Math.floor(Number(cols) || 1));
|
|
921
969
|
const out = [];
|
|
@@ -933,21 +981,6 @@ function wrapTextLines(text, cols) {
|
|
|
933
981
|
}
|
|
934
982
|
return out;
|
|
935
983
|
}
|
|
936
|
-
function scrollbarGlyphs(viewportRows, totalLines, scrollTop) {
|
|
937
|
-
const view = Math.max(1, Math.floor(viewportRows));
|
|
938
|
-
const total = Math.max(0, Math.floor(totalLines));
|
|
939
|
-
if (total <= view) return null;
|
|
940
|
-
const maxScroll = total - view;
|
|
941
|
-
const thumbSize = Math.max(1, Math.round(view / total * view));
|
|
942
|
-
const travel = Math.max(0, view - thumbSize);
|
|
943
|
-
const s = Math.min(Math.max(0, Math.floor(scrollTop)), maxScroll);
|
|
944
|
-
const thumbStart = maxScroll === 0 ? 0 : Math.round(s / maxScroll * travel);
|
|
945
|
-
const glyphs = [];
|
|
946
|
-
for (let i = 0; i < view; i++) {
|
|
947
|
-
glyphs.push(i >= thumbStart && i < thumbStart + thumbSize ? BAR_THUMB : BAR_TRACK);
|
|
948
|
-
}
|
|
949
|
-
return glyphs;
|
|
950
|
-
}
|
|
951
984
|
function padEndVisible(s, w) {
|
|
952
985
|
const t = String(s ?? "");
|
|
953
986
|
if (t.length >= w) return t.slice(0, w);
|
|
@@ -956,12 +989,7 @@ function padEndVisible(s, w) {
|
|
|
956
989
|
var SCROLL_KEYS = [
|
|
957
990
|
{ key: "upArrow", caption: "scroll", action: "scrollUp", order: 0 },
|
|
958
991
|
{ key: "downArrow", caption: "scroll", action: "scrollDown", order: 0 },
|
|
959
|
-
|
|
960
|
-
{ key: "downArrow", meta: true, caption: "page", action: "pageDown", order: 0 },
|
|
961
|
-
{ key: "upArrow", ctrl: true, caption: "page", action: "pageUp", order: 0 },
|
|
962
|
-
{ key: "downArrow", ctrl: true, caption: "page", action: "pageDown", order: 0 },
|
|
963
|
-
{ key: "pageUp", caption: "page", action: "pageUp", order: 0 },
|
|
964
|
-
{ key: "pageDown", caption: "page", action: "pageDown", order: 0 }
|
|
992
|
+
...PAGE_SCROLL_KEY_BINDINGS
|
|
965
993
|
];
|
|
966
994
|
function ScrollableText({
|
|
967
995
|
ctx,
|
|
@@ -1194,6 +1222,8 @@ if (typeof window === "undefined") {
|
|
|
1194
1222
|
});
|
|
1195
1223
|
}
|
|
1196
1224
|
export {
|
|
1225
|
+
BAR_THUMB,
|
|
1226
|
+
BAR_TRACK,
|
|
1197
1227
|
Box5 as Box,
|
|
1198
1228
|
Divider,
|
|
1199
1229
|
FooterPresets,
|
|
@@ -1203,6 +1233,7 @@ export {
|
|
|
1203
1233
|
ListItem,
|
|
1204
1234
|
MultiColumnListComponent,
|
|
1205
1235
|
MultiColumnListWithPreviewComponent,
|
|
1236
|
+
PAGE_SCROLL_KEY_BINDINGS,
|
|
1206
1237
|
React2 as React,
|
|
1207
1238
|
ScreenBody,
|
|
1208
1239
|
ScreenContainer,
|