@kud/gh-ink 0.8.1 → 0.9.1
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 +2 -1
- package/dist/index.js +197 -169
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -217,7 +217,7 @@ declare const ActionMenu: ({ item, actions, cursor, }: {
|
|
|
217
217
|
actions: Action[];
|
|
218
218
|
cursor: number;
|
|
219
219
|
}) => React.JSX.Element;
|
|
220
|
-
declare const App: ({ fetcher, cacheKey, title, detailFor, isWorkRepo, initialIncludeWork, jiraBase, jiraKeyRe, jiraTransitions, workToggle, hasCiStatus, ciJob, ciFetcher, ciPollMs, extensions, tabHelp, }: {
|
|
220
|
+
declare const App: ({ fetcher, cacheKey, title, detailFor, isWorkRepo, initialIncludeWork, jiraBase, jiraKeyRe, jiraTransitions, workToggle, hasCiStatus, ciJob, ciFetcher, ciPollMs, extensions, tabHelp, emptyHint, }: {
|
|
221
221
|
fetcher: () => Promise<{
|
|
222
222
|
sections: Section[];
|
|
223
223
|
login: string;
|
|
@@ -229,6 +229,7 @@ declare const App: ({ fetcher, cacheKey, title, detailFor, isWorkRepo, initialIn
|
|
|
229
229
|
isWorkRepo?: (repo: string) => boolean;
|
|
230
230
|
initialIncludeWork?: boolean;
|
|
231
231
|
tabHelp?: [string, string][];
|
|
232
|
+
emptyHint?: string;
|
|
232
233
|
jiraBase?: string;
|
|
233
234
|
jiraKeyRe?: RegExp;
|
|
234
235
|
jiraTransitions?: JiraTransition[];
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React2, { useState, useRef, useEffect } from 'react';
|
|
1
|
+
import React2, { createContext, useState, useRef, useEffect, useContext } from 'react';
|
|
2
2
|
import { useWindowSize, useInput, Text, Box } from 'ink';
|
|
3
|
-
import { colors, ScrollView, TextInput, LoadingScreen, Switch, useListCursor, Tabs
|
|
3
|
+
import { colors, ScrollView, TextInput, LoadingScreen, Switch, StatusMessage, FooterHints, useListCursor, Tabs } from '@kud/ink-ui';
|
|
4
4
|
import { isPassCheck, isFailCheck, resolveThread, unresolveThread, replyToThread, rerunFailedRun, mergePr, reRequestReviewer } from '@kud/gh';
|
|
5
5
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
6
6
|
import { $ } from 'zx';
|
|
@@ -1066,6 +1066,27 @@ var FRAME_PAD_X = 1;
|
|
|
1066
1066
|
var FRAME_CHROME_COLS = 2 + FRAME_PAD_X * 2;
|
|
1067
1067
|
var COLS = (process.stdout.columns ?? 120) - FRAME_CHROME_COLS;
|
|
1068
1068
|
var MODAL_CHROME_COLS = 2 + 1 * 2;
|
|
1069
|
+
var OVERLAY_BG = "#22222e";
|
|
1070
|
+
var DimContext = createContext(false);
|
|
1071
|
+
var Text2 = ({ children, ...props }) => {
|
|
1072
|
+
const dimmed = useContext(DimContext);
|
|
1073
|
+
return dimmed ? /* @__PURE__ */ jsx(Text, { ...props, bold: false, dimColor: true, children }) : /* @__PURE__ */ jsx(Text, { ...props, children });
|
|
1074
|
+
};
|
|
1075
|
+
var Backdrop = ({
|
|
1076
|
+
dimmed,
|
|
1077
|
+
absolute,
|
|
1078
|
+
height,
|
|
1079
|
+
children
|
|
1080
|
+
}) => /* @__PURE__ */ jsx(DimContext.Provider, { value: dimmed, children: absolute ? /* @__PURE__ */ jsx(
|
|
1081
|
+
Box,
|
|
1082
|
+
{
|
|
1083
|
+
position: "absolute",
|
|
1084
|
+
flexDirection: "column",
|
|
1085
|
+
width: "100%",
|
|
1086
|
+
height,
|
|
1087
|
+
children
|
|
1088
|
+
}
|
|
1089
|
+
) : children });
|
|
1069
1090
|
var topLevelCount = (s) => s.items.filter(
|
|
1070
1091
|
(i) => i.kind !== "repo-header" && i.kind !== "subgroup-header" && !i.indent
|
|
1071
1092
|
).length;
|
|
@@ -1342,13 +1363,14 @@ var InboxHeader = ({
|
|
|
1342
1363
|
brand,
|
|
1343
1364
|
work,
|
|
1344
1365
|
loading,
|
|
1366
|
+
quiet,
|
|
1345
1367
|
refreshing,
|
|
1346
1368
|
hasPending,
|
|
1347
1369
|
fetchedAt
|
|
1348
1370
|
}) => {
|
|
1349
1371
|
const total = sections.reduce((n, s) => n + topLevelCount(s), 0);
|
|
1350
|
-
const countSeg = loading ? " loading\u2026 " : ` ${String(total).padStart(3)} item${total !== 1 ? "s" : ""} \xB7 `;
|
|
1351
|
-
const userSeg = loading ? "" : `@${login} `;
|
|
1372
|
+
const countSeg = loading ? " loading\u2026 " : quiet ? " " : ` ${String(total).padStart(3)} item${total !== 1 ? "s" : ""} \xB7 `;
|
|
1373
|
+
const userSeg = loading || quiet ? "" : `@${login} `;
|
|
1352
1374
|
const workLabel = work === void 0 ? "" : " w work \u25CF\u2500\u25CB home ";
|
|
1353
1375
|
const [statusText, statusColor] = hasPending ? ["\u25CF new \xB7 r apply", "#FF8700"] : refreshing ? ["\u21BB refreshing\u2026", "cyan"] : fetchedAt ? [`updated ${agoText(fetchedAt)}`, void 0] : ["", void 0];
|
|
1354
1376
|
const statusSeg = statusText ? statusText + " " : "";
|
|
@@ -1357,16 +1379,16 @@ var InboxHeader = ({
|
|
|
1357
1379
|
COLS - brand.length - countSeg.length - userSeg.length - workLabel.length - statusSeg.length
|
|
1358
1380
|
);
|
|
1359
1381
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1360
|
-
/* @__PURE__ */ jsx(
|
|
1361
|
-
/* @__PURE__ */ jsx(
|
|
1362
|
-
userSeg ? /* @__PURE__ */ jsx(
|
|
1382
|
+
/* @__PURE__ */ jsx(Text2, { color: "#FF8700", bold: true, children: brand }),
|
|
1383
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: countSeg }),
|
|
1384
|
+
userSeg ? /* @__PURE__ */ jsx(Text2, { children: userSeg }) : null,
|
|
1363
1385
|
work !== void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1364
|
-
/* @__PURE__ */ jsx(
|
|
1386
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: " w " }),
|
|
1365
1387
|
/* @__PURE__ */ jsx(Switch, { left: "work", right: "home", value: work ? "left" : "right" }),
|
|
1366
|
-
/* @__PURE__ */ jsx(
|
|
1388
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: " " })
|
|
1367
1389
|
] }) : null,
|
|
1368
1390
|
statusText ? /* @__PURE__ */ jsx(
|
|
1369
|
-
|
|
1391
|
+
Text2,
|
|
1370
1392
|
{
|
|
1371
1393
|
color: statusColor,
|
|
1372
1394
|
dimColor: !statusColor,
|
|
@@ -1374,7 +1396,7 @@ var InboxHeader = ({
|
|
|
1374
1396
|
children: statusSeg
|
|
1375
1397
|
}
|
|
1376
1398
|
) : null,
|
|
1377
|
-
/* @__PURE__ */ jsx(
|
|
1399
|
+
/* @__PURE__ */ jsx(Text2, { color: "cyan", dimColor: true, children: "\u254C".repeat(fill) })
|
|
1378
1400
|
] });
|
|
1379
1401
|
};
|
|
1380
1402
|
var toCiStatusState = (status) => status ? { kind: "ready", status } : { kind: "error" };
|
|
@@ -1397,30 +1419,30 @@ var CiStatusLine = ({
|
|
|
1397
1419
|
const name = job ?? "ci";
|
|
1398
1420
|
if (state.kind === "loading")
|
|
1399
1421
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1400
|
-
/* @__PURE__ */ jsx(
|
|
1401
|
-
/* @__PURE__ */ jsx(
|
|
1422
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: " \xB7 " }),
|
|
1423
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: `${name} loading\u2026` })
|
|
1402
1424
|
] });
|
|
1403
1425
|
if (state.kind === "error")
|
|
1404
1426
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1405
|
-
/* @__PURE__ */ jsx(
|
|
1406
|
-
/* @__PURE__ */ jsx(
|
|
1427
|
+
/* @__PURE__ */ jsx(Text2, { color: "red", bold: true, children: " \u2717 " }),
|
|
1428
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: `${name} no build / not configured` })
|
|
1407
1429
|
] });
|
|
1408
1430
|
const { status } = state;
|
|
1409
1431
|
const [, color] = jenkinsResultDisplay(status.result, status.building);
|
|
1410
1432
|
const label = status.building ? "BUILDING" : status.result;
|
|
1411
1433
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1412
|
-
/* @__PURE__ */ jsx(
|
|
1413
|
-
/* @__PURE__ */ jsx(
|
|
1414
|
-
/* @__PURE__ */ jsx(
|
|
1415
|
-
/* @__PURE__ */ jsx(
|
|
1416
|
-
/* @__PURE__ */ jsx(
|
|
1417
|
-
status.age ? /* @__PURE__ */ jsx(
|
|
1434
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: " " }),
|
|
1435
|
+
/* @__PURE__ */ jsx(Text2, { color, bold: true, children: "\u25CF " }),
|
|
1436
|
+
/* @__PURE__ */ jsx(Text2, { bold: true, children: status.job }),
|
|
1437
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: " " + label }),
|
|
1438
|
+
/* @__PURE__ */ jsx(Text2, { color: "#FF8700", children: " #" + status.buildNumber }),
|
|
1439
|
+
status.age ? /* @__PURE__ */ jsx(Text2, { dimColor: true, children: " " + status.age }) : null
|
|
1418
1440
|
] });
|
|
1419
1441
|
};
|
|
1420
1442
|
var RepoHeaderRow = ({ repo, gap }) => {
|
|
1421
1443
|
const label = `\u2500\u2500 ${repo} `;
|
|
1422
1444
|
const fill = Math.max(4, 46 - label.length);
|
|
1423
|
-
return /* @__PURE__ */ jsx(Box, { marginTop: gap ? 1 : 0, children: /* @__PURE__ */ jsx(
|
|
1445
|
+
return /* @__PURE__ */ jsx(Box, { marginTop: gap ? 1 : 0, children: /* @__PURE__ */ jsx(Text2, { dimColor: true, children: " " + label + "\u2500".repeat(fill) }) });
|
|
1424
1446
|
};
|
|
1425
1447
|
var ItemRow = ({
|
|
1426
1448
|
item,
|
|
@@ -1432,29 +1454,29 @@ var ItemRow = ({
|
|
|
1432
1454
|
return /* @__PURE__ */ jsx(RepoHeaderRow, { repo: item.repo, gap: gap ?? false });
|
|
1433
1455
|
if (item.kind === "subgroup-header")
|
|
1434
1456
|
return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
|
|
1435
|
-
/* @__PURE__ */ jsx(
|
|
1436
|
-
/* @__PURE__ */ jsx(
|
|
1457
|
+
/* @__PURE__ */ jsx(Text2, { color: "#FF8700", bold: true, children: " \xBB " }),
|
|
1458
|
+
/* @__PURE__ */ jsx(Text2, { bold: true, children: item.label })
|
|
1437
1459
|
] });
|
|
1438
1460
|
if (item.kind === "show-more")
|
|
1439
1461
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
1440
|
-
/* @__PURE__ */ jsx(
|
|
1441
|
-
/* @__PURE__ */ jsx(
|
|
1442
|
-
/* @__PURE__ */ jsx(
|
|
1443
|
-
/* @__PURE__ */ jsx(
|
|
1462
|
+
/* @__PURE__ */ jsx(Text2, { color: "cyan", children: active ? "\u276F " : " " }),
|
|
1463
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: "\u2514\u2500 " }),
|
|
1464
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: active ? "\u21B5 " : " " }),
|
|
1465
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: `+${item.hidden.length} more` })
|
|
1444
1466
|
] });
|
|
1445
1467
|
if (item.kind === "show-less")
|
|
1446
1468
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
1447
|
-
/* @__PURE__ */ jsx(
|
|
1448
|
-
/* @__PURE__ */ jsx(
|
|
1449
|
-
/* @__PURE__ */ jsx(
|
|
1450
|
-
/* @__PURE__ */ jsx(
|
|
1469
|
+
/* @__PURE__ */ jsx(Text2, { color: "cyan", children: active ? "\u276F " : " " }),
|
|
1470
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: "\u2514\u2500 " }),
|
|
1471
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: active ? "\u21B5 " : " " }),
|
|
1472
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: "show less" })
|
|
1451
1473
|
] });
|
|
1452
1474
|
if (item.kind === "jira") {
|
|
1453
1475
|
const titleMax2 = Math.max(20, COLS - item.key.length - 10);
|
|
1454
1476
|
return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
|
|
1455
|
-
/* @__PURE__ */ jsx(
|
|
1456
|
-
/* @__PURE__ */ jsx(
|
|
1457
|
-
/* @__PURE__ */ jsx(
|
|
1477
|
+
/* @__PURE__ */ jsx(Text2, { color: "cyan", children: active ? "\u276F " : " " }),
|
|
1478
|
+
/* @__PURE__ */ jsx(Text2, { color: "#FF8700", bold: active, children: item.key + " " }),
|
|
1479
|
+
/* @__PURE__ */ jsx(Text2, { bold: active, children: truncate(item.summary, titleMax2) })
|
|
1458
1480
|
] });
|
|
1459
1481
|
}
|
|
1460
1482
|
const { glyph: icon, color } = healthDisplay[item.health];
|
|
@@ -1471,16 +1493,16 @@ var ItemRow = ({
|
|
|
1471
1493
|
const fixedWidth = 2 + (item.indent ? 3 : 0) + 2 + 2 + 7 + repoLabel.length + suffix.length + 6;
|
|
1472
1494
|
const titleMax = Math.max(20, COLS - fixedWidth);
|
|
1473
1495
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
1474
|
-
/* @__PURE__ */ jsx(
|
|
1475
|
-
item.indent ? /* @__PURE__ */ jsx(
|
|
1476
|
-
/* @__PURE__ */ jsx(
|
|
1477
|
-
/* @__PURE__ */ jsx(
|
|
1478
|
-
/* @__PURE__ */ jsx(
|
|
1479
|
-
/* @__PURE__ */ jsx(
|
|
1480
|
-
repoLabel ? /* @__PURE__ */ jsx(
|
|
1481
|
-
unresolvedLabel ? /* @__PURE__ */ jsx(
|
|
1482
|
-
showAuthor ? /* @__PURE__ */ jsx(
|
|
1483
|
-
item.age ? /* @__PURE__ */ jsx(
|
|
1496
|
+
/* @__PURE__ */ jsx(Text2, { color: "cyan", children: active ? "\u276F " : " " }),
|
|
1497
|
+
item.indent ? /* @__PURE__ */ jsx(Text2, { dimColor: true, children: "\u2514\u2500 " }) : null,
|
|
1498
|
+
/* @__PURE__ */ jsx(Text2, { color, bold: true, children: icon + " " }),
|
|
1499
|
+
/* @__PURE__ */ jsx(Text2, { color: turnColor, bold: turnIcon === "\u2190", children: turnIcon + " " }),
|
|
1500
|
+
/* @__PURE__ */ jsx(Text2, { color: "#FF8700", children: numStr }),
|
|
1501
|
+
/* @__PURE__ */ jsx(Text2, { bold: active, children: truncate(item.title, titleMax) + " " }),
|
|
1502
|
+
repoLabel ? /* @__PURE__ */ jsx(Text2, { dimColor: true, children: repoLabel }) : null,
|
|
1503
|
+
unresolvedLabel ? /* @__PURE__ */ jsx(Text2, { bold: true, color: "#FF8700", children: " " + unresolvedLabel }) : null,
|
|
1504
|
+
showAuthor ? /* @__PURE__ */ jsx(Text2, { dimColor: true, italic: true, children: " by " + item.author }) : null,
|
|
1505
|
+
item.age ? /* @__PURE__ */ jsx(Text2, { dimColor: true, children: " " + item.age }) : null
|
|
1484
1506
|
] });
|
|
1485
1507
|
};
|
|
1486
1508
|
var useActionMenu = () => {
|
|
@@ -1522,18 +1544,19 @@ var ActionMenu = ({
|
|
|
1522
1544
|
flexDirection: "column",
|
|
1523
1545
|
borderStyle: "round",
|
|
1524
1546
|
borderColor: "cyan",
|
|
1547
|
+
backgroundColor: OVERLAY_BG,
|
|
1525
1548
|
paddingX: 1,
|
|
1526
1549
|
marginTop: 1,
|
|
1527
1550
|
children: [
|
|
1528
|
-
/* @__PURE__ */ jsx(
|
|
1529
|
-
/* @__PURE__ */ jsx(
|
|
1551
|
+
/* @__PURE__ */ jsx(Text2, { color: "cyan", bold: true, children: title }),
|
|
1552
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: "\u2500".repeat(32) }),
|
|
1530
1553
|
actions.map((a, i) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
1531
|
-
/* @__PURE__ */ jsx(
|
|
1532
|
-
/* @__PURE__ */ jsx(
|
|
1533
|
-
/* @__PURE__ */ jsx(
|
|
1554
|
+
/* @__PURE__ */ jsx(Text2, { color: "cyan", children: i === cursor ? "\u276F " : " " }),
|
|
1555
|
+
/* @__PURE__ */ jsx(Text2, { bold: i === cursor, children: a.label }),
|
|
1556
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: " " + a.hint })
|
|
1534
1557
|
] }, a.label)),
|
|
1535
|
-
/* @__PURE__ */ jsx(
|
|
1536
|
-
/* @__PURE__ */ jsx(
|
|
1558
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: "\u2500".repeat(32) }),
|
|
1559
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: "\u2191\u2193 navigate \u21B5 confirm esc cancel" })
|
|
1537
1560
|
]
|
|
1538
1561
|
}
|
|
1539
1562
|
);
|
|
@@ -1570,10 +1593,10 @@ var LegendGroup = ({
|
|
|
1570
1593
|
flexDirection: "column",
|
|
1571
1594
|
marginTop: index === 0 ? 0 : 1,
|
|
1572
1595
|
children: [
|
|
1573
|
-
/* @__PURE__ */ jsx(
|
|
1596
|
+
/* @__PURE__ */ jsx(Text2, { bold: true, dimColor: true, children: col.title }),
|
|
1574
1597
|
col.rows.map((row) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
1575
|
-
/* @__PURE__ */ jsx(
|
|
1576
|
-
/* @__PURE__ */ jsx(
|
|
1598
|
+
/* @__PURE__ */ jsx(Text2, { color: row.color, bold: row.bold, children: row.cell.padEnd(cellWidth) }),
|
|
1599
|
+
/* @__PURE__ */ jsx(Text2, { wrap: "truncate-end", children: row.label })
|
|
1577
1600
|
] }, col.title + row.cell + row.label))
|
|
1578
1601
|
]
|
|
1579
1602
|
},
|
|
@@ -1661,10 +1684,11 @@ var HelpModal = ({
|
|
|
1661
1684
|
flexDirection: "column",
|
|
1662
1685
|
borderStyle: "round",
|
|
1663
1686
|
borderColor: "cyan",
|
|
1687
|
+
backgroundColor: OVERLAY_BG,
|
|
1664
1688
|
paddingX: 1,
|
|
1665
1689
|
width: contentWidth + MODAL_CHROME_COLS,
|
|
1666
1690
|
children: [
|
|
1667
|
-
/* @__PURE__ */ jsx(
|
|
1691
|
+
/* @__PURE__ */ jsx(Text2, { color: "cyan", bold: true, children: "Legend" }),
|
|
1668
1692
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, width: contentWidth, children: groups.map((group, index) => /* @__PURE__ */ jsx(
|
|
1669
1693
|
LegendGroup,
|
|
1670
1694
|
{
|
|
@@ -1674,8 +1698,8 @@ var HelpModal = ({
|
|
|
1674
1698
|
},
|
|
1675
1699
|
group[0]?.title ?? index
|
|
1676
1700
|
)) }),
|
|
1677
|
-
tabHelp ? /* @__PURE__ */ jsx(
|
|
1678
|
-
/* @__PURE__ */ jsx(
|
|
1701
|
+
tabHelp ? /* @__PURE__ */ jsx(Text2, { dimColor: true, children: "Each item lands in the FIRST tab that claims it, so counts are residuals rather than totals." }) : null,
|
|
1702
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: "esc \xB7 ? close" })
|
|
1679
1703
|
]
|
|
1680
1704
|
}
|
|
1681
1705
|
);
|
|
@@ -1686,16 +1710,17 @@ var ExplainModal = ({ item, login }) => /* @__PURE__ */ jsxs(
|
|
|
1686
1710
|
flexDirection: "column",
|
|
1687
1711
|
borderStyle: "round",
|
|
1688
1712
|
borderColor: "cyan",
|
|
1713
|
+
backgroundColor: OVERLAY_BG,
|
|
1689
1714
|
paddingX: 1,
|
|
1690
1715
|
width: Math.min(COLS, 78),
|
|
1691
1716
|
children: [
|
|
1692
|
-
/* @__PURE__ */ jsx(
|
|
1693
|
-
/* @__PURE__ */ jsx(
|
|
1717
|
+
/* @__PURE__ */ jsx(Text2, { color: "#FF8700", bold: true, children: `#${item.number} \xB7 ${item.repo}` }),
|
|
1718
|
+
/* @__PURE__ */ jsx(Text2, { children: item.title }),
|
|
1694
1719
|
explainItem(item, login).map((section) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
1695
|
-
/* @__PURE__ */ jsx(
|
|
1696
|
-
section.lines.map((line, i) => /* @__PURE__ */ jsx(
|
|
1720
|
+
/* @__PURE__ */ jsx(Text2, { bold: true, dimColor: true, children: section.heading }),
|
|
1721
|
+
section.lines.map((line, i) => /* @__PURE__ */ jsx(Text2, { children: " " + line }, i))
|
|
1697
1722
|
] }, section.heading)),
|
|
1698
|
-
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
|
|
1723
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text2, { dimColor: true, children: "esc \xB7 e close" }) })
|
|
1699
1724
|
]
|
|
1700
1725
|
}
|
|
1701
1726
|
);
|
|
@@ -1717,24 +1742,25 @@ var RepoPicker = ({
|
|
|
1717
1742
|
flexDirection: "column",
|
|
1718
1743
|
borderStyle: "round",
|
|
1719
1744
|
borderColor: "cyan",
|
|
1745
|
+
backgroundColor: OVERLAY_BG,
|
|
1720
1746
|
paddingX: 1,
|
|
1721
1747
|
minWidth: 42,
|
|
1722
1748
|
children: [
|
|
1723
|
-
/* @__PURE__ */ jsx(
|
|
1724
|
-
/* @__PURE__ */ jsx(
|
|
1749
|
+
/* @__PURE__ */ jsx(Text2, { color: "cyan", bold: true, children: `Filter by repo (${selected.size} on)` }),
|
|
1750
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: "\u2500".repeat(36) }),
|
|
1725
1751
|
visible.map((repo, i) => {
|
|
1726
1752
|
const idx = start + i;
|
|
1727
1753
|
const on = selected.has(repo);
|
|
1728
1754
|
const active = idx === cursor;
|
|
1729
1755
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
1730
|
-
/* @__PURE__ */ jsx(
|
|
1731
|
-
/* @__PURE__ */ jsx(
|
|
1732
|
-
/* @__PURE__ */ jsx(
|
|
1756
|
+
/* @__PURE__ */ jsx(Text2, { color: "cyan", children: active ? "\u276F " : " " }),
|
|
1757
|
+
/* @__PURE__ */ jsx(Text2, { color: on ? "green" : void 0, children: on ? "\u25C9 " : "\u25CB " }),
|
|
1758
|
+
/* @__PURE__ */ jsx(Text2, { bold: active, children: repo })
|
|
1733
1759
|
] }, repo);
|
|
1734
1760
|
}),
|
|
1735
|
-
repos.length > budget ? /* @__PURE__ */ jsx(
|
|
1736
|
-
/* @__PURE__ */ jsx(
|
|
1737
|
-
/* @__PURE__ */ jsx(
|
|
1761
|
+
repos.length > budget ? /* @__PURE__ */ jsx(Text2, { dimColor: true, children: ` \u2026 ${repos.length} repos total` }) : null,
|
|
1762
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: "\u2500".repeat(36) }),
|
|
1763
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: "space toggle \xB7 a clear all \xB7 \u21B5/esc done" })
|
|
1738
1764
|
]
|
|
1739
1765
|
}
|
|
1740
1766
|
);
|
|
@@ -2146,6 +2172,22 @@ var BrowseScreen = ({
|
|
|
2146
2172
|
(i) => i.kind !== "repo-header" && i.kind !== "subgroup-header"
|
|
2147
2173
|
).length;
|
|
2148
2174
|
if (hidden) return null;
|
|
2175
|
+
const overlay = help ? /* @__PURE__ */ jsx(
|
|
2176
|
+
HelpModal,
|
|
2177
|
+
{
|
|
2178
|
+
workToggle,
|
|
2179
|
+
extensions,
|
|
2180
|
+
hasJira: !!jiraBase,
|
|
2181
|
+
tabHelp
|
|
2182
|
+
}
|
|
2183
|
+
) : explain && activeItem && (activeItem.kind === "pr" || activeItem.kind === "issue") ? /* @__PURE__ */ jsx(ExplainModal, { item: activeItem, login }) : repoPicker ? /* @__PURE__ */ jsx(
|
|
2184
|
+
RepoPicker,
|
|
2185
|
+
{
|
|
2186
|
+
repos: allRepos,
|
|
2187
|
+
selected: repoFilter,
|
|
2188
|
+
cursor: Math.min(repoCursor, Math.max(0, allRepos.length - 1))
|
|
2189
|
+
}
|
|
2190
|
+
) : menu.actions && activeItem && activeItem.kind !== "repo-header" ? /* @__PURE__ */ jsx(ActionMenu, { item: activeItem, actions: menu.actions, cursor: menu.cursor }) : null;
|
|
2149
2191
|
return /* @__PURE__ */ jsxs(
|
|
2150
2192
|
Box,
|
|
2151
2193
|
{
|
|
@@ -2181,110 +2223,87 @@ var BrowseScreen = ({
|
|
|
2181
2223
|
}
|
|
2182
2224
|
) }),
|
|
2183
2225
|
search != null ? /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
2184
|
-
/* @__PURE__ */ jsx(
|
|
2185
|
-
/* @__PURE__ */ jsx(
|
|
2186
|
-
searchInput ? /* @__PURE__ */ jsx(
|
|
2226
|
+
/* @__PURE__ */ jsx(Text2, { color: "cyan", children: " / " }),
|
|
2227
|
+
/* @__PURE__ */ jsx(Text2, { children: search }),
|
|
2228
|
+
searchInput ? /* @__PURE__ */ jsx(Text2, { color: "cyan", children: "\u258F" }) : null,
|
|
2187
2229
|
/* @__PURE__ */ jsx(
|
|
2188
|
-
|
|
2230
|
+
Text2,
|
|
2189
2231
|
{
|
|
2190
2232
|
dimColor: true,
|
|
2191
2233
|
children: ` ${matchCount} match${matchCount !== 1 ? "es" : ""}${searchInput ? " \u21B5 accept \xB7 esc clear" : " esc clear"}`
|
|
2192
2234
|
}
|
|
2193
2235
|
)
|
|
2194
2236
|
] }) : repoFilter.size > 0 ? /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
2195
|
-
/* @__PURE__ */ jsx(
|
|
2196
|
-
/* @__PURE__ */ jsx(
|
|
2197
|
-
/* @__PURE__ */ jsx(
|
|
2237
|
+
/* @__PURE__ */ jsx(Text2, { color: "#FF8700", children: " \u25C9 " }),
|
|
2238
|
+
/* @__PURE__ */ jsx(Text2, { children: `${repoFilter.size} repo${repoFilter.size !== 1 ? "s" : ""}` }),
|
|
2239
|
+
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: " f edit \xB7 esc clear" })
|
|
2198
2240
|
] }) : null,
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
flexDirection: "column",
|
|
2204
|
-
justifyContent: "center",
|
|
2205
|
-
alignItems: "center",
|
|
2206
|
-
children: /* @__PURE__ */ jsx(
|
|
2207
|
-
HelpModal,
|
|
2208
|
-
{
|
|
2209
|
-
workToggle,
|
|
2210
|
-
extensions,
|
|
2211
|
-
hasJira: !!jiraBase,
|
|
2212
|
-
tabHelp
|
|
2213
|
-
}
|
|
2214
|
-
)
|
|
2215
|
-
}
|
|
2216
|
-
) : explain && activeItem && (activeItem.kind === "pr" || activeItem.kind === "issue") ? /* @__PURE__ */ jsx(
|
|
2217
|
-
Box,
|
|
2218
|
-
{
|
|
2219
|
-
minHeight: listHeight,
|
|
2220
|
-
flexDirection: "column",
|
|
2221
|
-
justifyContent: "center",
|
|
2222
|
-
alignItems: "center",
|
|
2223
|
-
children: /* @__PURE__ */ jsx(ExplainModal, { item: activeItem, login })
|
|
2224
|
-
}
|
|
2225
|
-
) : repoPicker ? /* @__PURE__ */ jsx(
|
|
2226
|
-
Box,
|
|
2227
|
-
{
|
|
2228
|
-
minHeight: listHeight,
|
|
2229
|
-
flexDirection: "column",
|
|
2230
|
-
justifyContent: "center",
|
|
2231
|
-
alignItems: "center",
|
|
2232
|
-
children: /* @__PURE__ */ jsx(
|
|
2233
|
-
RepoPicker,
|
|
2234
|
-
{
|
|
2235
|
-
repos: allRepos,
|
|
2236
|
-
selected: repoFilter,
|
|
2237
|
-
cursor: Math.min(repoCursor, Math.max(0, allRepos.length - 1))
|
|
2238
|
-
}
|
|
2239
|
-
)
|
|
2240
|
-
}
|
|
2241
|
-
) : menu.actions && activeItem && activeItem.kind !== "repo-header" ? /* @__PURE__ */ jsx(
|
|
2242
|
-
Box,
|
|
2243
|
-
{
|
|
2244
|
-
minHeight: listHeight,
|
|
2245
|
-
flexDirection: "column",
|
|
2246
|
-
justifyContent: "center",
|
|
2247
|
-
alignItems: "center",
|
|
2248
|
-
children: /* @__PURE__ */ jsx(
|
|
2249
|
-
ActionMenu,
|
|
2241
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", minHeight: listHeight, children: [
|
|
2242
|
+
/* @__PURE__ */ jsxs(Backdrop, { dimmed: !!overlay, absolute: !!overlay, height: listHeight, children: [
|
|
2243
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", flexGrow: 1, children: visibleItems.map((item, i) => /* @__PURE__ */ jsx(
|
|
2244
|
+
ItemRow,
|
|
2250
2245
|
{
|
|
2251
|
-
item
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2246
|
+
item,
|
|
2247
|
+
active: viewStart + i === cursor,
|
|
2248
|
+
login,
|
|
2249
|
+
gap: viewStart + i > 0 && (item.kind === "repo-header" || item.kind === "subgroup-header" || // A header is always followed by a blank line before its
|
|
2250
|
+
// first child — in Other PRs that's "free" because the
|
|
2251
|
+
// child is itself a repo-header (gap above). A jira row
|
|
2252
|
+
// has no such stand-in, so it needs this explicitly. Never
|
|
2253
|
+
// applies between two tickets/PRs — only right after a
|
|
2254
|
+
// header.
|
|
2255
|
+
item.kind === "jira" && ["repo-header", "subgroup-header"].includes(
|
|
2256
|
+
section.items[viewStart + i - 1]?.kind
|
|
2257
|
+
))
|
|
2258
|
+
},
|
|
2259
|
+
`${viewStart + i}:${item.kind === "jira" ? item.instanceKey ?? item.key : item.kind === "repo-header" ? `header:${item.repo}` : item.kind === "subgroup-header" ? `subgroup:${item.label}` : item.kind === "show-more" ? `show-more:${item.hidden[0]?.repo ?? i}` : item.kind === "show-less" ? `show-less:${item.toHide[0]?.repo ?? i}` : `${item.repo}/${item.number}`}`
|
|
2260
|
+
)) }),
|
|
2261
|
+
hasMore && /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
|
|
2262
|
+
" ",
|
|
2263
|
+
"\u2193 ",
|
|
2264
|
+
section.items.length - viewStart - visibleCount,
|
|
2265
|
+
" more"
|
|
2266
|
+
] })
|
|
2267
|
+
] }),
|
|
2268
|
+
overlay ? /* @__PURE__ */ jsx(
|
|
2269
|
+
Box,
|
|
2260
2270
|
{
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
// applies between two tickets/PRs — only right after a
|
|
2269
|
-
// header.
|
|
2270
|
-
item.kind === "jira" && ["repo-header", "subgroup-header"].includes(
|
|
2271
|
-
section.items[viewStart + i - 1]?.kind
|
|
2272
|
-
))
|
|
2273
|
-
},
|
|
2274
|
-
`${viewStart + i}:${item.kind === "jira" ? item.instanceKey ?? item.key : item.kind === "repo-header" ? `header:${item.repo}` : item.kind === "subgroup-header" ? `subgroup:${item.label}` : item.kind === "show-more" ? `show-more:${item.hidden[0]?.repo ?? i}` : item.kind === "show-less" ? `show-less:${item.toHide[0]?.repo ?? i}` : `${item.repo}/${item.number}`}`
|
|
2275
|
-
)) }),
|
|
2276
|
-
hasMore && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2277
|
-
" ",
|
|
2278
|
-
"\u2193 ",
|
|
2279
|
-
section.items.length - viewStart - visibleCount,
|
|
2280
|
-
" more"
|
|
2281
|
-
] })
|
|
2271
|
+
flexGrow: 1,
|
|
2272
|
+
flexDirection: "column",
|
|
2273
|
+
justifyContent: "center",
|
|
2274
|
+
alignItems: "center",
|
|
2275
|
+
children: overlay
|
|
2276
|
+
}
|
|
2277
|
+
) : null
|
|
2282
2278
|
] }),
|
|
2283
|
-
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: flash ? /* @__PURE__ */ jsx(
|
|
2279
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: flash ? /* @__PURE__ */ jsx(Text2, { color: "green", children: flash }) : /* @__PURE__ */ jsx(FooterHints, { hints }) })
|
|
2284
2280
|
]
|
|
2285
2281
|
}
|
|
2286
2282
|
);
|
|
2287
2283
|
};
|
|
2284
|
+
var NoRowsScreen = ({
|
|
2285
|
+
reason,
|
|
2286
|
+
detail,
|
|
2287
|
+
onRetry
|
|
2288
|
+
}) => {
|
|
2289
|
+
useInput((input) => {
|
|
2290
|
+
if (input === "q") process.exit(0);
|
|
2291
|
+
if (input === "r") onRetry();
|
|
2292
|
+
});
|
|
2293
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2294
|
+
/* @__PURE__ */ jsx(StatusMessage, { variant: reason === "empty" ? "info" : "error", children: reason === "empty" ? "Nothing open." : `Fetch failed \u2014 ${detail ?? "no reason reported"}` }),
|
|
2295
|
+
reason === "empty" && detail ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text2, { dimColor: true, children: detail }) }) : null,
|
|
2296
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
|
|
2297
|
+
FooterHints,
|
|
2298
|
+
{
|
|
2299
|
+
hints: [
|
|
2300
|
+
["r", "retry"],
|
|
2301
|
+
["q", "quit"]
|
|
2302
|
+
]
|
|
2303
|
+
}
|
|
2304
|
+
) })
|
|
2305
|
+
] });
|
|
2306
|
+
};
|
|
2288
2307
|
var signatureOf = (sections) => JSON.stringify(sections, (k, v) => k === "age" ? void 0 : v);
|
|
2289
2308
|
var App = ({
|
|
2290
2309
|
fetcher,
|
|
@@ -2302,7 +2321,8 @@ var App = ({
|
|
|
2302
2321
|
ciFetcher,
|
|
2303
2322
|
ciPollMs = 6e4,
|
|
2304
2323
|
extensions,
|
|
2305
|
-
tabHelp
|
|
2324
|
+
tabHelp,
|
|
2325
|
+
emptyHint
|
|
2306
2326
|
}) => {
|
|
2307
2327
|
const [state, setState] = useState({ phase: "loading" });
|
|
2308
2328
|
const [pending, setPending] = useState(null);
|
|
@@ -2334,8 +2354,8 @@ var App = ({
|
|
|
2334
2354
|
const freshKey = signatureOf(fresh.sections);
|
|
2335
2355
|
if (!displayedKey.current) {
|
|
2336
2356
|
if (fresh.sections.length === 0) {
|
|
2337
|
-
|
|
2338
|
-
|
|
2357
|
+
setState({ phase: "empty" });
|
|
2358
|
+
return;
|
|
2339
2359
|
}
|
|
2340
2360
|
showData(fresh.sections, fresh.login);
|
|
2341
2361
|
} else if (freshKey !== displayedKey.current) {
|
|
@@ -2347,8 +2367,8 @@ var App = ({
|
|
|
2347
2367
|
setRefreshing(false);
|
|
2348
2368
|
const message = err.message;
|
|
2349
2369
|
if (!displayedKey.current) {
|
|
2350
|
-
|
|
2351
|
-
|
|
2370
|
+
setState({ phase: "failed", message });
|
|
2371
|
+
return;
|
|
2352
2372
|
}
|
|
2353
2373
|
setRefreshError({ message, at: Date.now() });
|
|
2354
2374
|
});
|
|
@@ -2392,7 +2412,7 @@ var App = ({
|
|
|
2392
2412
|
clearInterval(id);
|
|
2393
2413
|
};
|
|
2394
2414
|
}, [hasCiStatus, ciFetcher, ciPollMs]);
|
|
2395
|
-
if (state.phase === "loading")
|
|
2415
|
+
if (state.phase === "loading" || state.phase === "empty" || state.phase === "failed")
|
|
2396
2416
|
return /* @__PURE__ */ jsxs(
|
|
2397
2417
|
Box,
|
|
2398
2418
|
{
|
|
@@ -2409,12 +2429,20 @@ var App = ({
|
|
|
2409
2429
|
brand: brandOf(title),
|
|
2410
2430
|
sections: [],
|
|
2411
2431
|
login: "",
|
|
2412
|
-
work: workToggle ? initialIncludeWork ?? true : void 0,
|
|
2413
|
-
loading:
|
|
2432
|
+
work: workToggle && state.phase === "loading" ? initialIncludeWork ?? true : void 0,
|
|
2433
|
+
loading: state.phase === "loading",
|
|
2434
|
+
quiet: state.phase !== "loading"
|
|
2414
2435
|
}
|
|
2415
2436
|
),
|
|
2416
2437
|
hasCiStatus ? /* @__PURE__ */ jsx(CiStatusLine, { state: ciStatusState, job: ciJob }) : null,
|
|
2417
|
-
/* @__PURE__ */ jsx(LoadingScreen, { label: `Fetching ${title}\u2026` })
|
|
2438
|
+
state.phase === "loading" ? /* @__PURE__ */ jsx(LoadingScreen, { label: `Fetching ${title}\u2026` }) : /* @__PURE__ */ jsx(
|
|
2439
|
+
NoRowsScreen,
|
|
2440
|
+
{
|
|
2441
|
+
reason: state.phase === "empty" ? "empty" : "failed",
|
|
2442
|
+
detail: state.phase === "failed" ? state.message : emptyHint,
|
|
2443
|
+
onRetry: () => revalidate(true)
|
|
2444
|
+
}
|
|
2445
|
+
)
|
|
2418
2446
|
]
|
|
2419
2447
|
}
|
|
2420
2448
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kud/gh-ink",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
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",
|