@nmakarov/cli-toolkit 0.80.0 → 0.81.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 +59 -26
- package/dist/cli-runner.cjs.map +1 -1
- package/dist/cli-runner.js +59 -26
- package/dist/cli-runner.js.map +1 -1
- package/dist/index.cjs +63 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +59 -26
- package/dist/index.js.map +1 -1
- package/dist/init.cjs +59 -26
- package/dist/init.cjs.map +1 -1
- package/dist/init.js +59 -26
- package/dist/init.js.map +1 -1
- package/dist/screen.cjs +59 -26
- package/dist/screen.cjs.map +1 -1
- package/dist/screen.js +55 -26
- package/dist/screen.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1018,6 +1018,30 @@ var init_ui_elements = __esm({
|
|
|
1018
1018
|
}
|
|
1019
1019
|
});
|
|
1020
1020
|
|
|
1021
|
+
// src/screen/follow-scroll.js
|
|
1022
|
+
function clampScroll(scrollTop, maxScroll) {
|
|
1023
|
+
const max = Math.max(0, Number(maxScroll) || 0);
|
|
1024
|
+
const top = Number(scrollTop) || 0;
|
|
1025
|
+
return Math.min(Math.max(0, top), max);
|
|
1026
|
+
}
|
|
1027
|
+
function isScrolledToBottom(scrollTop, maxScroll) {
|
|
1028
|
+
return clampScroll(scrollTop, maxScroll) >= Math.max(0, Number(maxScroll) || 0);
|
|
1029
|
+
}
|
|
1030
|
+
function nextScrollAfterUserMove(scrollTop, maxScroll, delta) {
|
|
1031
|
+
const next = clampScroll((Number(scrollTop) || 0) + (Number(delta) || 0), maxScroll);
|
|
1032
|
+
return { scrollTop: next, following: isScrolledToBottom(next, maxScroll) };
|
|
1033
|
+
}
|
|
1034
|
+
function nextScrollAfterContentChange({ following, scrollTop, maxScroll }) {
|
|
1035
|
+
const max = Math.max(0, Number(maxScroll) || 0);
|
|
1036
|
+
if (following) return { scrollTop: max, following: true };
|
|
1037
|
+
const next = clampScroll(scrollTop, max);
|
|
1038
|
+
return { scrollTop: next, following: isScrolledToBottom(next, max) };
|
|
1039
|
+
}
|
|
1040
|
+
var init_follow_scroll = __esm({
|
|
1041
|
+
"src/screen/follow-scroll.js"() {
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1021
1045
|
// src/screen/scrollable-text.js
|
|
1022
1046
|
function wrapTextLines(text, cols) {
|
|
1023
1047
|
const w = Math.max(1, Math.floor(Number(cols) || 1));
|
|
@@ -1050,9 +1074,11 @@ function ScrollableText({
|
|
|
1050
1074
|
showScrollbar = true,
|
|
1051
1075
|
showStatus = true,
|
|
1052
1076
|
bindKeys = true,
|
|
1053
|
-
header = null
|
|
1077
|
+
header = null,
|
|
1078
|
+
followBottom = false
|
|
1054
1079
|
}) {
|
|
1055
1080
|
const [scrollTop, setScrollTop] = (0, import_react5.useState)(0);
|
|
1081
|
+
const [following, setFollowing] = (0, import_react5.useState)(() => !!followBottom);
|
|
1056
1082
|
const [, bump] = (0, import_react5.useState)(0);
|
|
1057
1083
|
const termRows = process.stdout.rows || 24;
|
|
1058
1084
|
const viewportRows = Math.max(
|
|
@@ -1071,39 +1097,40 @@ function ScrollableText({
|
|
|
1071
1097
|
const clamped = Math.min(Math.max(0, scrollTop), maxScroll);
|
|
1072
1098
|
const visible = allLines.slice(clamped, clamped + viewportRows);
|
|
1073
1099
|
const bar = needsBar ? scrollbarGlyphs(viewportRows, allLines.length, clamped) : null;
|
|
1074
|
-
(0, import_react5.useEffect)(() => {
|
|
1075
|
-
setScrollTop((s) => Math.min(s, maxScroll));
|
|
1076
|
-
}, [maxScroll]);
|
|
1077
1100
|
const maxScrollRef = (0, import_react5.useRef)(maxScroll);
|
|
1078
1101
|
const pageSizeRef = (0, import_react5.useRef)(viewportRows);
|
|
1102
|
+
const scrollTopRef = (0, import_react5.useRef)(scrollTop);
|
|
1103
|
+
const followingRef = (0, import_react5.useRef)(following);
|
|
1079
1104
|
maxScrollRef.current = maxScroll;
|
|
1080
1105
|
pageSizeRef.current = viewportRows;
|
|
1106
|
+
scrollTopRef.current = scrollTop;
|
|
1107
|
+
followingRef.current = following;
|
|
1108
|
+
(0, import_react5.useEffect)(() => {
|
|
1109
|
+
const next = nextScrollAfterContentChange({
|
|
1110
|
+
following: followBottom && followingRef.current,
|
|
1111
|
+
scrollTop: scrollTopRef.current,
|
|
1112
|
+
maxScroll
|
|
1113
|
+
});
|
|
1114
|
+
if (next.scrollTop !== scrollTopRef.current) setScrollTop(next.scrollTop);
|
|
1115
|
+
if (followBottom && next.following !== followingRef.current) setFollowing(next.following);
|
|
1116
|
+
}, [maxScroll, followBottom]);
|
|
1117
|
+
const applyUserScroll = (delta) => {
|
|
1118
|
+
const next = nextScrollAfterUserMove(scrollTopRef.current, maxScrollRef.current, delta);
|
|
1119
|
+
setScrollTop(next.scrollTop);
|
|
1120
|
+
if (followBottom) setFollowing(next.following);
|
|
1121
|
+
bump((n) => n + 1);
|
|
1122
|
+
ctx?.update?.();
|
|
1123
|
+
};
|
|
1081
1124
|
(0, import_react5.useEffect)(() => {
|
|
1082
1125
|
if (!ctx || !bindKeys) return void 0;
|
|
1083
1126
|
ctx.setKeyBinding(SCROLL_KEYS);
|
|
1084
|
-
ctx.setAction("scrollUp", () =>
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
});
|
|
1089
|
-
ctx.setAction("scrollDown", () => {
|
|
1090
|
-
setScrollTop((s) => Math.min(maxScrollRef.current, s + 1));
|
|
1091
|
-
bump((n) => n + 1);
|
|
1092
|
-
ctx.update?.();
|
|
1093
|
-
});
|
|
1094
|
-
ctx.setAction("pageUp", () => {
|
|
1095
|
-
setScrollTop((s) => Math.max(0, s - pageSizeRef.current));
|
|
1096
|
-
bump((n) => n + 1);
|
|
1097
|
-
ctx.update?.();
|
|
1098
|
-
});
|
|
1099
|
-
ctx.setAction("pageDown", () => {
|
|
1100
|
-
setScrollTop((s) => Math.min(maxScrollRef.current, s + pageSizeRef.current));
|
|
1101
|
-
bump((n) => n + 1);
|
|
1102
|
-
ctx.update?.();
|
|
1103
|
-
});
|
|
1127
|
+
ctx.setAction("scrollUp", () => applyUserScroll(-1));
|
|
1128
|
+
ctx.setAction("scrollDown", () => applyUserScroll(1));
|
|
1129
|
+
ctx.setAction("pageUp", () => applyUserScroll(-pageSizeRef.current));
|
|
1130
|
+
ctx.setAction("pageDown", () => applyUserScroll(pageSizeRef.current));
|
|
1104
1131
|
return void 0;
|
|
1105
|
-
}, [ctx, bindKeys]);
|
|
1106
|
-
const status = allLines.length === 0 ? "empty" : `lines ${clamped + 1}-${Math.min(clamped + visible.length, allLines.length)} of ${allLines.length}` + (needsBar ? " \xB7 \u2325\u2191/\u2193 or PgUp/Dn page" : "");
|
|
1132
|
+
}, [ctx, bindKeys, followBottom]);
|
|
1133
|
+
const status = allLines.length === 0 ? "empty" : `lines ${clamped + 1}-${Math.min(clamped + visible.length, allLines.length)} of ${allLines.length}` + (needsBar ? " \xB7 \u2325\u2191/\u2193 or PgUp/Dn page" : "") + (followBottom && following ? " \xB7 follow" : followBottom ? " \xB7 follow off" : "");
|
|
1107
1134
|
const rowNodes = visible.map((line, i) => {
|
|
1108
1135
|
const body = padEndVisible(line, textWidth);
|
|
1109
1136
|
const glyph = bar ? bar[i] ?? BAR_TRACK : showScrollbar ? " " : "";
|
|
@@ -1143,6 +1170,7 @@ var init_scrollable_text = __esm({
|
|
|
1143
1170
|
import_ink5 = require("ink");
|
|
1144
1171
|
init_components();
|
|
1145
1172
|
init_scrollbar();
|
|
1173
|
+
init_follow_scroll();
|
|
1146
1174
|
init_scrollbar();
|
|
1147
1175
|
h5 = import_react5.createElement;
|
|
1148
1176
|
SCROLL_KEYS = [
|
|
@@ -1298,6 +1326,7 @@ var init_screen = __esm({
|
|
|
1298
1326
|
init_components();
|
|
1299
1327
|
init_ui_elements();
|
|
1300
1328
|
init_scrollable_text();
|
|
1329
|
+
init_follow_scroll();
|
|
1301
1330
|
init_scrollbar();
|
|
1302
1331
|
init_key_bindings();
|
|
1303
1332
|
init_utils();
|
|
@@ -1377,6 +1406,7 @@ __export(src_exports, {
|
|
|
1377
1406
|
buildDetailBreadcrumb: () => buildDetailBreadcrumb,
|
|
1378
1407
|
buildFooter: () => buildFooter,
|
|
1379
1408
|
bumpPatchVersion: () => bumpPatchVersion,
|
|
1409
|
+
clampScroll: () => clampScroll,
|
|
1380
1410
|
cloneRepo: () => cloneRepo,
|
|
1381
1411
|
coerceRuntimeValue: () => coerceRuntimeValue,
|
|
1382
1412
|
controlLaneTaskNames: () => controlLaneTaskNames,
|
|
@@ -1414,6 +1444,7 @@ __export(src_exports, {
|
|
|
1414
1444
|
ipcFileLogsTableNameForSourceResource: () => ipcFileLogsTableNameForSourceResource,
|
|
1415
1445
|
isFreshOnline: () => isFreshOnline,
|
|
1416
1446
|
isPidAlive: () => isPidAlive,
|
|
1447
|
+
isScrolledToBottom: () => isScrolledToBottom,
|
|
1417
1448
|
joiEdateType: () => joiEdateType,
|
|
1418
1449
|
joiStringArrayType: () => joiStringArrayType,
|
|
1419
1450
|
listAliveRunnerHeartbeats: () => listServicesRegistry,
|
|
@@ -1427,6 +1458,8 @@ __export(src_exports, {
|
|
|
1427
1458
|
memo: () => import_react6.memo,
|
|
1428
1459
|
mergeAllowedTasksWithServiceTasks: () => mergeAllowedTasksWithServiceTasks,
|
|
1429
1460
|
mergeRuntimeParamSpecs: () => mergeRuntimeParamSpecs,
|
|
1461
|
+
nextScrollAfterContentChange: () => nextScrollAfterContentChange,
|
|
1462
|
+
nextScrollAfterUserMove: () => nextScrollAfterUserMove,
|
|
1430
1463
|
nextTimeMatch: () => nextTimeMatch,
|
|
1431
1464
|
normalizeAllowedTasks: () => normalizeAllowedTasks,
|
|
1432
1465
|
npmEnv: () => npmEnv,
|
|
@@ -10351,6 +10384,7 @@ var TasksManager = class _TasksManager {
|
|
|
10351
10384
|
buildDetailBreadcrumb,
|
|
10352
10385
|
buildFooter,
|
|
10353
10386
|
bumpPatchVersion,
|
|
10387
|
+
clampScroll,
|
|
10354
10388
|
cloneRepo,
|
|
10355
10389
|
coerceRuntimeValue,
|
|
10356
10390
|
controlLaneTaskNames,
|
|
@@ -10388,6 +10422,7 @@ var TasksManager = class _TasksManager {
|
|
|
10388
10422
|
ipcFileLogsTableNameForSourceResource,
|
|
10389
10423
|
isFreshOnline,
|
|
10390
10424
|
isPidAlive,
|
|
10425
|
+
isScrolledToBottom,
|
|
10391
10426
|
joiEdateType,
|
|
10392
10427
|
joiStringArrayType,
|
|
10393
10428
|
listAliveRunnerHeartbeats,
|
|
@@ -10401,6 +10436,8 @@ var TasksManager = class _TasksManager {
|
|
|
10401
10436
|
memo,
|
|
10402
10437
|
mergeAllowedTasksWithServiceTasks,
|
|
10403
10438
|
mergeRuntimeParamSpecs,
|
|
10439
|
+
nextScrollAfterContentChange,
|
|
10440
|
+
nextScrollAfterUserMove,
|
|
10404
10441
|
nextTimeMatch,
|
|
10405
10442
|
normalizeAllowedTasks,
|
|
10406
10443
|
npmEnv,
|