@kud/gh-ink 0.63.0 → 0.65.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 +35 -15
- package/dist/index.js +95 -33
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
2
|
import { PrComments, PrHealthData, PrCheck, Health } from '@kud/gh';
|
|
3
3
|
import { GHItem, AnyItem, Section, CiStatus, OriginSplit } from '@kud/gh-workflow';
|
|
4
|
-
export { AnyItem, Band, CiStatus, GHDetail, GHItem, InboxConfig, Move, OriginSplit, PIN_MARK, RepoHeader, RepoProfile, Section, ShowLess, ShowMore, Standing, SubgroupHeader, TaskRow, bandOf, checkoutDirs, configureInbox, filterByOrigin, filterByRepos, filterBySearch, impliedLabels, inboxConfig, insertRepoHeaders, labelPriority, layoutGHItems, profileOf, relativeTime, repoPriority, resetInboxConfig, sortByRecency, sortItems, whoseMove } from '@kud/gh-workflow';
|
|
4
|
+
export { AnyItem, Band, CiStatus, GHDetail, GHItem, InboxConfig, Move, NEEDS_YOU_SECTION, NeedsYou, OriginSplit, PIN_MARK, RepoHeader, RepoProfile, Section, ShowLess, ShowMore, Standing, SubgroupHeader, TaskRow, bandOf, checkoutDirs, configureInbox, filterByOrigin, filterByRepos, filterBySearch, impliedLabels, inboxConfig, insertRepoHeaders, labelPriority, layoutGHItems, profileOf, relativeTime, repoPriority, resetInboxConfig, sortByRecency, sortItems, whoseMove } from '@kud/gh-workflow';
|
|
5
5
|
import { StyledLine } from '@kud/ink-ui';
|
|
6
6
|
|
|
7
7
|
type CommentsPanelProps = {
|
|
@@ -250,6 +250,12 @@ type PrRowProps = {
|
|
|
250
250
|
columns?: TrailingColumns;
|
|
251
251
|
/** Trailing columns the section has given up — see `sectionShedOf`. */
|
|
252
252
|
shed?: TrailingShed;
|
|
253
|
+
/**
|
|
254
|
+
* Width of the number cell across the section — see `numberColumnsOf`.
|
|
255
|
+
* Absent, the row measures itself, which aligns nothing but never runs the
|
|
256
|
+
* number into the title.
|
|
257
|
+
*/
|
|
258
|
+
numberCols?: number;
|
|
253
259
|
};
|
|
254
260
|
/**
|
|
255
261
|
* The trailing block, in reading order: how contested, how big, how recent.
|
|
@@ -274,7 +280,19 @@ type TrailingShed = Partial<Record<(typeof TRAILING)[number], boolean>>;
|
|
|
274
280
|
* would not.
|
|
275
281
|
*/
|
|
276
282
|
declare const trailingColumnsOf: (items: readonly GHItem[]) => TrailingColumns;
|
|
277
|
-
|
|
283
|
+
/**
|
|
284
|
+
* Width of the `#n` cell across these rows: the widest number plus a two-cell
|
|
285
|
+
* gutter, left-aligned. Measured once by the list over the whole section, the
|
|
286
|
+
* same move as `markerCols` and `trailingColumnsOf`, so the titles start on one
|
|
287
|
+
* column and that column does not move as you scroll.
|
|
288
|
+
*
|
|
289
|
+
* It replaced `padEnd(7)`, a constant that fitted the repos it was written
|
|
290
|
+
* against and nothing else: `#31805` left a one-cell gutter where `#172` left
|
|
291
|
+
* three, and a six-digit number would have run straight into its title. A
|
|
292
|
+
* section of short numbers no longer pays for a long one it does not hold.
|
|
293
|
+
*/
|
|
294
|
+
declare const numberColumnsOf: (items: readonly GHItem[]) => number;
|
|
295
|
+
type LayoutInput = Pick<PrRowProps, "item" | "login" | "cols" | "prefix" | "uniformLabels" | "announcements" | "columns" | "shed" | "numberCols">;
|
|
278
296
|
/**
|
|
279
297
|
* Which trailing columns the section has to give up, so that every row gives up
|
|
280
298
|
* the same ones. Each row is laid out alone and the drops are unioned: if any
|
|
@@ -300,7 +318,7 @@ declare const sectionShedOf: (rows: readonly Pick<LayoutInput, "item" | "prefix"
|
|
|
300
318
|
* arrival, merge and departure belongs to whoever owns the list, and reaches
|
|
301
319
|
* the row as `icon`, `motion` and `announcements` after the decisions are made.
|
|
302
320
|
*/
|
|
303
|
-
declare const PrRow: ({ item, active, login, cols, icon: iconOverride, prefix, uniformLabels, motion, announcements, columns, shed, }: PrRowProps) => React.JSX.Element;
|
|
321
|
+
declare const PrRow: ({ item, active, login, cols, icon: iconOverride, prefix, uniformLabels, motion, announcements, columns, shed, numberCols, }: PrRowProps) => React.JSX.Element;
|
|
304
322
|
|
|
305
323
|
/**
|
|
306
324
|
* One state per thing, from a closed set the strip knows how to draw. The host
|
|
@@ -525,18 +543,20 @@ declare const reposInSections: (sections: Section[]) => string[];
|
|
|
525
543
|
/**
|
|
526
544
|
* The next selectable row in `dir`, or `current` when there is none.
|
|
527
545
|
*
|
|
528
|
-
*
|
|
529
|
-
*
|
|
530
|
-
*
|
|
531
|
-
*
|
|
532
|
-
*
|
|
546
|
+
* Both header kinds are STOPS. A repo-header names a thing you can act on —
|
|
547
|
+
* open the checkout, copy every URL under it — and a band header
|
|
548
|
+
* ("» Your move") does now too: `c` copies the whole band. Landing on one
|
|
549
|
+
* used to be a keystroke spent on a row whose every key was inert, which is
|
|
550
|
+
* why `moveCursor` stepped over subgroup-headers; now that the key does
|
|
551
|
+
* something there, skipping it would hide the row that says how many links
|
|
552
|
+
* the key will take.
|
|
533
553
|
*
|
|
534
|
-
* Unconditional in both directions, deliberately. Skipping
|
|
535
|
-
* and landing on it going up would make ↓ then ↑ end somewhere other
|
|
536
|
-
* it started, and an arrow pair that is not its own inverse reads
|
|
537
|
-
* drifting rather than as a shortcut. The cost is one press per
|
|
538
|
-
*
|
|
539
|
-
* anyway, so the press buys orientation as well as position.
|
|
554
|
+
* Unconditional in both directions, deliberately. Skipping a header going
|
|
555
|
+
* down and landing on it going up would make ↓ then ↑ end somewhere other
|
|
556
|
+
* than where it started, and an arrow pair that is not its own inverse reads
|
|
557
|
+
* as the list drifting rather than as a shortcut. The cost is one press per
|
|
558
|
+
* header; each is also the "you have crossed into another group" beat the eye
|
|
559
|
+
* takes anyway, so the press buys orientation as well as position.
|
|
540
560
|
*/
|
|
541
561
|
declare const moveCursor: (items: AnyItem[], current: number, dir: 1 | -1) => number;
|
|
542
562
|
/**
|
|
@@ -792,4 +812,4 @@ declare const matchesFilter: (repo: string, filter: RepoFilter) => boolean;
|
|
|
792
812
|
*/
|
|
793
813
|
declare const parsePatterns: (value: string) => string[];
|
|
794
814
|
|
|
795
|
-
export { type Action, ActionMenu, App, COLS, CiStatusLine, type CiStatusState, type Command, CommentsPanel, type CommentsPanelProps, type DetailContext, type ExplainSection, type ExtensionTarget, HealthPanel, type HealthPanelProps, type InboxBudget, type InboxExtension, type JiraTransition, type LiveLabel, MIN_SIDEBAR_COLS, PrRow, type PrRowProps, type Rails, type RepoFilter, type RowAnnouncement, type RowMotion, SIDEBAR_COLS, type SettledResult, SidePanel, type Sidebar, type SidebarRow, type StatusStrip, StatusStripLine, type StripItem, type StripState, type StripStatusState, type TrailingColumns, type TrailingShed, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sectionShedOf, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, trailingColumnsOf, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
|
|
815
|
+
export { type Action, ActionMenu, App, COLS, CiStatusLine, type CiStatusState, type Command, CommentsPanel, type CommentsPanelProps, type DetailContext, type ExplainSection, type ExtensionTarget, HealthPanel, type HealthPanelProps, type InboxBudget, type InboxExtension, type JiraTransition, type LiveLabel, MIN_SIDEBAR_COLS, PrRow, type PrRowProps, type Rails, type RepoFilter, type RowAnnouncement, type RowMotion, SIDEBAR_COLS, type SettledResult, SidePanel, type Sidebar, type SidebarRow, type StatusStrip, StatusStripLine, type StripItem, type StripState, type StripStatusState, type TrailingColumns, type TrailingShed, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, numberColumnsOf, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sectionShedOf, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, trailingColumnsOf, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { colors, ScrollView, TextInput, Pill, useAppKeys, LoadingScreen, StatusM
|
|
|
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 { PIN_MARK, sizeOf, sizePartsOf, depthOf, impliedLabels, labelPriority, checkoutDirs, profileOf, inboxConfig, relativeTime, filterBySearch, filterByRepos, filterByOrigin } from '@kud/gh-workflow';
|
|
7
|
-
export { PIN_MARK, bandOf, checkoutDirs, configureInbox, filterByOrigin, filterByRepos, filterBySearch, impliedLabels, inboxConfig, insertRepoHeaders, labelPriority, layoutGHItems, profileOf, relativeTime, repoPriority, resetInboxConfig, sortByRecency, sortItems, whoseMove } from '@kud/gh-workflow';
|
|
7
|
+
export { NEEDS_YOU_SECTION, PIN_MARK, bandOf, checkoutDirs, configureInbox, filterByOrigin, filterByRepos, filterBySearch, impliedLabels, inboxConfig, insertRepoHeaders, labelPriority, layoutGHItems, profileOf, relativeTime, repoPriority, resetInboxConfig, sortByRecency, sortItems, whoseMove } from '@kud/gh-workflow';
|
|
8
8
|
import { $ } from 'zx';
|
|
9
9
|
import { spawn } from 'child_process';
|
|
10
10
|
import { readFileSync, mkdirSync, writeFileSync, existsSync, readdirSync, statSync, watch, rmSync } from 'fs';
|
|
@@ -849,6 +849,7 @@ var trailingColumnsOf = (items) => items.reduce(
|
|
|
849
849
|
}),
|
|
850
850
|
{ threads: 0, size: 0, age: 0 }
|
|
851
851
|
);
|
|
852
|
+
var numberColumnsOf = (items) => items.reduce((w, item) => Math.max(w, cellsOf(`#${item.number}`)), 0) + 2;
|
|
852
853
|
var sectionShedOf = (rows, context) => rows.reduce((shed, row) => {
|
|
853
854
|
const { givingUp } = layoutOf({ ...context, ...row });
|
|
854
855
|
return {
|
|
@@ -865,9 +866,11 @@ var layoutOf = ({
|
|
|
865
866
|
uniformLabels = [],
|
|
866
867
|
announcements = [],
|
|
867
868
|
columns,
|
|
868
|
-
shed = {}
|
|
869
|
+
shed = {},
|
|
870
|
+
numberCols
|
|
869
871
|
}) => {
|
|
870
|
-
const
|
|
872
|
+
const numCols = numberCols ?? numberColumnsOf([item]);
|
|
873
|
+
const numStr = `#${item.number}`.padEnd(numCols);
|
|
871
874
|
const showAuthor = !!item.author && item.author !== login;
|
|
872
875
|
const sizeParts = sizePartsOf(item);
|
|
873
876
|
const unresolvedLabel = threadsLabelOf(item);
|
|
@@ -911,7 +914,7 @@ var layoutOf = ({
|
|
|
911
914
|
const author = showAuthor && !givingUp.author ? ` by ${item.author}`.length : 0;
|
|
912
915
|
const pills = announcements.reduce((w, a) => w + 2 + a.label.length, 0);
|
|
913
916
|
const cell = labelCell();
|
|
914
|
-
return 2 + prefix.length + 2 + 2 +
|
|
917
|
+
return 2 + prefix.length + 2 + 2 + numCols + (cell ? 2 + cell.length + 1 : 0) + (givingUp.repo ? 0 : repoLabel.length) + author + block + pills + pillCaps + 4;
|
|
915
918
|
};
|
|
916
919
|
const MIN_TITLE = 24;
|
|
917
920
|
for (const give of [
|
|
@@ -953,7 +956,8 @@ var PrRow = ({
|
|
|
953
956
|
motion,
|
|
954
957
|
announcements = [],
|
|
955
958
|
columns,
|
|
956
|
-
shed
|
|
959
|
+
shed,
|
|
960
|
+
numberCols
|
|
957
961
|
}) => {
|
|
958
962
|
const backdropped = useBackdropped();
|
|
959
963
|
const { glyph: healthIcon, color: healthColor2 } = displayFor(item.health);
|
|
@@ -983,7 +987,8 @@ var PrRow = ({
|
|
|
983
987
|
uniformLabels,
|
|
984
988
|
announcements,
|
|
985
989
|
columns,
|
|
986
|
-
shed
|
|
990
|
+
shed,
|
|
991
|
+
numberCols
|
|
987
992
|
});
|
|
988
993
|
return /* @__PURE__ */ jsxs(Box, { width: cols, children: [
|
|
989
994
|
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
@@ -997,7 +1002,10 @@ var PrRow = ({
|
|
|
997
1002
|
bold: active || motion === "arriving",
|
|
998
1003
|
dimColor: motion === "departing" || motion === "withdrawn",
|
|
999
1004
|
strikethrough: motion === "withdrawn",
|
|
1000
|
-
children: truncate(
|
|
1005
|
+
children: truncate(
|
|
1006
|
+
item.needsYou?.decision ? item.needsYou.decision : item.title,
|
|
1007
|
+
titleMax
|
|
1008
|
+
) + " "
|
|
1001
1009
|
}
|
|
1002
1010
|
),
|
|
1003
1011
|
labelLabel ? /* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: labelLabel + " " }) : null,
|
|
@@ -1516,9 +1524,7 @@ var reposInSections = (sections) => [
|
|
|
1516
1524
|
)
|
|
1517
1525
|
].sort();
|
|
1518
1526
|
var moveCursor = (items, current, dir) => {
|
|
1519
|
-
|
|
1520
|
-
while (next >= 0 && next < items.length && items[next].kind === "subgroup-header")
|
|
1521
|
-
next += dir;
|
|
1527
|
+
const next = current + dir;
|
|
1522
1528
|
if (next < 0 || next >= items.length) return current;
|
|
1523
1529
|
return next;
|
|
1524
1530
|
};
|
|
@@ -1594,6 +1600,28 @@ var treeUrls = (items, i) => {
|
|
|
1594
1600
|
}
|
|
1595
1601
|
return urls;
|
|
1596
1602
|
};
|
|
1603
|
+
var bandUrls = (items, i) => {
|
|
1604
|
+
const urls = [];
|
|
1605
|
+
for (let j = i + 1; j < items.length; j += 1) {
|
|
1606
|
+
const item = items[j];
|
|
1607
|
+
if (item.kind === "subgroup-header") break;
|
|
1608
|
+
if (item.kind === "show-more") {
|
|
1609
|
+
for (const child of item.hidden) if (child.url) urls.push(child.url);
|
|
1610
|
+
continue;
|
|
1611
|
+
}
|
|
1612
|
+
const url = item.url;
|
|
1613
|
+
if (url) urls.push(url);
|
|
1614
|
+
}
|
|
1615
|
+
return urls;
|
|
1616
|
+
};
|
|
1617
|
+
var copyUrls = (items, i) => {
|
|
1618
|
+
const item = items[i];
|
|
1619
|
+
if (!item) return [];
|
|
1620
|
+
if (item.kind === "repo-header") return groupUrls(items, i);
|
|
1621
|
+
if (item.kind === "subgroup-header") return bandUrls(items, i);
|
|
1622
|
+
const url = item.url;
|
|
1623
|
+
return url ? [url] : [];
|
|
1624
|
+
};
|
|
1597
1625
|
var gapsAbove = (items, i) => {
|
|
1598
1626
|
const item = items[i];
|
|
1599
1627
|
if (!item || i === 0) return false;
|
|
@@ -1820,6 +1848,7 @@ var FRAME_PAD_X = 1;
|
|
|
1820
1848
|
var FRAME_CHROME_COLS = 2 + FRAME_PAD_X * 2;
|
|
1821
1849
|
var COLS = (process.stdout.columns ?? 120) - FRAME_CHROME_COLS;
|
|
1822
1850
|
var MODAL_CHROME_COLS = 2 + 1 * 2;
|
|
1851
|
+
var ROW_MAX_COLS = 140;
|
|
1823
1852
|
var OVERLAY_BG = "#22222e";
|
|
1824
1853
|
var workCount = (s) => {
|
|
1825
1854
|
let n = 0;
|
|
@@ -1994,7 +2023,10 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
1994
2023
|
(e) => {
|
|
1995
2024
|
showFlash(`\u2717 #${item.number}: ${explainGhAction(e)}`);
|
|
1996
2025
|
onRefresh?.();
|
|
1997
|
-
ext?.onSettled?.(item, {
|
|
2026
|
+
ext?.onSettled?.(item, {
|
|
2027
|
+
ok: false,
|
|
2028
|
+
reason: firstLine(e)
|
|
2029
|
+
});
|
|
1998
2030
|
}
|
|
1999
2031
|
);
|
|
2000
2032
|
}
|
|
@@ -2076,7 +2108,10 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
2076
2108
|
(e) => {
|
|
2077
2109
|
showFlash(`\u2717 Close failed \u2014 restoring #${item.number}`);
|
|
2078
2110
|
onRefresh?.();
|
|
2079
|
-
ext?.onSettled?.(item, {
|
|
2111
|
+
ext?.onSettled?.(item, {
|
|
2112
|
+
ok: false,
|
|
2113
|
+
reason: firstLine(e)
|
|
2114
|
+
});
|
|
2080
2115
|
}
|
|
2081
2116
|
);
|
|
2082
2117
|
}
|
|
@@ -2132,7 +2167,10 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
2132
2167
|
(e) => {
|
|
2133
2168
|
showFlash(`\u2717 Close failed \u2014 restoring #${item.number}`);
|
|
2134
2169
|
onRefresh?.();
|
|
2135
|
-
ext?.onSettled?.(item, {
|
|
2170
|
+
ext?.onSettled?.(item, {
|
|
2171
|
+
ok: false,
|
|
2172
|
+
reason: firstLine(e)
|
|
2173
|
+
});
|
|
2136
2174
|
}
|
|
2137
2175
|
);
|
|
2138
2176
|
}
|
|
@@ -2351,7 +2389,8 @@ var ItemRow = ({
|
|
|
2351
2389
|
markerCols = 0,
|
|
2352
2390
|
uniformLabels = [],
|
|
2353
2391
|
columns,
|
|
2354
|
-
shed
|
|
2392
|
+
shed,
|
|
2393
|
+
numberCols
|
|
2355
2394
|
}) => {
|
|
2356
2395
|
const backdropped = useBackdropped();
|
|
2357
2396
|
const transient = leaving ? "out" : refreshMark;
|
|
@@ -2362,7 +2401,8 @@ var ItemRow = ({
|
|
|
2362
2401
|
return /* @__PURE__ */ jsx(RepoHeaderRow, { repo: item.repo, gap: gap ?? false, active });
|
|
2363
2402
|
if (item.kind === "subgroup-header")
|
|
2364
2403
|
return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
|
|
2365
|
-
/* @__PURE__ */ jsx(Text3, { color: colors.
|
|
2404
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2405
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: true, children: "\xBB " }),
|
|
2366
2406
|
/* @__PURE__ */ jsx(Text3, { bold: true, children: item.label })
|
|
2367
2407
|
] });
|
|
2368
2408
|
if (item.kind === "show-more")
|
|
@@ -2444,6 +2484,7 @@ var ItemRow = ({
|
|
|
2444
2484
|
uniformLabels,
|
|
2445
2485
|
columns,
|
|
2446
2486
|
shed,
|
|
2487
|
+
numberCols,
|
|
2447
2488
|
icon,
|
|
2448
2489
|
motion,
|
|
2449
2490
|
announcements
|
|
@@ -2859,17 +2900,7 @@ var BrowseScreen = ({
|
|
|
2859
2900
|
s.items.length - 1
|
|
2860
2901
|
);
|
|
2861
2902
|
if (c < 0) return [s.id, 0];
|
|
2862
|
-
return [
|
|
2863
|
-
s.id,
|
|
2864
|
-
// Only `subgroup-header`, which is the one kind the arrows refuse to
|
|
2865
|
-
// stand on — `moveCursor` skips it and nothing else. A REPO header is
|
|
2866
|
-
// selectable on purpose: it opens the repo and `C` copies the group,
|
|
2867
|
-
// and the footer advertises both. Stepping off it here meant that
|
|
2868
|
-
// standing on a repo and pressing `r` moved you onto an issue, every
|
|
2869
|
-
// single time, and the rule predated repo headers being selectable
|
|
2870
|
-
// at all.
|
|
2871
|
-
s.items[c]?.kind === "subgroup-header" ? moveCursor(s.items, c, 1) : c
|
|
2872
|
-
];
|
|
2903
|
+
return [s.id, c];
|
|
2873
2904
|
})
|
|
2874
2905
|
)
|
|
2875
2906
|
);
|
|
@@ -2967,11 +2998,19 @@ var BrowseScreen = ({
|
|
|
2967
2998
|
const railCols = railWidth(COLS);
|
|
2968
2999
|
const listCols = showRail ? COLS - railCols : COLS;
|
|
2969
3000
|
const trailingColumns = trailingColumnsOf(labelBearing);
|
|
3001
|
+
const numberCols = numberColumnsOf(labelBearing);
|
|
3002
|
+
const rowCols = Math.min(listCols, ROW_MAX_COLS);
|
|
2970
3003
|
const trailingShed = sectionShedOf(
|
|
2971
3004
|
section.items.flatMap(
|
|
2972
3005
|
(item, i) => item.kind === "pr" || item.kind === "issue" ? [{ item, prefix: treePrefix(section.items, i) }] : []
|
|
2973
3006
|
),
|
|
2974
|
-
{
|
|
3007
|
+
{
|
|
3008
|
+
login,
|
|
3009
|
+
cols: rowCols,
|
|
3010
|
+
uniformLabels,
|
|
3011
|
+
columns: trailingColumns,
|
|
3012
|
+
numberCols
|
|
3013
|
+
}
|
|
2975
3014
|
);
|
|
2976
3015
|
const [sparkFrame, setSparkFrame] = useState(0);
|
|
2977
3016
|
const sparkling = (mergedUrls?.length ?? 0) > 0 || (leavingUrls?.length ?? 0) > 0 || // Any MARKED TAB, not just rows on screen. The scope used to be this tab's
|
|
@@ -3198,8 +3237,10 @@ var BrowseScreen = ({
|
|
|
3198
3237
|
return;
|
|
3199
3238
|
}
|
|
3200
3239
|
if (input === "c") {
|
|
3201
|
-
|
|
3202
|
-
|
|
3240
|
+
const urls = copyUrls(section.items, cursor);
|
|
3241
|
+
if (urls.length === 0) return;
|
|
3242
|
+
clipboard(urls.join("\n"));
|
|
3243
|
+
showFlash(`\u2713 Copied ${urls.length} link${urls.length === 1 ? "" : "s"}`);
|
|
3203
3244
|
return;
|
|
3204
3245
|
}
|
|
3205
3246
|
if (input === "C" || input === "O") {
|
|
@@ -3218,7 +3259,16 @@ var BrowseScreen = ({
|
|
|
3218
3259
|
}
|
|
3219
3260
|
return;
|
|
3220
3261
|
}
|
|
3221
|
-
if (
|
|
3262
|
+
if (activeItem?.kind === "subgroup-header") {
|
|
3263
|
+
if (input === "c") {
|
|
3264
|
+
const urls = copyUrls(section.items, cursor);
|
|
3265
|
+
if (urls.length === 0) return;
|
|
3266
|
+
clipboard(urls.join("\n"));
|
|
3267
|
+
showFlash(`\u2713 Copied ${urls.length} link${urls.length === 1 ? "" : "s"}`);
|
|
3268
|
+
}
|
|
3269
|
+
return;
|
|
3270
|
+
}
|
|
3271
|
+
if (!activeItem) return;
|
|
3222
3272
|
if (key.return && activeItem.kind === "show-more") {
|
|
3223
3273
|
setLocalSections(
|
|
3224
3274
|
(prev) => prev.map((s) => ({
|
|
@@ -3410,6 +3460,11 @@ var BrowseScreen = ({
|
|
|
3410
3460
|
menu.open(actions);
|
|
3411
3461
|
}
|
|
3412
3462
|
});
|
|
3463
|
+
const headerLinks = activeItem?.kind === "repo-header" || activeItem?.kind === "subgroup-header" ? copyUrls(section.items, cursor).length : 0;
|
|
3464
|
+
const headerHint = [
|
|
3465
|
+
"c",
|
|
3466
|
+
`copy ${headerLinks} link${headerLinks === 1 ? "" : "s"}`
|
|
3467
|
+
];
|
|
3413
3468
|
const hints = railActive ? (
|
|
3414
3469
|
// The rail's own keymap while it holds focus, not the list's with a line
|
|
3415
3470
|
// bolted on. A footer advertising `m actions` beside a cursor that cannot
|
|
@@ -3429,7 +3484,13 @@ var BrowseScreen = ({
|
|
|
3429
3484
|
["\u2190\u2192", "tab"],
|
|
3430
3485
|
["\u21B5", "open repo"],
|
|
3431
3486
|
["o", "browser"],
|
|
3432
|
-
|
|
3487
|
+
headerHint,
|
|
3488
|
+
["?", "help"],
|
|
3489
|
+
["q", "quit"]
|
|
3490
|
+
] : activeItem?.kind === "subgroup-header" ? [
|
|
3491
|
+
["\u2191\u2193", "nav"],
|
|
3492
|
+
["\u2190\u2192", "tab"],
|
|
3493
|
+
headerHint,
|
|
3433
3494
|
["?", "help"],
|
|
3434
3495
|
["q", "quit"]
|
|
3435
3496
|
] : [
|
|
@@ -3667,11 +3728,12 @@ var BrowseScreen = ({
|
|
|
3667
3728
|
prefix: treePrefix(section.items, viewStart + i),
|
|
3668
3729
|
parent: item.kind === "task" && depthOf(section.items[viewStart + i + 1]) > depthOf(item),
|
|
3669
3730
|
sparkFrame,
|
|
3670
|
-
cols: listCols,
|
|
3731
|
+
cols: item.kind === "pr" || item.kind === "issue" ? rowCols : listCols,
|
|
3671
3732
|
markerCols,
|
|
3672
3733
|
uniformLabels,
|
|
3673
3734
|
columns: trailingColumns,
|
|
3674
3735
|
shed: trailingShed,
|
|
3736
|
+
numberCols,
|
|
3675
3737
|
gap: i > 0 && gapsAbove(section.items, viewStart + i)
|
|
3676
3738
|
},
|
|
3677
3739
|
`${viewStart + i}:${rowKey(item)}`
|
|
@@ -4260,4 +4322,4 @@ var matchesFilter = (repo, filter) => {
|
|
|
4260
4322
|
};
|
|
4261
4323
|
var parsePatterns = (value) => value.split(",").map((p) => p.trim()).filter(Boolean);
|
|
4262
4324
|
|
|
4263
|
-
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, MIN_SIDEBAR_COLS, PrRow, SIDEBAR_COLS, SidePanel, StatusStripLine, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sectionShedOf, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, trailingColumnsOf, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
|
|
4325
|
+
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, MIN_SIDEBAR_COLS, PrRow, SIDEBAR_COLS, SidePanel, StatusStripLine, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, numberColumnsOf, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sectionShedOf, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, trailingColumnsOf, 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.65.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",
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
"react": ">=19"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@kud/gh": "0.
|
|
52
|
-
"@kud/gh-workflow": "0.
|
|
51
|
+
"@kud/gh": "0.19.0",
|
|
52
|
+
"@kud/gh-workflow": "0.14.0",
|
|
53
53
|
"@kud/ink-ui": "0.31.0",
|
|
54
54
|
"zx": "8.8.5"
|
|
55
55
|
},
|