@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/cli-runner.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 = [
|
|
@@ -1311,10 +1339,14 @@ __export(screen_exports, {
|
|
|
1311
1339
|
buildBreadcrumb: () => buildBreadcrumb,
|
|
1312
1340
|
buildDetailBreadcrumb: () => buildDetailBreadcrumb,
|
|
1313
1341
|
buildFooter: () => buildFooter,
|
|
1342
|
+
clampScroll: () => clampScroll,
|
|
1314
1343
|
formatBindingKey: () => formatBindingKey,
|
|
1315
1344
|
h: () => import_react6.createElement,
|
|
1345
|
+
isScrolledToBottom: () => isScrolledToBottom,
|
|
1316
1346
|
load: () => load,
|
|
1317
1347
|
memo: () => import_react6.memo,
|
|
1348
|
+
nextScrollAfterContentChange: () => nextScrollAfterContentChange,
|
|
1349
|
+
nextScrollAfterUserMove: () => nextScrollAfterUserMove,
|
|
1318
1350
|
organizeFooterMessages: () => organizeFooterMessages,
|
|
1319
1351
|
scrollbarGlyphs: () => scrollbarGlyphs,
|
|
1320
1352
|
showListScreen: () => showListScreen,
|
|
@@ -1351,6 +1383,7 @@ var init_screen = __esm({
|
|
|
1351
1383
|
init_components();
|
|
1352
1384
|
init_ui_elements();
|
|
1353
1385
|
init_scrollable_text();
|
|
1386
|
+
init_follow_scroll();
|
|
1354
1387
|
init_scrollbar();
|
|
1355
1388
|
init_key_bindings();
|
|
1356
1389
|
init_utils();
|