@kud/gh-ink 0.62.1 → 0.64.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 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
- type LayoutInput = Pick<PrRowProps, "item" | "login" | "cols" | "prefix" | "uniformLabels" | "announcements" | "columns" | "shed">;
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
@@ -486,6 +504,12 @@ type DetailContext = {
486
504
  */
487
505
  onTyping?: (typing: boolean) => void;
488
506
  };
507
+ type SettledResult = {
508
+ ok: true;
509
+ } | {
510
+ ok: false;
511
+ reason: string;
512
+ };
489
513
  type Action = {
490
514
  label: string;
491
515
  hint: string;
@@ -624,6 +648,19 @@ declare const buildActions: (item: AnyItem, login: string, showFlash: (msg: stri
624
648
  * the drop stops the pre-action cache outliving a quit inside that window.
625
649
  */
626
650
  onActed?: () => void;
651
+ /**
652
+ * A mutation settled (succeeded or failed). Called exactly once per
653
+ * invocation of the three optimistic actions: "Remove me as reviewer",
654
+ * "Close issue" → "Close #N", and "Close PR" → "Close #N".
655
+ *
656
+ * On success: `{ ok: true }`. On failure: `{ ok: false; reason }` where
657
+ * `reason` is the first line of the error message/stderr, trimmed and
658
+ * non-empty.
659
+ *
660
+ * When absent, behaviour is identical — the host simply does not receive
661
+ * the settlement signal.
662
+ */
663
+ onSettled?: (item: GHItem, result: SettledResult) => void;
627
664
  }) => Action[];
628
665
  type CiStatusState = {
629
666
  kind: "loading";
@@ -665,7 +702,7 @@ declare const ActionMenu: ({ item, actions, cursor, }: {
665
702
  cursor: number;
666
703
  }) => React.JSX.Element;
667
704
  declare const signatureOf: (sections: Section[]) => string;
668
- declare const App: ({ fetcher, cacheKey, title, detailFor, origin, jiraBase, jiraKeyRe, jiraSetupHint, jiraTransitions, hasCiStatus, ciJob, ciFetcher, ciPollMs, stripFetcher, stripLabel, stripPollMs, watchPath, watchDebounceMs, watchJitterMs, extensions, tabHelp, emptyHint, liveLabel, }: {
705
+ declare const App: ({ fetcher, cacheKey, title, detailFor, origin, jiraBase, jiraKeyRe, jiraSetupHint, jiraTransitions, hasCiStatus, ciJob, ciFetcher, ciPollMs, stripFetcher, stripLabel, stripPollMs, watchPath, watchDebounceMs, watchJitterMs, extensions, tabHelp, emptyHint, liveLabel, onSettled, }: {
669
706
  fetcher: () => Promise<{
670
707
  sections: Section[];
671
708
  login: string;
@@ -739,6 +776,19 @@ declare const App: ({ fetcher, cacheKey, title, detailFor, origin, jiraBase, jir
739
776
  */
740
777
  watchJitterMs?: number;
741
778
  extensions?: InboxExtension[];
779
+ /**
780
+ * A mutation settled (succeeded or failed). Called exactly once per
781
+ * invocation of the three optimistic actions: "Remove me as reviewer",
782
+ * "Close issue" → "Close #N", and "Close PR" → "Close #N".
783
+ *
784
+ * On success: `{ ok: true }`. On failure: `{ ok: false; reason }` where
785
+ * `reason` is the first line of the error message/stderr, trimmed and
786
+ * non-empty.
787
+ *
788
+ * When absent, behaviour is identical — the host simply does not receive
789
+ * the settlement signal.
790
+ */
791
+ onSettled?: (item: GHItem, result: SettledResult) => void;
742
792
  }) => React.JSX.Element;
743
793
 
744
794
  type RepoFilter = {
@@ -760,4 +810,4 @@ declare const matchesFilter: (repo: string, filter: RepoFilter) => boolean;
760
810
  */
761
811
  declare const parsePatterns: (value: string) => string[];
762
812
 
763
- 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, 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 };
813
+ 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 numStr = `#${item.number}`.padEnd(7);
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 + 7 + (cell ? 2 + cell.length + 1 : 0) + (givingUp.repo ? 0 : repoLabel.length) + author + block + pills + pillCaps + 4;
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(item.title, titleMax) + " "
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,
@@ -1820,6 +1828,7 @@ var FRAME_PAD_X = 1;
1820
1828
  var FRAME_CHROME_COLS = 2 + FRAME_PAD_X * 2;
1821
1829
  var COLS = (process.stdout.columns ?? 120) - FRAME_CHROME_COLS;
1822
1830
  var MODAL_CHROME_COLS = 2 + 1 * 2;
1831
+ var ROW_MAX_COLS = 140;
1823
1832
  var OVERLAY_BG = "#22222e";
1824
1833
  var workCount = (s) => {
1825
1834
  let n = 0;
@@ -1875,6 +1884,12 @@ var explainGhAction = (e) => {
1875
1884
  const human = GH_ACTION_FAILURES.find(([re]) => re.test(raw))?.[1];
1876
1885
  return human ? `${human} (${raw})` : raw;
1877
1886
  };
1887
+ var firstLine = (e) => {
1888
+ const err = e;
1889
+ const raw = (err.stderr ?? err.message ?? err.stdout ?? String(e)).trim();
1890
+ const line = raw.split("\n").find((l) => l.trim().length > 0);
1891
+ return (line?.trim() ?? "failed").slice(0, 200);
1892
+ };
1878
1893
  var unsubscribeFrom = async (item) => {
1879
1894
  const route = item.kind === "pr" ? "pulls" : "issues";
1880
1895
  const found = await quietly`gh api repos/${item.repo}/${route}/${item.number} --jq .node_id`;
@@ -1979,13 +1994,21 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1979
1994
  run: () => {
1980
1995
  onRemove?.(item);
1981
1996
  showFlash(`\u22EF Removing you from #${item.number}\u2026`);
1982
- void quietly`gh pr edit ${item.number} --repo ${item.repo} --remove-reviewer ${login}`.then(() => {
1983
- showFlash(`\u2713 Removed you as reviewer on #${item.number}`);
1984
- ext?.onActed?.();
1985
- }).catch((e) => {
1986
- showFlash(`\u2717 #${item.number}: ${explainGhAction(e)}`);
1987
- onRefresh?.();
1988
- });
1997
+ void quietly`gh pr edit ${item.number} --repo ${item.repo} --remove-reviewer ${login}`.then(
1998
+ () => {
1999
+ showFlash(`\u2713 Removed you as reviewer on #${item.number}`);
2000
+ ext?.onActed?.();
2001
+ ext?.onSettled?.(item, { ok: true });
2002
+ },
2003
+ (e) => {
2004
+ showFlash(`\u2717 #${item.number}: ${explainGhAction(e)}`);
2005
+ onRefresh?.();
2006
+ ext?.onSettled?.(item, {
2007
+ ok: false,
2008
+ reason: firstLine(e)
2009
+ });
2010
+ }
2011
+ );
1989
2012
  }
1990
2013
  });
1991
2014
  }
@@ -2058,10 +2081,17 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
2058
2081
  run: () => {
2059
2082
  onRemove?.(item);
2060
2083
  showFlash(`\u2713 Closed #${item.number}`);
2061
- void quietly`gh issue close ${item.number} --repo ${item.repo}`.catch(
2084
+ void quietly`gh issue close ${item.number} --repo ${item.repo}`.then(
2062
2085
  () => {
2086
+ ext?.onSettled?.(item, { ok: true });
2087
+ },
2088
+ (e) => {
2063
2089
  showFlash(`\u2717 Close failed \u2014 restoring #${item.number}`);
2064
2090
  onRefresh?.();
2091
+ ext?.onSettled?.(item, {
2092
+ ok: false,
2093
+ reason: firstLine(e)
2094
+ });
2065
2095
  }
2066
2096
  );
2067
2097
  }
@@ -2110,10 +2140,17 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
2110
2140
  run: () => {
2111
2141
  onRemove?.(item);
2112
2142
  showFlash(`\u2713 Closed #${item.number}`);
2113
- void quietly`gh pr close ${item.number} --repo ${item.repo}`.catch(
2143
+ void quietly`gh pr close ${item.number} --repo ${item.repo}`.then(
2114
2144
  () => {
2145
+ ext?.onSettled?.(item, { ok: true });
2146
+ },
2147
+ (e) => {
2115
2148
  showFlash(`\u2717 Close failed \u2014 restoring #${item.number}`);
2116
2149
  onRefresh?.();
2150
+ ext?.onSettled?.(item, {
2151
+ ok: false,
2152
+ reason: firstLine(e)
2153
+ });
2117
2154
  }
2118
2155
  );
2119
2156
  }
@@ -2332,7 +2369,8 @@ var ItemRow = ({
2332
2369
  markerCols = 0,
2333
2370
  uniformLabels = [],
2334
2371
  columns,
2335
- shed
2372
+ shed,
2373
+ numberCols
2336
2374
  }) => {
2337
2375
  const backdropped = useBackdropped();
2338
2376
  const transient = leaving ? "out" : refreshMark;
@@ -2425,6 +2463,7 @@ var ItemRow = ({
2425
2463
  uniformLabels,
2426
2464
  columns,
2427
2465
  shed,
2466
+ numberCols,
2428
2467
  icon,
2429
2468
  motion,
2430
2469
  announcements
@@ -2751,6 +2790,7 @@ var BrowseScreen = ({
2751
2790
  jiraTransitions,
2752
2791
  onRefresh,
2753
2792
  onActed,
2793
+ onSettled,
2754
2794
  refreshing,
2755
2795
  hasPending,
2756
2796
  pendingSummary,
@@ -2947,11 +2987,19 @@ var BrowseScreen = ({
2947
2987
  const railCols = railWidth(COLS);
2948
2988
  const listCols = showRail ? COLS - railCols : COLS;
2949
2989
  const trailingColumns = trailingColumnsOf(labelBearing);
2990
+ const numberCols = numberColumnsOf(labelBearing);
2991
+ const rowCols = Math.min(listCols, ROW_MAX_COLS);
2950
2992
  const trailingShed = sectionShedOf(
2951
2993
  section.items.flatMap(
2952
2994
  (item, i) => item.kind === "pr" || item.kind === "issue" ? [{ item, prefix: treePrefix(section.items, i) }] : []
2953
2995
  ),
2954
- { login, cols: listCols, uniformLabels, columns: trailingColumns }
2996
+ {
2997
+ login,
2998
+ cols: rowCols,
2999
+ uniformLabels,
3000
+ columns: trailingColumns,
3001
+ numberCols
3002
+ }
2955
3003
  );
2956
3004
  const [sparkFrame, setSparkFrame] = useState(0);
2957
3005
  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
@@ -3029,7 +3077,7 @@ var BrowseScreen = ({
3029
3077
  onRefresh,
3030
3078
  dismissItem,
3031
3079
  openDrillView,
3032
- { extensions, onOpenExt, onActed }
3080
+ { extensions, onOpenExt, onActed, onSettled }
3033
3081
  );
3034
3082
  menu.open(actions);
3035
3083
  };
@@ -3310,13 +3358,18 @@ var BrowseScreen = ({
3310
3358
  if (input === "x" && activeItem.kind === "pr" && activeItem.standing === "queued" && login) {
3311
3359
  dismissItem(activeItem);
3312
3360
  showFlash(`\u22EF Removing you from #${activeItem.number}\u2026`);
3313
- void quietly`gh pr edit ${activeItem.number} --repo ${activeItem.repo} --remove-reviewer ${login}`.then(() => {
3314
- showFlash(`\u2713 Removed you as reviewer on #${activeItem.number}`);
3315
- onActed?.();
3316
- }).catch((e) => {
3317
- showFlash(`\u2717 #${activeItem.number}: ${explainGhAction(e)}`);
3318
- onRefresh?.();
3319
- });
3361
+ void quietly`gh pr edit ${activeItem.number} --repo ${activeItem.repo} --remove-reviewer ${login}`.then(
3362
+ () => {
3363
+ showFlash(`\u2713 Removed you as reviewer on #${activeItem.number}`);
3364
+ onActed?.();
3365
+ onSettled?.(activeItem, { ok: true });
3366
+ },
3367
+ (e) => {
3368
+ showFlash(`\u2717 #${activeItem.number}: ${explainGhAction(e)}`);
3369
+ onRefresh?.();
3370
+ onSettled?.(activeItem, { ok: false, reason: firstLine(e) });
3371
+ }
3372
+ );
3320
3373
  return;
3321
3374
  }
3322
3375
  if (input === "b" && activeItem.kind === "pr" && activeItem.branch) {
@@ -3642,11 +3695,12 @@ var BrowseScreen = ({
3642
3695
  prefix: treePrefix(section.items, viewStart + i),
3643
3696
  parent: item.kind === "task" && depthOf(section.items[viewStart + i + 1]) > depthOf(item),
3644
3697
  sparkFrame,
3645
- cols: listCols,
3698
+ cols: item.kind === "pr" || item.kind === "issue" ? rowCols : listCols,
3646
3699
  markerCols,
3647
3700
  uniformLabels,
3648
3701
  columns: trailingColumns,
3649
3702
  shed: trailingShed,
3703
+ numberCols,
3650
3704
  gap: i > 0 && gapsAbove(section.items, viewStart + i)
3651
3705
  },
3652
3706
  `${viewStart + i}:${rowKey(item)}`
@@ -3744,7 +3798,8 @@ var App = ({
3744
3798
  extensions,
3745
3799
  tabHelp,
3746
3800
  emptyHint,
3747
- liveLabel
3801
+ liveLabel,
3802
+ onSettled
3748
3803
  }) => {
3749
3804
  const { rows } = useWindowSize();
3750
3805
  const [state, setState] = useState({ phase: "loading" });
@@ -4155,6 +4210,7 @@ var App = ({
4155
4210
  jiraTransitions,
4156
4211
  onRefresh: applyOrRefresh,
4157
4212
  onActed,
4213
+ onSettled,
4158
4214
  refreshing,
4159
4215
  hasPending: pending !== null,
4160
4216
  pendingSummary,
@@ -4233,4 +4289,4 @@ var matchesFilter = (repo, filter) => {
4233
4289
  };
4234
4290
  var parsePatterns = (value) => value.split(",").map((p) => p.trim()).filter(Boolean);
4235
4291
 
4236
- 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 };
4292
+ 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.62.1",
3
+ "version": "0.64.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.18.0",
52
- "@kud/gh-workflow": "0.13.1",
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
  },