@kud/gh-ink 0.52.0 → 0.53.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/index.d.ts +20 -12
- package/dist/index.js +95 -58
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -70,6 +70,14 @@ type Sidebar = {
|
|
|
70
70
|
/** Heading for the rail. The host's vocabulary, never ours. */
|
|
71
71
|
title: string;
|
|
72
72
|
rows: SidebarRow[];
|
|
73
|
+
/**
|
|
74
|
+
* What to call `live` on screen, in the host's words — `4 on board` and `off
|
|
75
|
+
* board` on a ticket cockpit, say. Takes the number rather than a word pair
|
|
76
|
+
* because the two states need not share a sentence shape: "off board" has no
|
|
77
|
+
* N in it. `live` itself stays a number, so the absent-draws-nothing contract
|
|
78
|
+
* and the host's sort are untouched.
|
|
79
|
+
*/
|
|
80
|
+
liveLabel?: (live: number) => string;
|
|
73
81
|
};
|
|
74
82
|
/**
|
|
75
83
|
* The rail's width, INCLUDING its rule and padding. Exported because the list
|
|
@@ -86,15 +94,13 @@ type Sidebar = {
|
|
|
86
94
|
*/
|
|
87
95
|
declare const SIDEBAR_COLS = 52;
|
|
88
96
|
/**
|
|
89
|
-
* The
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* number — and a zero is printed wherever it was counted, because "nothing is
|
|
95
|
-
* moving" is exactly the thing a roadmap is read to notice.
|
|
97
|
+
* The plain-text facts of a row, for a host or a test that wants them as one
|
|
98
|
+
* string: how far through, then how much is moving. Either half may be missing
|
|
99
|
+
* and the other still worth saying, and a zero is printed wherever it was
|
|
100
|
+
* counted, because "nothing is moving" is exactly the thing a roadmap is read
|
|
101
|
+
* to notice.
|
|
96
102
|
*/
|
|
97
|
-
declare const counts: (row: SidebarRow) => string;
|
|
103
|
+
declare const counts: (row: SidebarRow, liveLabel?: (live: number) => string) => string;
|
|
98
104
|
/**
|
|
99
105
|
* How many rows fit in `height` — one fewer than would physically fit whenever
|
|
100
106
|
* that means anything is left over, to buy the line that says so.
|
|
@@ -108,10 +114,12 @@ declare const railCapacity: (height: number, rows: number) => number;
|
|
|
108
114
|
/**
|
|
109
115
|
* A right-hand rail of initiatives, standing beside the list.
|
|
110
116
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
117
|
+
* Label first, facts beneath, because a roadmap is read by name: nobody thinks
|
|
118
|
+
* "ACC-11312", they think "the OpenSearch migration". So the label is the
|
|
119
|
+
* bright line and the key drops to the facts line as what it is — a reference
|
|
120
|
+
* you follow, in the secondary tier. Two lines rather than one because both are
|
|
121
|
+
* load-bearing and neither survives the other being cut: words with no key
|
|
122
|
+
* cannot be opened, and a key with no words cannot be read at a glance.
|
|
115
123
|
*
|
|
116
124
|
* Presentational, like every other row renderer here: it DRAWS a cursor but does
|
|
117
125
|
* not own one, and it never calls `useInput`. Where the cursor is, and whether
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React2, { createContext, useState, useRef, useEffect, useMemo, useContext } from 'react';
|
|
2
|
-
import { useWindowSize, useInput, Text, Box } from 'ink';
|
|
3
|
-
import { colors, ScrollView, TextInput, LoadingScreen, StatusMessage, FooterHints, useListCursor, Tabs, pillWidth, Pill } from '@kud/ink-ui';
|
|
2
|
+
import { useWindowSize, useInput, Text, Box, useApp } from 'ink';
|
|
3
|
+
import { colors, ScrollView, TextInput, LoadingScreen, ProgressBar, StatusMessage, FooterHints, useListCursor, Tabs, pillWidth, Pill } from '@kud/ink-ui';
|
|
4
4
|
import { isPassCheck, isFailCheck, isInconclusiveCheck, resolveThread, unresolveThread, replyToThread, rerunFailedRun, mergePr, reRequestReviewer } from '@kud/gh';
|
|
5
5
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
6
6
|
import { $ } from 'zx';
|
|
@@ -585,40 +585,75 @@ var HealthPanel = ({
|
|
|
585
585
|
] }) }) : note ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: colors.success, children: " " + note }) }) : null
|
|
586
586
|
] });
|
|
587
587
|
};
|
|
588
|
-
var ACCENT = "#FF8700";
|
|
589
588
|
var SIDEBAR_COLS = 52;
|
|
590
589
|
var RULE = 1;
|
|
591
590
|
var PAD = 2;
|
|
592
591
|
var CONTENT = SIDEBAR_COLS - RULE - PAD;
|
|
593
|
-
var
|
|
594
|
-
var
|
|
595
|
-
var
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
var
|
|
592
|
+
var MARKS = 4;
|
|
593
|
+
var LABEL_COLS = CONTENT - MARKS;
|
|
594
|
+
var FACTS_INDENT = 6;
|
|
595
|
+
var KEY_COLS = 10;
|
|
596
|
+
var BAR_COLS = 10;
|
|
597
|
+
var FRACTION_COLS = 5;
|
|
598
|
+
var GUTTER = " ";
|
|
599
|
+
var LIVE_COLS = CONTENT - FACTS_INDENT - KEY_COLS - BAR_COLS - FRACTION_COLS - GUTTER.length * 3;
|
|
600
|
+
var defaultLiveLabel = (live) => live === 0 ? "nothing live" : `${live} live`;
|
|
601
|
+
var fractionOf = (row) => row.done !== void 0 && row.total !== void 0 ? `${row.done}/${row.total}` : "";
|
|
602
|
+
var counts = (row, liveLabel = defaultLiveLabel) => [fractionOf(row), row.live !== void 0 ? liveLabel(row.live) : ""].filter(Boolean).join(" \xB7 ");
|
|
603
|
+
var DANGLING = /[\s:;,.\-—–(\[{]+$/u;
|
|
604
|
+
var truncateWords = (text, max) => {
|
|
605
|
+
const chars = [...text];
|
|
606
|
+
if (chars.length <= max) return text;
|
|
607
|
+
const room = Math.max(0, max - 1);
|
|
608
|
+
const hard = chars.slice(0, room).join("");
|
|
609
|
+
const boundary = chars[room] === " " ? room : hard.lastIndexOf(" ");
|
|
610
|
+
const soft = boundary >= Math.floor(room * 0.6) ? hard.slice(0, boundary) : hard;
|
|
611
|
+
return soft.replace(DANGLING, "") + "\u2026";
|
|
612
|
+
};
|
|
600
613
|
var ROW_LINES = 3;
|
|
601
614
|
var HEADING_LINES = 2;
|
|
602
615
|
var railCapacity = (height, rows) => {
|
|
603
616
|
const fits = Math.max(0, Math.floor((height - HEADING_LINES) / ROW_LINES));
|
|
604
617
|
return fits >= rows ? rows : Math.max(0, fits - 1);
|
|
605
618
|
};
|
|
619
|
+
var percentOf = (done, total) => total === 0 ? 0 : Math.round(done / total * 100);
|
|
620
|
+
var Progress = ({ row }) => {
|
|
621
|
+
const fraction = fractionOf(row);
|
|
622
|
+
const bar = row.done !== void 0 && row.total !== void 0 && row.total > 0 ? /* @__PURE__ */ jsx(
|
|
623
|
+
ProgressBar,
|
|
624
|
+
{
|
|
625
|
+
value: percentOf(row.done, row.total),
|
|
626
|
+
width: BAR_COLS,
|
|
627
|
+
color: colors.secondary
|
|
628
|
+
}
|
|
629
|
+
) : /* @__PURE__ */ jsx(Text, { children: " ".repeat(BAR_COLS) });
|
|
630
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
631
|
+
bar,
|
|
632
|
+
/* @__PURE__ */ jsx(Text, { color: colors.secondary, children: GUTTER + fraction.padStart(FRACTION_COLS) })
|
|
633
|
+
] });
|
|
634
|
+
};
|
|
606
635
|
var SidePanel = ({
|
|
607
636
|
sidebar,
|
|
608
637
|
height,
|
|
609
638
|
focused = false,
|
|
610
639
|
cursor = 0
|
|
611
640
|
}) => {
|
|
641
|
+
const liveLabel = sidebar.liveLabel ?? defaultLiveLabel;
|
|
612
642
|
const capacity = height === void 0 ? sidebar.rows.length : railCapacity(height, sidebar.rows.length);
|
|
613
643
|
const start = focused && cursor >= capacity ? Math.min(cursor - capacity + 1, sidebar.rows.length - capacity) : 0;
|
|
614
644
|
const shown = sidebar.rows.slice(start, start + capacity);
|
|
615
645
|
const hidden = sidebar.rows.length - shown.length;
|
|
646
|
+
const focus = focused ? " \u25CF focus" : "";
|
|
647
|
+
const rule = "\u254C".repeat(
|
|
648
|
+
Math.max(0, CONTENT - [...sidebar.title].length - focus.length - 1)
|
|
649
|
+
);
|
|
616
650
|
return (
|
|
617
651
|
// A rule down the left rather than a full box: the rail's other three edges
|
|
618
652
|
// already have the frame's border a column or two away, and a second
|
|
619
653
|
// rectangle inside the first reads as a nested panel — something you could
|
|
620
654
|
// focus and act on, which this cannot be. One line is the whole claim: what
|
|
621
|
-
// is left of it is the list, what is right of it is not.
|
|
655
|
+
// is left of it is the list, what is right of it is not. In the frame's own
|
|
656
|
+
// colour and not dimmed, so the two rules read as one hierarchy.
|
|
622
657
|
/* @__PURE__ */ jsxs(
|
|
623
658
|
Box,
|
|
624
659
|
{
|
|
@@ -627,31 +662,33 @@ var SidePanel = ({
|
|
|
627
662
|
flexShrink: 0,
|
|
628
663
|
height,
|
|
629
664
|
borderStyle: "single",
|
|
630
|
-
borderColor:
|
|
631
|
-
borderDimColor: true,
|
|
665
|
+
borderColor: colors.muted,
|
|
632
666
|
borderTop: false,
|
|
633
667
|
borderRight: false,
|
|
634
668
|
borderBottom: false,
|
|
635
669
|
paddingLeft: PAD,
|
|
636
670
|
children: [
|
|
637
671
|
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
638
|
-
/* @__PURE__ */ jsx(Text, { color: ACCENT, bold: true, children: "\xBB " }),
|
|
639
672
|
/* @__PURE__ */ jsx(Text, { bold: true, children: sidebar.title }),
|
|
640
|
-
focused ? /* @__PURE__ */ jsx(Text, { color:
|
|
673
|
+
focused ? /* @__PURE__ */ jsx(Text, { color: colors.accent, children: focus }) : null,
|
|
674
|
+
/* @__PURE__ */ jsx(Text, { color: colors.info, dimColor: true, children: ` ${rule}` })
|
|
641
675
|
] }),
|
|
642
|
-
sidebar.rows.length === 0 ? /* @__PURE__ */ jsx(Box, { paddingLeft:
|
|
676
|
+
sidebar.rows.length === 0 ? /* @__PURE__ */ jsx(Box, { paddingLeft: MARKS, children: /* @__PURE__ */ jsx(Text, { color: colors.muted, children: "nothing open" }) }) : shown.map((row, i) => {
|
|
643
677
|
const active = focused && start + i === cursor;
|
|
644
678
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
645
679
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
646
|
-
/* @__PURE__ */ jsx(Text, { color:
|
|
647
|
-
/* @__PURE__ */ jsx(Text, { color:
|
|
648
|
-
/* @__PURE__ */ jsx(Text, {
|
|
649
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${counts(row)}` })
|
|
680
|
+
/* @__PURE__ */ jsx(Text, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
681
|
+
/* @__PURE__ */ jsx(Text, { color: colors.accent, bold: true, children: row.wantsYou ? "\u2190 " : " " }),
|
|
682
|
+
/* @__PURE__ */ jsx(Text, { bold: active, children: truncateWords(row.label, LABEL_COLS) })
|
|
650
683
|
] }),
|
|
651
|
-
/* @__PURE__ */
|
|
684
|
+
/* @__PURE__ */ jsxs(Box, { paddingLeft: FACTS_INDENT, children: [
|
|
685
|
+
/* @__PURE__ */ jsx(Text, { color: colors.secondary, children: row.key.padEnd(KEY_COLS) + GUTTER }),
|
|
686
|
+
/* @__PURE__ */ jsx(Progress, { row }),
|
|
687
|
+
/* @__PURE__ */ jsx(Text, { children: GUTTER + (row.live !== void 0 ? liveLabel(row.live).slice(0, LIVE_COLS) : "") })
|
|
688
|
+
] })
|
|
652
689
|
] }, row.key);
|
|
653
690
|
}),
|
|
654
|
-
hidden > 0 ? /* @__PURE__ */ jsx(Box, { paddingLeft:
|
|
691
|
+
hidden > 0 ? /* @__PURE__ */ jsx(Box, { paddingLeft: MARKS, children: /* @__PURE__ */ jsx(Text, { color: colors.muted, children: `+${hidden} more` }) }) : null
|
|
655
692
|
]
|
|
656
693
|
}
|
|
657
694
|
)
|
|
@@ -1135,7 +1172,7 @@ var withHeaders = (items, idx) => {
|
|
|
1135
1172
|
start--;
|
|
1136
1173
|
return start;
|
|
1137
1174
|
};
|
|
1138
|
-
var
|
|
1175
|
+
var truncate = (str, max) => {
|
|
1139
1176
|
if (str.length <= max) return str;
|
|
1140
1177
|
const half = Math.floor((max - 1) / 2);
|
|
1141
1178
|
return `${str.slice(0, half)}\u2026${str.slice(-half)}`;
|
|
@@ -1723,18 +1760,18 @@ var InboxHeader = ({
|
|
|
1723
1760
|
const userSeg = loading || quiet ? "" : `@${login} `;
|
|
1724
1761
|
const workLabel = scopeLabel ? ` ${scopeLabel} ` : "";
|
|
1725
1762
|
const budgetSeg = budgetLabel ? budgetLabel + " " : "";
|
|
1726
|
-
const [statusText, statusColor] = hasPending ? [`\u25CF ${pendingSummary || "new"} \xB7 r apply`,
|
|
1763
|
+
const [statusText, statusColor] = hasPending ? [`\u25CF ${pendingSummary || "new"} \xB7 r apply`, colors.accent] : refreshing ? ["\u21BB refreshing\u2026", "cyan"] : appliedSummary ? [`\u25C9 ${appliedSummary}`, colors.accent] : fetchedAt ? [`updated ${agoText(fetchedAt)}`, void 0] : ["", void 0];
|
|
1727
1764
|
const statusSeg = statusText ? statusText + " " : "";
|
|
1728
1765
|
const fill = Math.max(
|
|
1729
1766
|
4,
|
|
1730
1767
|
COLS - brand.length - countSeg.length - userSeg.length - workLabel.length - budgetSeg.length - statusSeg.length
|
|
1731
1768
|
);
|
|
1732
1769
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1733
|
-
/* @__PURE__ */ jsx(Text3, { color:
|
|
1770
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: true, children: brand }),
|
|
1734
1771
|
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: countSeg }),
|
|
1735
1772
|
userSeg ? /* @__PURE__ */ jsx(Text3, { children: userSeg }) : null,
|
|
1736
1773
|
scopeLabel ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: workLabel }) : null,
|
|
1737
|
-
budgetLabel ? /* @__PURE__ */ jsx(Text3, { bold: true, color: budgetCritical ? "#FF5F5F" :
|
|
1774
|
+
budgetLabel ? /* @__PURE__ */ jsx(Text3, { bold: true, color: budgetCritical ? "#FF5F5F" : colors.accent, children: budgetSeg }) : null,
|
|
1738
1775
|
statusText ? /* @__PURE__ */ jsx(
|
|
1739
1776
|
Text3,
|
|
1740
1777
|
{
|
|
@@ -1783,7 +1820,7 @@ var CiStatusLine = ({
|
|
|
1783
1820
|
/* @__PURE__ */ jsx(Text3, { color, bold: true, children: "\u25CF " }),
|
|
1784
1821
|
/* @__PURE__ */ jsx(Text3, { bold: true, children: status.job }),
|
|
1785
1822
|
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: " " + label }),
|
|
1786
|
-
/* @__PURE__ */ jsx(Text3, { color:
|
|
1823
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, children: " #" + status.buildNumber }),
|
|
1787
1824
|
status.age ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: " " + status.age }) : null
|
|
1788
1825
|
] });
|
|
1789
1826
|
};
|
|
@@ -1825,13 +1862,13 @@ var TRANSIT_IN_FRAMES = ["\xB7", "\u25CB", "\u25CE", "\u25C9"];
|
|
|
1825
1862
|
var TRANSIT_COLOUR = {
|
|
1826
1863
|
in: "#3FB950",
|
|
1827
1864
|
out: "#8B949E",
|
|
1828
|
-
changed:
|
|
1865
|
+
changed: colors.accent,
|
|
1829
1866
|
// A move is neither an arrival nor a departure, so it takes the colour of the
|
|
1830
1867
|
// third thing that can happen to a row you already had: it changed. Both ends
|
|
1831
1868
|
// of one move wear the same colour and the same word, which is what lets you
|
|
1832
1869
|
// recognise the row you just watched leave when you land on the tab it went to.
|
|
1833
|
-
"moved-in":
|
|
1834
|
-
"moved-out":
|
|
1870
|
+
"moved-in": colors.accent,
|
|
1871
|
+
"moved-out": colors.accent
|
|
1835
1872
|
};
|
|
1836
1873
|
var TRANSIT_LABEL = {
|
|
1837
1874
|
out: "gone"};
|
|
@@ -1863,7 +1900,7 @@ var ItemRow = ({
|
|
|
1863
1900
|
return /* @__PURE__ */ jsx(RepoHeaderRow, { repo: item.repo, gap: gap ?? false, active });
|
|
1864
1901
|
if (item.kind === "subgroup-header")
|
|
1865
1902
|
return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
|
|
1866
|
-
/* @__PURE__ */ jsx(Text3, { color:
|
|
1903
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: true, children: " \xBB " }),
|
|
1867
1904
|
/* @__PURE__ */ jsx(Text3, { bold: true, children: item.label })
|
|
1868
1905
|
] });
|
|
1869
1906
|
if (item.kind === "show-more")
|
|
@@ -1892,14 +1929,14 @@ var ItemRow = ({
|
|
|
1892
1929
|
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: prefix }),
|
|
1893
1930
|
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: parent ? "\u252C " : " " }),
|
|
1894
1931
|
/* @__PURE__ */ jsx(Text3, { bold: true, color: transient ? TRANSIT_COLOUR[transient] : void 0, children: transitIcon + " " }),
|
|
1895
|
-
/* @__PURE__ */ jsx(Text3, { color:
|
|
1932
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: active, children: item.key + " " }),
|
|
1896
1933
|
/* @__PURE__ */ jsx(
|
|
1897
1934
|
Text3,
|
|
1898
1935
|
{
|
|
1899
1936
|
bold: active || !!transient && isArrival(transient),
|
|
1900
1937
|
dimColor: !!transient && isDeparture(transient),
|
|
1901
1938
|
strikethrough: transient === "out",
|
|
1902
|
-
children:
|
|
1939
|
+
children: truncate(item.summary, titleMax2)
|
|
1903
1940
|
}
|
|
1904
1941
|
),
|
|
1905
1942
|
item.pill && !backdropped ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -1925,7 +1962,7 @@ var ItemRow = ({
|
|
|
1925
1962
|
const icon = merged ? MERGED_FRAMES[sparkFrame % MERGED_FRAMES.length] : transient && isDeparture(transient) ? TRANSIT_OUT_FRAMES[rampAt(TRANSIT_OUT_FRAMES.length)] : transient && isArrival(transient) ? TRANSIT_IN_FRAMES[rampAt(TRANSIT_IN_FRAMES.length)] : healthIcon;
|
|
1926
1963
|
const color = merged ? MERGED_COLOUR : transient ? TRANSIT_COLOUR[transient] : healthColor2;
|
|
1927
1964
|
const spokeLast = !!login && !!item.lastActor && item.lastActor === login;
|
|
1928
|
-
const [turnIcon, turnColor] = item.pinned ? [PIN_MARK,
|
|
1965
|
+
const [turnIcon, turnColor] = item.pinned ? [PIN_MARK, colors.accent] : !login || !item.lastActor ? [" ", "white"] : spokeLast ? ["\u2192", colors.secondary] : ["\u2190", colors.accent];
|
|
1929
1966
|
const numStr = `#${item.number}`.padEnd(7);
|
|
1930
1967
|
const showAuthor = !!item.author && item.author !== login;
|
|
1931
1968
|
const sizeLabel = sizeOf(item);
|
|
@@ -1958,7 +1995,7 @@ var ItemRow = ({
|
|
|
1958
1995
|
if (next.length <= LABEL_CELL_MAX) fitted.push(name);
|
|
1959
1996
|
}
|
|
1960
1997
|
if (fitted.length === 0) {
|
|
1961
|
-
return `\uF02B ${
|
|
1998
|
+
return `\uF02B ${truncate(shown[0], LABEL_CELL_MAX)}`;
|
|
1962
1999
|
}
|
|
1963
2000
|
return `\uF02B ${fitted.join(", ")}`;
|
|
1964
2001
|
};
|
|
@@ -1994,14 +2031,14 @@ var ItemRow = ({
|
|
|
1994
2031
|
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: prefix }),
|
|
1995
2032
|
/* @__PURE__ */ jsx(Text3, { color, bold: true, children: icon + " " }),
|
|
1996
2033
|
/* @__PURE__ */ jsx(Text3, { color: turnColor, bold: turnIcon === "\u2190", children: turnIcon + " " }),
|
|
1997
|
-
/* @__PURE__ */ jsx(Text3, { color:
|
|
2034
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, children: numStr }),
|
|
1998
2035
|
/* @__PURE__ */ jsx(
|
|
1999
2036
|
Text3,
|
|
2000
2037
|
{
|
|
2001
2038
|
bold: active || !!transient && isArrival(transient),
|
|
2002
2039
|
dimColor: !!transient && isDeparture(transient),
|
|
2003
2040
|
strikethrough: transient === "out",
|
|
2004
|
-
children:
|
|
2041
|
+
children: truncate(item.title, titleMax) + " "
|
|
2005
2042
|
}
|
|
2006
2043
|
),
|
|
2007
2044
|
labelLabel ? /* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: labelLabel + " " }) : null,
|
|
@@ -2012,7 +2049,7 @@ var ItemRow = ({
|
|
|
2012
2049
|
" ",
|
|
2013
2050
|
/* @__PURE__ */ jsx(Text3, { color: colors.error, children: sizeParts.removed })
|
|
2014
2051
|
] }) : null,
|
|
2015
|
-
unresolvedLabel && !givingUp.threads ? /* @__PURE__ */ jsx(Text3, { bold: !spokeLast, color: spokeLast ? colors.secondary :
|
|
2052
|
+
unresolvedLabel && !givingUp.threads ? /* @__PURE__ */ jsx(Text3, { bold: !spokeLast, color: spokeLast ? colors.secondary : colors.accent, children: " " + unresolvedLabel }) : null,
|
|
2016
2053
|
showAuthor && !givingUp.author ? /* @__PURE__ */ jsx(Text3, { dimColor: true, italic: true, children: " by " + item.author }) : null,
|
|
2017
2054
|
ageLabel && !givingUp.age ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: " " + ageLabel }) : null,
|
|
2018
2055
|
mergedLabel && !backdropped ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -2082,7 +2119,7 @@ var ActionMenu = ({
|
|
|
2082
2119
|
);
|
|
2083
2120
|
};
|
|
2084
2121
|
var TURN_LEGEND = [
|
|
2085
|
-
["\u2190",
|
|
2122
|
+
["\u2190", colors.accent, "They spoke last \xB7 your turn"],
|
|
2086
2123
|
["\u2192", colors.secondary, "You spoke last \xB7 waiting on them"]
|
|
2087
2124
|
];
|
|
2088
2125
|
var CELL_GUTTER = 2;
|
|
@@ -2187,7 +2224,7 @@ var HelpModal = ({
|
|
|
2187
2224
|
})),
|
|
2188
2225
|
{
|
|
2189
2226
|
cell: "\uF086",
|
|
2190
|
-
color:
|
|
2227
|
+
color: colors.accent,
|
|
2191
2228
|
bold: true,
|
|
2192
2229
|
label: "Open-thread count"
|
|
2193
2230
|
}
|
|
@@ -2200,7 +2237,7 @@ var HelpModal = ({
|
|
|
2200
2237
|
title: "Tabs",
|
|
2201
2238
|
rows: tabHelp.map(([tab, meaning]) => ({
|
|
2202
2239
|
cell: tab,
|
|
2203
|
-
color:
|
|
2240
|
+
color: colors.accent,
|
|
2204
2241
|
label: meaning
|
|
2205
2242
|
}))
|
|
2206
2243
|
}
|
|
@@ -2275,7 +2312,7 @@ var ExplainModal = ({ item, login }) => /* @__PURE__ */ jsxs(
|
|
|
2275
2312
|
paddingX: 1,
|
|
2276
2313
|
width: Math.min(COLS, 78),
|
|
2277
2314
|
children: [
|
|
2278
|
-
/* @__PURE__ */ jsx(Text3, { color:
|
|
2315
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: true, children: `#${item.number} \xB7 ${item.repo}` }),
|
|
2279
2316
|
/* @__PURE__ */ jsx(Text3, { children: item.title }),
|
|
2280
2317
|
explainItem(item, login).map((section) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
2281
2318
|
/* @__PURE__ */ jsx(Text3, { bold: true, dimColor: true, children: section.heading }),
|
|
@@ -2367,6 +2404,7 @@ var BrowseScreen = ({
|
|
|
2367
2404
|
sidebar
|
|
2368
2405
|
}) => {
|
|
2369
2406
|
const { rows } = useWindowSize();
|
|
2407
|
+
const { exit } = useApp();
|
|
2370
2408
|
const applyWork = (secs) => origin ? filterByOrigin(secs, origin.show, origin.match, login) : secs;
|
|
2371
2409
|
const initialSections = applyWork(sections);
|
|
2372
2410
|
const [localSections, setLocalSections] = useState(initialSections);
|
|
@@ -2576,11 +2614,11 @@ var BrowseScreen = ({
|
|
|
2576
2614
|
if (key.ctrl || key.meta) return;
|
|
2577
2615
|
if (help) {
|
|
2578
2616
|
if (helpRange.max > 0) {
|
|
2579
|
-
const
|
|
2580
|
-
if (key.upArrow) return
|
|
2581
|
-
if (key.downArrow) return
|
|
2582
|
-
if (key.pageUp) return
|
|
2583
|
-
if (key.pageDown) return
|
|
2617
|
+
const step2 = (n) => setHelpScroll((s) => Math.min(helpRange.max, Math.max(0, s + n)));
|
|
2618
|
+
if (key.upArrow) return step2(-1);
|
|
2619
|
+
if (key.downArrow) return step2(1);
|
|
2620
|
+
if (key.pageUp) return step2(-helpRange.page);
|
|
2621
|
+
if (key.pageDown) return step2(helpRange.page);
|
|
2584
2622
|
}
|
|
2585
2623
|
setHelp(false);
|
|
2586
2624
|
return;
|
|
@@ -2690,14 +2728,12 @@ var BrowseScreen = ({
|
|
|
2690
2728
|
setCursors((p) => ({ ...p, [activeId]: next }));
|
|
2691
2729
|
setViewStarts((p) => ({ ...p, [activeId]: newVs }));
|
|
2692
2730
|
}
|
|
2693
|
-
|
|
2694
|
-
if (
|
|
2695
|
-
setTabIdx((i) => Math.min(localSections.length - 1, i + 1));
|
|
2696
|
-
if (key.tab)
|
|
2731
|
+
const step = key.leftArrow || key.tab && key.shift ? -1 : key.rightArrow || key.tab ? 1 : 0;
|
|
2732
|
+
if (step !== 0)
|
|
2697
2733
|
setTabIdx(
|
|
2698
|
-
(i) => (i +
|
|
2734
|
+
(i) => (i + step + localSections.length) % localSections.length
|
|
2699
2735
|
);
|
|
2700
|
-
if (input === "q")
|
|
2736
|
+
if (input === "q") exit();
|
|
2701
2737
|
if (input === "r") {
|
|
2702
2738
|
onRefresh?.();
|
|
2703
2739
|
return;
|
|
@@ -3010,7 +3046,7 @@ var BrowseScreen = ({
|
|
|
3010
3046
|
),
|
|
3011
3047
|
ciStatusState ? /* @__PURE__ */ jsx(CiStatusLine, { state: ciStatusState, job: ciJob }) : null,
|
|
3012
3048
|
skippedForBudget ? /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
3013
|
-
/* @__PURE__ */ jsx(Text3, { bold: true, color:
|
|
3049
|
+
/* @__PURE__ */ jsx(Text3, { bold: true, color: colors.accent, children: " \u26A1 auto-refresh paused to save API budget" }),
|
|
3014
3050
|
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: " r refreshes anyway" })
|
|
3015
3051
|
] }) : null,
|
|
3016
3052
|
/* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(
|
|
@@ -3042,7 +3078,7 @@ var BrowseScreen = ({
|
|
|
3042
3078
|
s.id,
|
|
3043
3079
|
pulseSettled ? PULSE_SETTLED_FRAME : sparkFrame
|
|
3044
3080
|
),
|
|
3045
|
-
markerColor:
|
|
3081
|
+
markerColor: colors.accent
|
|
3046
3082
|
}))
|
|
3047
3083
|
}
|
|
3048
3084
|
) }),
|
|
@@ -3052,7 +3088,7 @@ var BrowseScreen = ({
|
|
|
3052
3088
|
searchInput ? /* @__PURE__ */ jsx(Text3, { color: "cyan", children: "\u258F" }) : null,
|
|
3053
3089
|
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` ${matchCount} match${matchCount !== 1 ? "es" : ""}${searchInput ? " \u21B5 accept \xB7 esc clear" : " esc clear"}` })
|
|
3054
3090
|
] }) : repoFilter.size > 0 ? /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
3055
|
-
/* @__PURE__ */ jsx(Text3, { color:
|
|
3091
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, children: " \u25C9 " }),
|
|
3056
3092
|
/* @__PURE__ */ jsx(Text3, { children: `${repoFilter.size} repo${repoFilter.size !== 1 ? "s" : ""}` }),
|
|
3057
3093
|
/* @__PURE__ */ jsx(Text3, { dimColor: true, children: " f edit \xB7 esc clear" })
|
|
3058
3094
|
] }) : null,
|
|
@@ -3132,8 +3168,9 @@ var NoRowsScreen = ({
|
|
|
3132
3168
|
detail,
|
|
3133
3169
|
onRetry
|
|
3134
3170
|
}) => {
|
|
3171
|
+
const { exit } = useApp();
|
|
3135
3172
|
useInput((input) => {
|
|
3136
|
-
if (input === "q")
|
|
3173
|
+
if (input === "q") exit();
|
|
3137
3174
|
if (input === "r") onRetry();
|
|
3138
3175
|
});
|
|
3139
3176
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
@@ -3594,4 +3631,4 @@ var matchesFilter = (repo, filter) => {
|
|
|
3594
3631
|
};
|
|
3595
3632
|
var parsePatterns = (value) => value.split(",").map((p) => p.trim()).filter(Boolean);
|
|
3596
3633
|
|
|
3597
|
-
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, SIDEBAR_COLS, SidePanel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, railCapacity, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, toCiStatusState,
|
|
3634
|
+
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, SIDEBAR_COLS, SidePanel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, railCapacity, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, toCiStatusState, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kud/gh-ink",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.53.0",
|
|
4
4
|
"description": "Ink components for rendering GitHub PR review comments and health — controlled, presentation-only, built on @kud/ink-ui and fed by @kud/gh.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@kud/gh": "0.16.0",
|
|
52
|
-
"@kud/gh-workflow": "0.
|
|
53
|
-
"@kud/ink-ui": "0.
|
|
52
|
+
"@kud/gh-workflow": "0.11.0",
|
|
53
|
+
"@kud/ink-ui": "0.29.0",
|
|
54
54
|
"zx": "8.8.5"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|