@kud/gh-ink 0.23.2 → 0.23.3
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 +15 -16
- package/dist/index.js +12 -38
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -238,6 +238,20 @@ declare const filterByRepos: (sections: Section[], repos: Set<string>) => Sectio
|
|
|
238
238
|
declare const withoutItem: (sections: Section[], target: GHItem) => Section[];
|
|
239
239
|
declare const reposInSections: (sections: Section[]) => string[];
|
|
240
240
|
declare const moveCursor: (items: AnyItem[], current: number, dir: 1 | -1) => number;
|
|
241
|
+
/**
|
|
242
|
+
* Whether this row draws a blank line above it.
|
|
243
|
+
*
|
|
244
|
+
* ONE definition, because two readers need the same answer: the renderer draws
|
|
245
|
+
* the gap, and fitCount pays for it out of the window budget. They disagreed
|
|
246
|
+
* until 2026-08-27 — fitCount priced only headers at two lines while the
|
|
247
|
+
* renderer ALSO gapped a task row following a header — so a tab with that shape
|
|
248
|
+
* drew one line more than the window had bought. The frame is sized to fill the
|
|
249
|
+
* terminal exactly, so the overflow scrolls the whole panel instead of clipping.
|
|
250
|
+
*
|
|
251
|
+
* Index-based rather than item-based: whether a row gaps depends on what sits
|
|
252
|
+
* above it, which an item alone cannot answer.
|
|
253
|
+
*/
|
|
254
|
+
declare const gapsAbove: (items: readonly AnyItem[], i: number) => boolean;
|
|
241
255
|
declare const fitCount: (items: AnyItem[], start: number, budget: number) => number;
|
|
242
256
|
declare const windowCount: (items: AnyItem[], start: number, budget: number) => number;
|
|
243
257
|
declare const maxViewStart: (items: AnyItem[], budget: number) => number;
|
|
@@ -282,21 +296,6 @@ declare const CiStatusLine: ({ state, job, }: {
|
|
|
282
296
|
state: CiStatusState;
|
|
283
297
|
job?: string;
|
|
284
298
|
}) => React.JSX.Element;
|
|
285
|
-
/**
|
|
286
|
-
* Indexes of task rows whose row has already appeared higher up the same list.
|
|
287
|
-
*
|
|
288
|
-
* A ticket with one PR needing you and another in review lands in two bands,
|
|
289
|
-
* which is right — the band reads each PR, not the ticket. What was wrong was
|
|
290
|
-
* drawing the second occurrence identically to the first, so one ticket read as
|
|
291
|
-
* two. The repeat keeps its key and drops its summary.
|
|
292
|
-
*
|
|
293
|
-
* Identity is the URL, never `key`. `key` is a LABEL, and on a task surface that
|
|
294
|
-
* is not a tracker (`life`, whose keys are categories like "Flat") one label
|
|
295
|
-
* legitimately heads several unrelated rows — keying on it hid the summary of
|
|
296
|
-
* every row but the first. A row with no url is never a repeat, because nothing
|
|
297
|
-
* identifies it.
|
|
298
|
-
*/
|
|
299
|
-
declare const repeatedTaskRows: (items: readonly AnyItem[]) => Set<number>;
|
|
300
299
|
declare const useActionMenu: () => {
|
|
301
300
|
actions: Action[] | null;
|
|
302
301
|
cursor: number;
|
|
@@ -444,4 +443,4 @@ declare const matchesFilter: (repo: string, filter: RepoFilter) => boolean;
|
|
|
444
443
|
*/
|
|
445
444
|
declare const parsePatterns: (value: string) => string[];
|
|
446
445
|
|
|
447
|
-
export { type Action, ActionMenu, type AnyItem, App, COLS, type CiStatus, CiStatusLine, type CiStatusState, CommentsPanel, type CommentsPanelProps, type DetailContext, type ExplainSection, type ExtensionTarget, type GHDetail, type GHItem, HealthPanel, type HealthPanelProps, type InboxConfig, type InboxExtension, type JiraTransition, type OriginSplit, type RepoFilter, type RepoHeader, type RepoProfile, type Section, type ShowLess, type ShowMore, type Standing, type SubgroupHeader, type TaskRow, buildActions, buildCheckoutCmd, checkoutDirs, clipboard, configureInbox, drillCmd, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, profileOf, readCache, relativeTime, renderMarkdown,
|
|
446
|
+
export { type Action, ActionMenu, type AnyItem, App, COLS, type CiStatus, CiStatusLine, type CiStatusState, CommentsPanel, type CommentsPanelProps, type DetailContext, type ExplainSection, type ExtensionTarget, type GHDetail, type GHItem, HealthPanel, type HealthPanelProps, type InboxConfig, type InboxExtension, type JiraTransition, type OriginSplit, type RepoFilter, type RepoHeader, type RepoProfile, type Section, type ShowLess, type ShowMore, type Standing, type SubgroupHeader, type TaskRow, buildActions, buildCheckoutCmd, checkoutDirs, clipboard, configureInbox, drillCmd, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, profileOf, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, whoseMove, windowCount, withHeaders, withoutItem, writeCache };
|
package/dist/index.js
CHANGED
|
@@ -1028,12 +1028,17 @@ var moveCursor = (items, current2, dir) => {
|
|
|
1028
1028
|
if (next < 0 || next >= items.length) return current2;
|
|
1029
1029
|
return next;
|
|
1030
1030
|
};
|
|
1031
|
-
var
|
|
1031
|
+
var gapsAbove = (items, i) => {
|
|
1032
|
+
const item = items[i];
|
|
1033
|
+
if (!item || i === 0) return false;
|
|
1034
|
+
if (item.kind === "repo-header" || item.kind === "subgroup-header") return true;
|
|
1035
|
+
return item.kind === "task";
|
|
1036
|
+
};
|
|
1032
1037
|
var fitCount = (items, start, budget) => {
|
|
1033
1038
|
let lines = 0;
|
|
1034
1039
|
let count = 0;
|
|
1035
1040
|
for (let i = start; i < items.length; i++) {
|
|
1036
|
-
const cost =
|
|
1041
|
+
const cost = i !== start && gapsAbove(items, i) ? 2 : 1;
|
|
1037
1042
|
if (lines + cost > budget) break;
|
|
1038
1043
|
lines += cost;
|
|
1039
1044
|
count++;
|
|
@@ -1685,16 +1690,6 @@ var TRANSIT_LABEL = {
|
|
|
1685
1690
|
};
|
|
1686
1691
|
var TAB_MARK = "\u25CF";
|
|
1687
1692
|
var tabLabel = (label, marked, id) => marked.size === 0 ? label : `${marked.has(id) ? TAB_MARK : " "} ${label}`;
|
|
1688
|
-
var repeatedTaskRows = (items) => {
|
|
1689
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1690
|
-
const repeats = /* @__PURE__ */ new Set();
|
|
1691
|
-
items.forEach((row, i) => {
|
|
1692
|
-
if (row.kind !== "task" || !row.url) return;
|
|
1693
|
-
if (seen.has(row.url)) repeats.add(i);
|
|
1694
|
-
else seen.add(row.url);
|
|
1695
|
-
});
|
|
1696
|
-
return repeats;
|
|
1697
|
-
};
|
|
1698
1693
|
var isChildRow = (item) => !!item && (item.kind === "show-more" || item.kind === "show-less" || "indent" in item && item.indent === true);
|
|
1699
1694
|
var ItemRow = ({
|
|
1700
1695
|
item,
|
|
@@ -1705,7 +1700,6 @@ var ItemRow = ({
|
|
|
1705
1700
|
transient,
|
|
1706
1701
|
lastChild,
|
|
1707
1702
|
parent,
|
|
1708
|
-
repeat,
|
|
1709
1703
|
sparkFrame = 0
|
|
1710
1704
|
}) => {
|
|
1711
1705
|
if (item.kind === "repo-header")
|
|
@@ -1741,8 +1735,8 @@ var ItemRow = ({
|
|
|
1741
1735
|
/* @__PURE__ */ jsx(Text2, { color: "cyan", children: active ? "\u276F " : " " }),
|
|
1742
1736
|
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: parent ? "\u252C " : " " }),
|
|
1743
1737
|
/* @__PURE__ */ jsx(Text2, { bold: true, color: transient ? TRANSIT_COLOUR[transient] : void 0, children: transitIcon + " " }),
|
|
1744
|
-
/* @__PURE__ */ jsx(Text2, { color:
|
|
1745
|
-
|
|
1738
|
+
/* @__PURE__ */ jsx(Text2, { color: "#FF8700", bold: active, children: item.key + " " }),
|
|
1739
|
+
/* @__PURE__ */ jsx(
|
|
1746
1740
|
Text2,
|
|
1747
1741
|
{
|
|
1748
1742
|
bold: active || transient === "in",
|
|
@@ -1751,7 +1745,7 @@ var ItemRow = ({
|
|
|
1751
1745
|
children: truncate(item.summary, titleMax2)
|
|
1752
1746
|
}
|
|
1753
1747
|
),
|
|
1754
|
-
note
|
|
1748
|
+
note ? /* @__PURE__ */ jsx(Text2, { dimColor: true, children: ` ${note}` }) : null,
|
|
1755
1749
|
transitLabel2 ? /* @__PURE__ */ jsx(Text2, { bold: true, color: TRANSIT_COLOUR[transient], children: " " + transitLabel2 }) : null
|
|
1756
1750
|
] });
|
|
1757
1751
|
}
|
|
@@ -2209,10 +2203,6 @@ var BrowseScreen = ({
|
|
|
2209
2203
|
{ vimKeys: false, isActive: repoPicker }
|
|
2210
2204
|
);
|
|
2211
2205
|
const cursor = cursors[activeId] ?? 0;
|
|
2212
|
-
const repeatedTasks = useMemo(
|
|
2213
|
-
() => repeatedTaskRows(section.items),
|
|
2214
|
-
[section.items]
|
|
2215
|
-
);
|
|
2216
2206
|
const viewStart = viewStarts[activeId] ?? 0;
|
|
2217
2207
|
const visibleCount = windowCount(section.items, viewStart, listHeight);
|
|
2218
2208
|
const visibleItems = section.items.slice(viewStart, viewStart + visibleCount);
|
|
@@ -2624,24 +2614,8 @@ var BrowseScreen = ({
|
|
|
2624
2614
|
transient: transientOf(transients, item),
|
|
2625
2615
|
lastChild: "indent" in item && item.indent ? !isChildRow(section.items[viewStart + i + 1]) : void 0,
|
|
2626
2616
|
parent: item.kind === "task" && isChildRow(section.items[viewStart + i + 1]),
|
|
2627
|
-
repeat: repeatedTasks.has(viewStart + i),
|
|
2628
2617
|
sparkFrame,
|
|
2629
|
-
gap: (
|
|
2630
|
-
// Window-relative, never `viewStart + i`. fitCount prices the
|
|
2631
|
-
// window's FIRST row at one line (isFirst), so gapping it when
|
|
2632
|
-
// scrolled draws a row the budget never bought — and the frame
|
|
2633
|
-
// is sized to fill the terminal exactly, so the overflow scrolls
|
|
2634
|
-
// the whole panel up a line instead of clipping.
|
|
2635
|
-
i > 0 && (item.kind === "repo-header" || item.kind === "subgroup-header" || // A header is always followed by a blank line before its
|
|
2636
|
-
// first child — in Other PRs that's "free" because the
|
|
2637
|
-
// child is itself a repo-header (gap above). A task row
|
|
2638
|
-
// has no such stand-in, so it needs this explicitly. Never
|
|
2639
|
-
// applies between two tickets/PRs — only right after a
|
|
2640
|
-
// header.
|
|
2641
|
-
item.kind === "task" && ["repo-header", "subgroup-header"].includes(
|
|
2642
|
-
section.items[viewStart + i - 1]?.kind
|
|
2643
|
-
))
|
|
2644
|
-
)
|
|
2618
|
+
gap: i > 0 && gapsAbove(section.items, viewStart + i)
|
|
2645
2619
|
},
|
|
2646
2620
|
`${viewStart + i}:${item.kind === "task" ? 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}`}`
|
|
2647
2621
|
)) }),
|
|
@@ -3035,4 +3009,4 @@ var matchesFilter = (repo, filter) => {
|
|
|
3035
3009
|
};
|
|
3036
3010
|
var parsePatterns = (value) => value.split(",").map((p) => p.trim()).filter(Boolean);
|
|
3037
3011
|
|
|
3038
|
-
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, buildActions, buildCheckoutCmd, checkoutDirs, clipboard, configureInbox, drillCmd, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, profileOf, readCache, relativeTime, renderMarkdown,
|
|
3012
|
+
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, buildActions, buildCheckoutCmd, checkoutDirs, clipboard, configureInbox, drillCmd, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, profileOf, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, whoseMove, windowCount, withHeaders, withoutItem, writeCache };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kud/gh-ink",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.3",
|
|
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",
|