@kud/gh-ink 0.13.0 → 0.15.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 +18 -5
- package/dist/index.js +92 -40
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -76,12 +76,12 @@ type GHItem = {
|
|
|
76
76
|
detail?: GHDetail;
|
|
77
77
|
indent: boolean;
|
|
78
78
|
};
|
|
79
|
-
type
|
|
80
|
-
kind: "
|
|
79
|
+
type TaskRow = {
|
|
80
|
+
kind: "task";
|
|
81
81
|
key: string;
|
|
82
82
|
summary: string;
|
|
83
83
|
url: string;
|
|
84
|
-
|
|
84
|
+
status: string;
|
|
85
85
|
age: string;
|
|
86
86
|
indent: boolean;
|
|
87
87
|
instanceKey?: string;
|
|
@@ -92,6 +92,19 @@ type JiraRow = {
|
|
|
92
92
|
* separately instead of being smuggled past the truncation maths.
|
|
93
93
|
*/
|
|
94
94
|
note?: string;
|
|
95
|
+
/**
|
|
96
|
+
* The Jira issue key behind this row, when one exists. Its PRESENCE is what
|
|
97
|
+
* turns on the ticket affordances — ↵ opens a menu led by `jira issue view`,
|
|
98
|
+
* and `t` transitions the issue. A row without it is just a task: ↵ opens its
|
|
99
|
+
* URL and nothing here shells out to `jira`.
|
|
100
|
+
*
|
|
101
|
+
* Separate from `key` because the two are not the same thing. `key` is the
|
|
102
|
+
* left column, and a caller is free to put anything legible there: cockpit
|
|
103
|
+
* puts the ticket key, `life` puts a Todoist project name. Reading the drill
|
|
104
|
+
* off `key` is what made `life` run `jira issue view "Maison "` and
|
|
105
|
+
* label it "View ticket" on a surface that has never touched Jira.
|
|
106
|
+
*/
|
|
107
|
+
ticket?: string;
|
|
95
108
|
};
|
|
96
109
|
type RepoHeader = {
|
|
97
110
|
kind: "repo-header";
|
|
@@ -115,7 +128,7 @@ type SubgroupHeader = {
|
|
|
115
128
|
age: string;
|
|
116
129
|
indent: boolean;
|
|
117
130
|
};
|
|
118
|
-
type AnyItem = GHItem |
|
|
131
|
+
type AnyItem = GHItem | TaskRow | RepoHeader | SubgroupHeader | ShowMore | ShowLess;
|
|
119
132
|
type CiStatus = {
|
|
120
133
|
job: string;
|
|
121
134
|
buildNumber: number;
|
|
@@ -275,4 +288,4 @@ declare const writeCache: (key: string, data: {
|
|
|
275
288
|
login: string;
|
|
276
289
|
}) => void;
|
|
277
290
|
|
|
278
|
-
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 InboxExtension, type
|
|
291
|
+
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 InboxExtension, type JiraTransition, type RepoHeader, type Section, type ShowLess, type ShowMore, type SubgroupHeader, type TaskRow, buildActions, buildCheckoutCmd, clipboard, drillCmd, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, healthColor, healthDisplay, healthGlyph, healthLegend, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, maxViewStart, moveCursor, openInTab, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, windowCount, withHeaders, withoutItem, writeCache };
|
package/dist/index.js
CHANGED
|
@@ -607,7 +607,7 @@ var healthLegend = [
|
|
|
607
607
|
["closed", "Closed"]
|
|
608
608
|
];
|
|
609
609
|
var CACHE_TTL_MS = 12e4;
|
|
610
|
-
var CACHE_VERSION =
|
|
610
|
+
var CACHE_VERSION = 2;
|
|
611
611
|
var cacheDir = () => join(process.env.XDG_CACHE_HOME || join(homedir(), ".cache"), "ambre");
|
|
612
612
|
var cacheFile = (key) => join(cacheDir(), `${key.replace(/[^a-z0-9._-]/gi, "-")}.json`);
|
|
613
613
|
var readCache = (key) => {
|
|
@@ -641,9 +641,9 @@ var invalidateCache = (key) => {
|
|
|
641
641
|
// src/inbox/diff.ts
|
|
642
642
|
var keyOf = (item) => {
|
|
643
643
|
if (item.kind === "pr" || item.kind === "issue") return item.url;
|
|
644
|
-
if (item.kind === "
|
|
644
|
+
if (item.kind === "task") {
|
|
645
645
|
const row = item;
|
|
646
|
-
return row.url || `
|
|
646
|
+
return row.url || `task:${row.key}`;
|
|
647
647
|
}
|
|
648
648
|
return null;
|
|
649
649
|
};
|
|
@@ -659,9 +659,9 @@ var renderedState = (item) => {
|
|
|
659
659
|
i.author ?? ""
|
|
660
660
|
].join("|");
|
|
661
661
|
}
|
|
662
|
-
if (item.kind === "
|
|
662
|
+
if (item.kind === "task") {
|
|
663
663
|
const j = item;
|
|
664
|
-
return [j.summary, j.
|
|
664
|
+
return [j.summary, j.status].join("|");
|
|
665
665
|
}
|
|
666
666
|
return "";
|
|
667
667
|
};
|
|
@@ -733,6 +733,15 @@ var transientOf = (transients, item) => {
|
|
|
733
733
|
const key = keyOf(item);
|
|
734
734
|
return key ? transients.get(key) : void 0;
|
|
735
735
|
};
|
|
736
|
+
var tabsOfMarks = (sections, marks) => {
|
|
737
|
+
const out = /* @__PURE__ */ new Map();
|
|
738
|
+
for (const section of sections)
|
|
739
|
+
for (const item of section.items) {
|
|
740
|
+
const key = keyOf(item);
|
|
741
|
+
if (key && marks.has(key)) out.set(key, section.id);
|
|
742
|
+
}
|
|
743
|
+
return out;
|
|
744
|
+
};
|
|
736
745
|
var quietly = $({ quiet: true });
|
|
737
746
|
var relativeTime = (iso) => {
|
|
738
747
|
const diff = (Date.now() - new Date(iso).getTime()) / 1e3;
|
|
@@ -881,7 +890,7 @@ var filterByOrigin = (sections, keep, isWorkRepo) => sections.map((s) => {
|
|
|
881
890
|
(i) => i.kind !== "repo-header" && i.kind !== "subgroup-header"
|
|
882
891
|
)
|
|
883
892
|
);
|
|
884
|
-
var searchText = (i) => i.kind === "pr" || i.kind === "issue" ? `${i.title} ${i.repo} #${i.number}` : i.kind === "
|
|
893
|
+
var searchText = (i) => i.kind === "pr" || i.kind === "issue" ? `${i.title} ${i.repo} #${i.number}` : i.kind === "task" ? `${i.summary} ${i.key}` : "";
|
|
885
894
|
var filterBySearch = (sections, query) => {
|
|
886
895
|
const q = query.trim().toLowerCase();
|
|
887
896
|
if (!q) return sections;
|
|
@@ -1202,11 +1211,12 @@ var topLevelCount = (s) => s.items.filter(
|
|
|
1202
1211
|
(i) => i.kind !== "repo-header" && i.kind !== "subgroup-header" && !i.indent
|
|
1203
1212
|
).length;
|
|
1204
1213
|
var drillCmd = (item) => {
|
|
1205
|
-
if (item.kind === "
|
|
1214
|
+
if (item.kind === "task")
|
|
1215
|
+
return item.ticket ? `jira issue view ${item.ticket}` : null;
|
|
1206
1216
|
return null;
|
|
1207
1217
|
};
|
|
1208
1218
|
var drillLabel = (item) => {
|
|
1209
|
-
if (item.kind === "
|
|
1219
|
+
if (item.kind === "task") return "View ticket";
|
|
1210
1220
|
if (item.kind === "issue") return "View issue";
|
|
1211
1221
|
if (item.kind === "pr") return "Open PR";
|
|
1212
1222
|
return "Drill in";
|
|
@@ -1228,7 +1238,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
1228
1238
|
hint: "c",
|
|
1229
1239
|
run: () => {
|
|
1230
1240
|
clipboard(item.url);
|
|
1231
|
-
const label = item.kind === "
|
|
1241
|
+
const label = item.kind === "task" ? item.key : `#${item.number}`;
|
|
1232
1242
|
showFlash(`\u2713 Copied URL for ${label}`);
|
|
1233
1243
|
}
|
|
1234
1244
|
};
|
|
@@ -1246,9 +1256,9 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
1246
1256
|
}
|
|
1247
1257
|
}
|
|
1248
1258
|
} : null;
|
|
1249
|
-
if (item.kind === "
|
|
1259
|
+
if (item.kind === "task") {
|
|
1250
1260
|
const base = drillAction ? [drillAction, open, copyUrl] : [open, copyUrl];
|
|
1251
|
-
if (jiraTransitions && jiraTransitions.length > 0) {
|
|
1261
|
+
if (item.ticket && jiraTransitions && jiraTransitions.length > 0) {
|
|
1252
1262
|
base.push({
|
|
1253
1263
|
label: "Move status",
|
|
1254
1264
|
hint: "t",
|
|
@@ -1265,7 +1275,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
1265
1275
|
hint: "",
|
|
1266
1276
|
run: () => {
|
|
1267
1277
|
showFlash(`\u22EF ${label} \xB7 ${resolution}\u2026`);
|
|
1268
|
-
void quietly`jira issue move ${item.
|
|
1278
|
+
void quietly`jira issue move ${item.ticket} ${state} --resolution ${resolution}`.then(() => {
|
|
1269
1279
|
showFlash(`\u2713 ${label} \xB7 ${resolution}`);
|
|
1270
1280
|
ext?.onActed?.();
|
|
1271
1281
|
}).catch(() => showFlash(`\u2717 Move to ${label} failed`));
|
|
@@ -1276,7 +1286,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
1276
1286
|
hint: "",
|
|
1277
1287
|
run: () => {
|
|
1278
1288
|
showFlash(`\u22EF Moving to ${label}\u2026`);
|
|
1279
|
-
void quietly`jira issue move ${item.
|
|
1289
|
+
void quietly`jira issue move ${item.ticket} ${state}`.then(() => {
|
|
1280
1290
|
showFlash(`\u2713 Moved to ${label}`);
|
|
1281
1291
|
ext?.onActed?.();
|
|
1282
1292
|
}).catch(() => showFlash(`\u2717 Move to ${label} failed`));
|
|
@@ -1604,7 +1614,7 @@ var ItemRow = ({
|
|
|
1604
1614
|
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: active ? "\u21B5 " : " " }),
|
|
1605
1615
|
/* @__PURE__ */ jsx(Text2, { dimColor: true, children: "show less" })
|
|
1606
1616
|
] });
|
|
1607
|
-
if (item.kind === "
|
|
1617
|
+
if (item.kind === "task") {
|
|
1608
1618
|
const note = item.note ?? "";
|
|
1609
1619
|
const titleMax2 = Math.max(20, COLS - item.key.length - note.length - 10);
|
|
1610
1620
|
return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
|
|
@@ -1689,7 +1699,7 @@ var ActionMenu = ({
|
|
|
1689
1699
|
actions,
|
|
1690
1700
|
cursor
|
|
1691
1701
|
}) => {
|
|
1692
|
-
const title = item.kind === "
|
|
1702
|
+
const title = item.kind === "task" ? item.key : item.kind === "pr" || item.kind === "issue" ? `#${item.number}` : "";
|
|
1693
1703
|
return /* @__PURE__ */ jsxs(
|
|
1694
1704
|
Box,
|
|
1695
1705
|
{
|
|
@@ -1946,7 +1956,8 @@ var BrowseScreen = ({
|
|
|
1946
1956
|
initialIncludeWork,
|
|
1947
1957
|
brand,
|
|
1948
1958
|
mergedUrls,
|
|
1949
|
-
transients
|
|
1959
|
+
transients,
|
|
1960
|
+
onTabChange
|
|
1950
1961
|
}) => {
|
|
1951
1962
|
const { rows } = useWindowSize();
|
|
1952
1963
|
const [includeWork, setIncludeWork] = useState(
|
|
@@ -1962,6 +1973,9 @@ var BrowseScreen = ({
|
|
|
1962
1973
|
const [viewStarts, setViewStarts] = useState({});
|
|
1963
1974
|
const safeTabIdx = Math.min(tabIdx, Math.max(0, localSections.length - 1));
|
|
1964
1975
|
const activeId = localSections[safeTabIdx]?.id ?? "";
|
|
1976
|
+
useEffect(() => {
|
|
1977
|
+
onTabChange?.(activeId);
|
|
1978
|
+
}, [activeId]);
|
|
1965
1979
|
const [flash, setFlash] = useState(null);
|
|
1966
1980
|
const menu = useActionMenu();
|
|
1967
1981
|
const [search, setSearch] = useState(null);
|
|
@@ -2037,7 +2051,7 @@ var BrowseScreen = ({
|
|
|
2037
2051
|
setTimeout(() => setFlash(null), 2e3);
|
|
2038
2052
|
};
|
|
2039
2053
|
const [sparkFrame, setSparkFrame] = useState(0);
|
|
2040
|
-
const sparkling = (mergedUrls?.length ?? 0) > 0 ||
|
|
2054
|
+
const sparkling = (mergedUrls?.length ?? 0) > 0 || !!transients?.size && section.items.some((item) => transientOf(transients, item));
|
|
2041
2055
|
useEffect(() => {
|
|
2042
2056
|
if (!sparkling) return;
|
|
2043
2057
|
const id = setInterval(() => setSparkFrame((f) => f + 1), MERGED_FRAME_MS);
|
|
@@ -2222,6 +2236,12 @@ var BrowseScreen = ({
|
|
|
2222
2236
|
return;
|
|
2223
2237
|
if (key.return) {
|
|
2224
2238
|
if (openDrillView(activeItem)) return;
|
|
2239
|
+
if (activeItem.kind === "task" && !activeItem.ticket) {
|
|
2240
|
+
void quietly`open ${activeItem.url}`.catch(() => {
|
|
2241
|
+
});
|
|
2242
|
+
showFlash("\u2197 Opened in browser");
|
|
2243
|
+
return;
|
|
2244
|
+
}
|
|
2225
2245
|
openMenu();
|
|
2226
2246
|
return;
|
|
2227
2247
|
}
|
|
@@ -2236,13 +2256,13 @@ var BrowseScreen = ({
|
|
|
2236
2256
|
if (input === "o") {
|
|
2237
2257
|
quietly`open ${activeItem.url}`.catch(() => {
|
|
2238
2258
|
});
|
|
2239
|
-
const label = activeItem.kind === "
|
|
2259
|
+
const label = activeItem.kind === "task" ? activeItem.key : `#${activeItem.number}`;
|
|
2240
2260
|
showFlash(`\u2197 Opened ${label}`);
|
|
2241
2261
|
return;
|
|
2242
2262
|
}
|
|
2243
2263
|
if (input === "c") {
|
|
2244
2264
|
clipboard(activeItem.url);
|
|
2245
|
-
const label = activeItem.kind === "
|
|
2265
|
+
const label = activeItem.kind === "task" ? activeItem.key : `#${activeItem.number}`;
|
|
2246
2266
|
showFlash(`\u2713 Copied URL for ${label}`);
|
|
2247
2267
|
return;
|
|
2248
2268
|
}
|
|
@@ -2261,7 +2281,7 @@ var BrowseScreen = ({
|
|
|
2261
2281
|
showFlash(`\u2713 Copied ${activeItem.branch}`);
|
|
2262
2282
|
return;
|
|
2263
2283
|
}
|
|
2264
|
-
if (activeItem.kind !== "
|
|
2284
|
+
if (activeItem.kind !== "task") {
|
|
2265
2285
|
if (input === "s" && activeItem.kind === "pr" && activeItem.branch) {
|
|
2266
2286
|
const script = [
|
|
2267
2287
|
"delay 0.5",
|
|
@@ -2286,8 +2306,8 @@ var BrowseScreen = ({
|
|
|
2286
2306
|
return;
|
|
2287
2307
|
}
|
|
2288
2308
|
}
|
|
2289
|
-
if (input === "t" && activeItem && activeItem.kind === "
|
|
2290
|
-
const jiraKey = activeItem.
|
|
2309
|
+
if (input === "t" && activeItem && activeItem.kind === "task" && activeItem.ticket && jiraTransitions && jiraTransitions.length > 0) {
|
|
2310
|
+
const jiraKey = activeItem.ticket;
|
|
2291
2311
|
const actions = jiraTransitions.map(
|
|
2292
2312
|
({ label, state, resolutions }) => resolutions && resolutions.length > 0 ? {
|
|
2293
2313
|
label,
|
|
@@ -2414,16 +2434,16 @@ var BrowseScreen = ({
|
|
|
2414
2434
|
// the whole panel up a line instead of clipping.
|
|
2415
2435
|
i > 0 && (item.kind === "repo-header" || item.kind === "subgroup-header" || // A header is always followed by a blank line before its
|
|
2416
2436
|
// first child — in Other PRs that's "free" because the
|
|
2417
|
-
// child is itself a repo-header (gap above). A
|
|
2437
|
+
// child is itself a repo-header (gap above). A task row
|
|
2418
2438
|
// has no such stand-in, so it needs this explicitly. Never
|
|
2419
2439
|
// applies between two tickets/PRs — only right after a
|
|
2420
2440
|
// header.
|
|
2421
|
-
item.kind === "
|
|
2441
|
+
item.kind === "task" && ["repo-header", "subgroup-header"].includes(
|
|
2422
2442
|
section.items[viewStart + i - 1]?.kind
|
|
2423
2443
|
))
|
|
2424
2444
|
)
|
|
2425
2445
|
},
|
|
2426
|
-
`${viewStart + i}:${item.kind === "
|
|
2446
|
+
`${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}`}`
|
|
2427
2447
|
)) }),
|
|
2428
2448
|
hasMore && /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
|
|
2429
2449
|
" ",
|
|
@@ -2508,13 +2528,8 @@ var App = ({
|
|
|
2508
2528
|
const displayedKey = useRef("");
|
|
2509
2529
|
const displayedSections = useRef([]);
|
|
2510
2530
|
const [transients, setTransients] = useState(NO_TRANSIENTS);
|
|
2511
|
-
const
|
|
2512
|
-
|
|
2513
|
-
() => () => {
|
|
2514
|
-
if (transitTimer.current) clearTimeout(transitTimer.current);
|
|
2515
|
-
},
|
|
2516
|
-
[]
|
|
2517
|
-
);
|
|
2531
|
+
const transitTabs = useRef(/* @__PURE__ */ new Map());
|
|
2532
|
+
const [visibleTab, setVisibleTab] = useState("");
|
|
2518
2533
|
const showData = (sections, login) => {
|
|
2519
2534
|
const before = displayedSections.current;
|
|
2520
2535
|
displayedSections.current = sections;
|
|
@@ -2522,25 +2537,61 @@ var App = ({
|
|
|
2522
2537
|
setPending(null);
|
|
2523
2538
|
setFetchedAt(Date.now());
|
|
2524
2539
|
if (before.length === 0) {
|
|
2540
|
+
transitTabs.current = /* @__PURE__ */ new Map();
|
|
2525
2541
|
setTransients(NO_TRANSIENTS);
|
|
2526
2542
|
setState({ phase: "browse", sections, login });
|
|
2527
2543
|
return;
|
|
2528
2544
|
}
|
|
2529
|
-
const { transients:
|
|
2545
|
+
const { transients: fresh, union } = diffSections(before, sections);
|
|
2546
|
+
const marks = new Map(fresh);
|
|
2547
|
+
for (const [key, mark] of transients)
|
|
2548
|
+
if (!marks.has(key)) marks.set(key, mark);
|
|
2549
|
+
const tabs = tabsOfMarks(union, marks);
|
|
2550
|
+
for (const key of [...marks.keys()]) if (!tabs.has(key)) marks.delete(key);
|
|
2530
2551
|
if (marks.size === 0) {
|
|
2552
|
+
transitTabs.current = /* @__PURE__ */ new Map();
|
|
2553
|
+
setTransients(NO_TRANSIENTS);
|
|
2531
2554
|
setState({ phase: "browse", sections, login });
|
|
2532
2555
|
return;
|
|
2533
2556
|
}
|
|
2557
|
+
transitTabs.current = tabs;
|
|
2534
2558
|
setTransients(marks);
|
|
2535
2559
|
setState({ phase: "browse", sections: union, login });
|
|
2536
|
-
if (transitTimer.current) clearTimeout(transitTimer.current);
|
|
2537
|
-
transitTimer.current = setTimeout(() => {
|
|
2538
|
-
setTransients(NO_TRANSIENTS);
|
|
2539
|
-
setState(
|
|
2540
|
-
(prev) => prev.phase === "browse" && prev.sections === union ? { ...prev, sections } : prev
|
|
2541
|
-
);
|
|
2542
|
-
}, TRANSIT_HOLD_MS);
|
|
2543
2560
|
};
|
|
2561
|
+
const settleTab = (tabId, marks) => {
|
|
2562
|
+
const keys = [...transitTabs.current].filter(([, tab]) => tab === tabId).map(([key]) => key);
|
|
2563
|
+
for (const key of keys) transitTabs.current.delete(key);
|
|
2564
|
+
const gone = new Set(keys.filter((key) => marks.get(key) === "out"));
|
|
2565
|
+
setTransients((prev) => {
|
|
2566
|
+
const next = new Map(prev);
|
|
2567
|
+
for (const key of keys) next.delete(key);
|
|
2568
|
+
return next.size === 0 ? NO_TRANSIENTS : next;
|
|
2569
|
+
});
|
|
2570
|
+
setState(
|
|
2571
|
+
(prev) => prev.phase !== "browse" ? prev : {
|
|
2572
|
+
...prev,
|
|
2573
|
+
sections: prev.sections.map(
|
|
2574
|
+
(section) => section.id !== tabId ? section : {
|
|
2575
|
+
...section,
|
|
2576
|
+
items: section.items.filter((item) => {
|
|
2577
|
+
const key = keyOf(item);
|
|
2578
|
+
return !(key && gone.has(key));
|
|
2579
|
+
})
|
|
2580
|
+
}
|
|
2581
|
+
)
|
|
2582
|
+
}
|
|
2583
|
+
);
|
|
2584
|
+
};
|
|
2585
|
+
useEffect(() => {
|
|
2586
|
+
if (transients.size === 0) return;
|
|
2587
|
+
if (state.phase !== "browse" || !visibleTab) return;
|
|
2588
|
+
if (![...transitTabs.current.values()].includes(visibleTab)) return;
|
|
2589
|
+
const timer = setTimeout(
|
|
2590
|
+
() => settleTab(visibleTab, transients),
|
|
2591
|
+
TRANSIT_HOLD_MS
|
|
2592
|
+
);
|
|
2593
|
+
return () => clearTimeout(timer);
|
|
2594
|
+
}, [transients, visibleTab, state.phase]);
|
|
2544
2595
|
const pendingSummary = useMemo(
|
|
2545
2596
|
() => pending ? summariseDiff(
|
|
2546
2597
|
diffSections(displayedSections.current, pending.sections).counts
|
|
@@ -2725,6 +2776,7 @@ var App = ({
|
|
|
2725
2776
|
hidden: overlay !== null,
|
|
2726
2777
|
mergedUrls,
|
|
2727
2778
|
transients,
|
|
2779
|
+
onTabChange: setVisibleTab,
|
|
2728
2780
|
ciStatusState: hasCiStatus ? ciStatusState : void 0,
|
|
2729
2781
|
ciJob,
|
|
2730
2782
|
tabHelp,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kud/gh-ink",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.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",
|