@kud/gh-ink 0.61.3 → 0.62.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 CHANGED
@@ -242,7 +242,54 @@ type PrRowProps = {
242
242
  motion?: RowMotion;
243
243
  /** In order, left to right. Charged against the width budget either way. */
244
244
  announcements?: readonly RowAnnouncement[];
245
+ /**
246
+ * The trailing columns' widths across the section — see `trailingColumnsOf`.
247
+ * Absent, the row measures itself, which aligns nothing but draws the same
248
+ * cells a host that never measured always got.
249
+ */
250
+ columns?: TrailingColumns;
251
+ /** Trailing columns the section has given up — see `sectionShedOf`. */
252
+ shed?: TrailingShed;
245
253
  };
254
+ /**
255
+ * The trailing block, in reading order: how contested, how big, how recent.
256
+ * Threads lead because they are the one cell that makes a claim on you; age
257
+ * ends the row so every row ends on the date.
258
+ */
259
+ declare const TRAILING: readonly ["threads", "size", "age"];
260
+ /** Width of each trailing column, in terminal cells. Zero draws no column. */
261
+ type TrailingColumns = Record<(typeof TRAILING)[number], number>;
262
+ /** Which trailing columns a whole section has given up. */
263
+ type TrailingShed = Partial<Record<(typeof TRAILING)[number], boolean>>;
264
+ /**
265
+ * The widest value each trailing column holds across these rows, measured once
266
+ * by the list — the same move as `uniformLabels` and `markerCols`. It is what
267
+ * makes the numbers line up: a column as wide as its widest value, right-
268
+ * aligned, so digits sit under digits and the eye can run straight down it.
269
+ * A column no row fills measures zero and is not drawn at all, which is what
270
+ * keeps this from becoming GitHub's grid of `—`.
271
+ *
272
+ * Code points rather than `.length`: every value here is ASCII or a single
273
+ * BMP glyph, so the two agree today, and a surrogate pair is the day they
274
+ * would not.
275
+ */
276
+ declare const trailingColumnsOf: (items: readonly GHItem[]) => TrailingColumns;
277
+ type LayoutInput = Pick<PrRowProps, "item" | "login" | "cols" | "prefix" | "uniformLabels" | "announcements" | "columns" | "shed">;
278
+ /**
279
+ * Which trailing columns the section has to give up, so that every row gives up
280
+ * the same ones. Each row is laid out alone and the drops are unioned: if any
281
+ * row needs its size cell gone to keep a readable title, the size column goes
282
+ * for all of them.
283
+ *
284
+ * Forcing a drop on a row that did not need it only ever hands that row more
285
+ * room, so it can never push the row further down the ladder than it went on
286
+ * its own — the union is stable in one pass.
287
+ *
288
+ * Announcements are left out on purpose. A MERGED pill lives for three seconds
289
+ * on a row already leaving, and letting it reshape the whole section for those
290
+ * three seconds would move every row under the one you just acted on.
291
+ */
292
+ declare const sectionShedOf: (rows: readonly Pick<LayoutInput, "item" | "prefix">[], context: Omit<LayoutInput, "item" | "prefix" | "announcements" | "shed">) => TrailingShed;
246
293
  /**
247
294
  * One pull request or issue, as a single line of a list.
248
295
  *
@@ -253,7 +300,7 @@ type PrRowProps = {
253
300
  * arrival, merge and departure belongs to whoever owns the list, and reaches
254
301
  * the row as `icon`, `motion` and `announcements` after the decisions are made.
255
302
  */
256
- declare const PrRow: ({ item, active, login, cols, icon: iconOverride, prefix, uniformLabels, motion, announcements, }: PrRowProps) => React.JSX.Element;
303
+ declare const PrRow: ({ item, active, login, cols, icon: iconOverride, prefix, uniformLabels, motion, announcements, columns, shed, }: PrRowProps) => React.JSX.Element;
257
304
 
258
305
  /**
259
306
  * One state per thing, from a closed set the strip knows how to draw. The host
@@ -713,4 +760,4 @@ declare const matchesFilter: (repo: string, filter: RepoFilter) => boolean;
713
760
  */
714
761
  declare const parsePatterns: (value: string) => string[];
715
762
 
716
- 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, 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, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
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 };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import React2, { createContext, useState, useRef, useEffect, useMemo, useContext } from 'react';
2
2
  import { useWindowSize, useInput, Text, Box } from 'ink';
3
- import { colors, ScrollView, TextInput, Pill, useAppKeys, LoadingScreen, StatusMessage, FooterHints, useListCursor, CommandPalette, Tabs, ProgressBar, pillWidth } from '@kud/ink-ui';
3
+ import { colors, ScrollView, TextInput, Pill, useAppKeys, LoadingScreen, StatusMessage, FooterHints, useFilterMode, useListCursor, CommandPalette, Tabs, ProgressBar, pillWidth } from '@kud/ink-ui';
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';
@@ -833,41 +833,56 @@ var Backdrop = ({
833
833
  children
834
834
  }
835
835
  ) : children });
836
- var PrRow = ({
836
+ var threadsLabelOf = (item) => item.unresolved > 0 ? `\uF086 ${item.unresolved}` : "";
837
+ var agePairOf = (item) => item.activityAge && item.activityAge !== item.age ? { activity: item.activityAge, lifetime: item.age } : null;
838
+ var ageLabelOf = (item) => {
839
+ const pair = agePairOf(item);
840
+ return pair ? `${pair.activity} (${pair.lifetime})` : item.age;
841
+ };
842
+ var TRAILING = ["threads", "size", "age"];
843
+ var cellsOf = (s) => [...s].length;
844
+ var trailingColumnsOf = (items) => items.reduce(
845
+ (w, item) => ({
846
+ threads: Math.max(w.threads, cellsOf(threadsLabelOf(item))),
847
+ size: Math.max(w.size, cellsOf(sizeOf(item) ?? "")),
848
+ age: Math.max(w.age, cellsOf(ageLabelOf(item) ?? ""))
849
+ }),
850
+ { threads: 0, size: 0, age: 0 }
851
+ );
852
+ var sectionShedOf = (rows, context) => rows.reduce((shed, row) => {
853
+ const { givingUp } = layoutOf({ ...context, ...row });
854
+ return {
855
+ threads: shed.threads || givingUp.threads,
856
+ size: shed.size || givingUp.size,
857
+ age: shed.age || givingUp.age
858
+ };
859
+ }, {});
860
+ var layoutOf = ({
837
861
  item,
838
- active,
839
862
  login,
840
863
  cols,
841
- icon: iconOverride,
842
864
  prefix = "",
843
865
  uniformLabels = [],
844
- motion,
845
- announcements = []
866
+ announcements = [],
867
+ columns,
868
+ shed = {}
846
869
  }) => {
847
- const backdropped = useBackdropped();
848
- const { glyph: healthIcon, color: healthColor2 } = displayFor(item.health);
849
- const { glyph: icon, color } = iconOverride ?? {
850
- glyph: healthIcon,
851
- color: healthColor2
852
- };
853
- const spokeLast = !!login && !!item.lastActor && item.lastActor === login;
854
- const [turnIcon, turnColor] = item.pinned ? [PIN_MARK, colors.accent] : !login || !item.lastActor || spokeLast ? [" ", colors.muted] : ["\u2190", colors.accent];
855
870
  const numStr = `#${item.number}`.padEnd(7);
856
871
  const showAuthor = !!item.author && item.author !== login;
857
- const sizeLabel = sizeOf(item);
858
872
  const sizeParts = sizePartsOf(item);
859
- const unresolvedLabel = item.unresolved > 0 ? `\uF086 ${item.unresolved}` : "";
860
- const agePair = item.activityAge && item.activityAge !== item.age ? { activity: item.activityAge, lifetime: item.age } : null;
861
- const ageLabel2 = agePair ? `${agePair.activity} (${agePair.lifetime})` : item.age;
873
+ const unresolvedLabel = threadsLabelOf(item);
874
+ const agePair = agePairOf(item);
875
+ const ageLabel2 = ageLabelOf(item);
876
+ const own = columns ?? trailingColumnsOf([item]);
862
877
  const pillCaps = announcements.length * 2;
863
878
  const repoLabel = depthOf(item) > 0 ? item.repo : "";
864
879
  const implied = [...impliedLabels(item.repo), ...uniformLabels];
865
880
  const labelNames = (item.labels ?? []).filter((l) => !implied.includes(l)).sort((a, b) => labelPriority(a) - labelPriority(b) || a.localeCompare(b)).slice(0, 2);
866
881
  const givingUp = {
867
882
  author: false,
868
- size: false,
869
- threads: false,
870
- age: false,
883
+ size: !!shed.size,
884
+ threads: !!shed.threads,
885
+ age: !!shed.age,
871
886
  repo: false,
872
887
  labels: 0
873
888
  };
@@ -889,16 +904,14 @@ var PrRow = ({
889
904
  return `\uF02B ${fitted.join(", ")}`;
890
905
  };
891
906
  const widthOf2 = () => {
892
- const suffix = [
893
- givingUp.age ? "" : ageLabel2 || "",
894
- // ASCII only, so no PUA double-width correction — see the label cell.
895
- givingUp.size ? "" : sizeLabel || "",
896
- givingUp.threads ? "" : unresolvedLabel,
897
- showAuthor && !givingUp.author ? `by ${item.author}` : "",
898
- ...announcements.map((a) => a.label)
899
- ].filter(Boolean).join(" ");
907
+ const block = TRAILING.reduce(
908
+ (w, k) => givingUp[k] || own[k] === 0 ? w : w + 2 + own[k],
909
+ 0
910
+ );
911
+ const author = showAuthor && !givingUp.author ? ` by ${item.author}`.length : 0;
912
+ const pills = announcements.reduce((w, a) => w + 2 + a.label.length, 0);
900
913
  const cell = labelCell();
901
- return 2 + prefix.length + 2 + 2 + 7 + (cell ? 2 + cell.length + 1 : 0) + (givingUp.repo ? 0 : repoLabel.length) + suffix.length + pillCaps + 6;
914
+ return 2 + prefix.length + 2 + 2 + 7 + (cell ? 2 + cell.length + 1 : 0) + (givingUp.repo ? 0 : repoLabel.length) + author + block + pills + pillCaps + 4;
902
915
  };
903
916
  const MIN_TITLE = 24;
904
917
  for (const give of [
@@ -915,7 +928,64 @@ var PrRow = ({
915
928
  }
916
929
  const labelLabel = labelCell();
917
930
  const titleMax = Math.max(1, cols - widthOf2());
918
- return /* @__PURE__ */ jsxs(Box, { children: [
931
+ return {
932
+ numStr,
933
+ showAuthor,
934
+ sizeParts,
935
+ unresolvedLabel,
936
+ agePair,
937
+ ageLabel: ageLabel2,
938
+ repoLabel,
939
+ givingUp,
940
+ labelLabel,
941
+ titleMax,
942
+ columns: own
943
+ };
944
+ };
945
+ var PrRow = ({
946
+ item,
947
+ active,
948
+ login,
949
+ cols,
950
+ icon: iconOverride,
951
+ prefix = "",
952
+ uniformLabels = [],
953
+ motion,
954
+ announcements = [],
955
+ columns,
956
+ shed
957
+ }) => {
958
+ const backdropped = useBackdropped();
959
+ const { glyph: healthIcon, color: healthColor2 } = displayFor(item.health);
960
+ const { glyph: icon, color } = iconOverride ?? {
961
+ glyph: healthIcon,
962
+ color: healthColor2
963
+ };
964
+ const spokeLast = !!login && !!item.lastActor && item.lastActor === login;
965
+ const [turnIcon, turnColor] = item.pinned ? [PIN_MARK, colors.accent] : !login || !item.lastActor || spokeLast ? [" ", colors.muted] : ["\u2190", colors.accent];
966
+ const {
967
+ numStr,
968
+ showAuthor,
969
+ sizeParts,
970
+ unresolvedLabel,
971
+ agePair,
972
+ ageLabel: ageLabel2,
973
+ repoLabel,
974
+ givingUp,
975
+ labelLabel,
976
+ titleMax,
977
+ columns: block
978
+ } = layoutOf({
979
+ item,
980
+ login,
981
+ cols,
982
+ prefix,
983
+ uniformLabels,
984
+ announcements,
985
+ columns,
986
+ shed
987
+ });
988
+ return /* @__PURE__ */ jsxs(Box, { width: cols, children: [
919
989
  /* @__PURE__ */ jsx(Text3, { color: colors.info, children: active ? "\u276F " : " " }),
920
990
  /* @__PURE__ */ jsx(Text3, { dimColor: true, children: prefix }),
921
991
  /* @__PURE__ */ jsx(Text3, { color, bold: true, children: icon + " " }),
@@ -932,25 +1002,43 @@ var PrRow = ({
932
1002
  ),
933
1003
  labelLabel ? /* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: labelLabel + " " }) : null,
934
1004
  repoLabel && !givingUp.repo ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: repoLabel }) : null,
935
- sizeParts && !givingUp.size ? /* @__PURE__ */ jsxs(Text3, { children: [
936
- " ",
937
- /* @__PURE__ */ jsx(Text3, { color: colors.success, children: sizeParts.added }),
938
- " ",
939
- /* @__PURE__ */ jsx(Text3, { color: colors.error, children: sizeParts.removed })
940
- ] }) : null,
941
- unresolvedLabel && !givingUp.threads ? /* @__PURE__ */ jsx(
942
- Text3,
1005
+ showAuthor && !givingUp.author ? /* @__PURE__ */ jsx(Text3, { dimColor: true, italic: true, children: " by " + item.author }) : null,
1006
+ /* @__PURE__ */ jsx(Box, { flexGrow: 1 }),
1007
+ block.threads > 0 && !givingUp.threads ? /* @__PURE__ */ jsx(
1008
+ Box,
943
1009
  {
944
- bold: !spokeLast,
945
- color: spokeLast ? colors.secondary : colors.accent,
946
- children: " " + unresolvedLabel
1010
+ marginLeft: 2,
1011
+ width: block.threads,
1012
+ justifyContent: "flex-end",
1013
+ flexShrink: 0,
1014
+ children: unresolvedLabel ? /* @__PURE__ */ jsx(
1015
+ Text3,
1016
+ {
1017
+ bold: !spokeLast,
1018
+ color: spokeLast ? colors.secondary : colors.accent,
1019
+ children: unresolvedLabel
1020
+ }
1021
+ ) : null
947
1022
  }
948
1023
  ) : null,
949
- showAuthor && !givingUp.author ? /* @__PURE__ */ jsx(Text3, { dimColor: true, italic: true, children: " by " + item.author }) : null,
950
- ageLabel2 && !givingUp.age ? agePair ? /* @__PURE__ */ jsxs(Fragment, { children: [
951
- /* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: " " + agePair.activity }),
1024
+ block.size > 0 && !givingUp.size ? /* @__PURE__ */ jsx(
1025
+ Box,
1026
+ {
1027
+ marginLeft: 2,
1028
+ width: block.size,
1029
+ justifyContent: "flex-end",
1030
+ flexShrink: 0,
1031
+ children: sizeParts ? /* @__PURE__ */ jsxs(Text3, { children: [
1032
+ /* @__PURE__ */ jsx(Text3, { color: colors.success, children: sizeParts.added }),
1033
+ " ",
1034
+ /* @__PURE__ */ jsx(Text3, { color: colors.error, children: sizeParts.removed })
1035
+ ] }) : null
1036
+ }
1037
+ ) : null,
1038
+ block.age > 0 && !givingUp.age ? /* @__PURE__ */ jsx(Box, { marginLeft: 2, width: block.age, flexShrink: 0, children: agePair ? /* @__PURE__ */ jsxs(Text3, { children: [
1039
+ /* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: agePair.activity }),
952
1040
  /* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` (${agePair.lifetime})` })
953
- ] }) : /* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: " " + ageLabel2 }) : null,
1041
+ ] }) : ageLabel2 ? /* @__PURE__ */ jsx(Text3, { color: colors.secondary, children: ageLabel2 }) : null }) : null,
954
1042
  backdropped ? null : announcements.map((a) => /* @__PURE__ */ jsxs(React2.Fragment, { children: [
955
1043
  /* @__PURE__ */ jsx(Text3, { children: " " }),
956
1044
  /* @__PURE__ */ jsx(Pill, { color: a.color, children: a.label })
@@ -2242,7 +2330,9 @@ var ItemRow = ({
2242
2330
  sparkFrame = 0,
2243
2331
  cols = COLS,
2244
2332
  markerCols = 0,
2245
- uniformLabels = []
2333
+ uniformLabels = [],
2334
+ columns,
2335
+ shed
2246
2336
  }) => {
2247
2337
  const backdropped = useBackdropped();
2248
2338
  const transient = leaving ? "out" : refreshMark;
@@ -2333,6 +2423,8 @@ var ItemRow = ({
2333
2423
  cols,
2334
2424
  prefix,
2335
2425
  uniformLabels,
2426
+ columns,
2427
+ shed,
2336
2428
  icon,
2337
2429
  motion,
2338
2430
  announcements
@@ -2376,6 +2468,7 @@ var ActionMenu = ({
2376
2468
  Box,
2377
2469
  {
2378
2470
  flexDirection: "column",
2471
+ flexShrink: 0,
2379
2472
  borderStyle: "round",
2380
2473
  borderColor: colors.info,
2381
2474
  backgroundColor: OVERLAY_BG,
@@ -2705,8 +2798,6 @@ var BrowseScreen = ({
2705
2798
  }, [activeId]);
2706
2799
  const [flash, setFlash] = useState(null);
2707
2800
  const menu = useActionMenu();
2708
- const [search, setSearch] = useState(null);
2709
- const [searchInput, setSearchInput] = useState(false);
2710
2801
  const [repoFilter, setRepoFilter] = useState(/* @__PURE__ */ new Set());
2711
2802
  const [repoPicker, setRepoPicker] = useState(false);
2712
2803
  const [help, setHelp] = useState(false);
@@ -2714,6 +2805,11 @@ var BrowseScreen = ({
2714
2805
  const [helpRange, setHelpRange] = useState({ max: 0, page: 1 });
2715
2806
  const [explain, setExplain] = useState(false);
2716
2807
  const [palette, setPalette] = useState(null);
2808
+ const filter = useFilterMode({
2809
+ isActive: !hidden && palette === null && !help && !explain && !repoPicker && menu.actions === null
2810
+ });
2811
+ const search = filter.term;
2812
+ const searchInput = filter.typing;
2717
2813
  const filterActive = search != null || repoFilter.size > 0;
2718
2814
  const reserveCiRow = ciStatusState != null;
2719
2815
  const reserveStripRow = stripState != null;
@@ -2834,7 +2930,7 @@ var BrowseScreen = ({
2834
2930
  if (repoPicker) return setRepoPicker(false), true;
2835
2931
  if (railActive) return setRailFocus(false), true;
2836
2932
  if (menu.actions !== null) return menu.close(), true;
2837
- if (search != null) return setSearch(null), true;
2933
+ if (search != null) return filter.clear(), true;
2838
2934
  if (repoFilter.size > 0) return setRepoFilter(/* @__PURE__ */ new Set()), true;
2839
2935
  return false;
2840
2936
  };
@@ -2850,6 +2946,13 @@ var BrowseScreen = ({
2850
2946
  }, [searchInput, palette, onTyping]);
2851
2947
  const railCols = railWidth(COLS);
2852
2948
  const listCols = showRail ? COLS - railCols : COLS;
2949
+ const trailingColumns = trailingColumnsOf(labelBearing);
2950
+ const trailingShed = sectionShedOf(
2951
+ section.items.flatMap(
2952
+ (item, i) => item.kind === "pr" || item.kind === "issue" ? [{ item, prefix: treePrefix(section.items, i) }] : []
2953
+ ),
2954
+ { login, cols: listCols, uniformLabels, columns: trailingColumns }
2955
+ );
2853
2956
  const [sparkFrame, setSparkFrame] = useState(0);
2854
2957
  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
2855
2958
  // own items, which was right while the animation lived on the rows and is
@@ -2976,23 +3079,7 @@ var BrowseScreen = ({
2976
3079
  }
2977
3080
  return;
2978
3081
  }
2979
- if (searchInput && !key.upArrow && !key.downArrow) {
2980
- if (key.return) return setSearchInput(false);
2981
- if (key.escape) {
2982
- setSearch(null);
2983
- return setSearchInput(false);
2984
- }
2985
- if (key.backspace || key.delete)
2986
- return setSearch((s) => (s ?? "").slice(0, -1));
2987
- if (input && !key.ctrl && !key.meta && !key.tab)
2988
- return setSearch((s) => (s ?? "") + input);
2989
- return;
2990
- }
2991
- if (input === "/") {
2992
- setSearch("");
2993
- setSearchInput(true);
2994
- return;
2995
- }
3082
+ if (searchInput && !key.upArrow && !key.downArrow) return;
2996
3083
  if (input === "f" && allRepos.length > 0) {
2997
3084
  setRepoCursor(0);
2998
3085
  setRepoPicker(true);
@@ -3520,7 +3607,7 @@ var BrowseScreen = ({
3520
3607
  /* @__PURE__ */ jsx(Text3, { color: colors.info, children: " / " }),
3521
3608
  /* @__PURE__ */ jsx(Text3, { children: search }),
3522
3609
  searchInput ? /* @__PURE__ */ jsx(Text3, { color: colors.info, children: "\u258F" }) : null,
3523
- /* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` ${matchCount} match${matchCount !== 1 ? "es" : ""}${searchInput ? " \u2191\u2193 move \xB7 \u21B5 accept \xB7 esc clear" : " esc clear"}` })
3610
+ /* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` ${matchCount} match${matchCount !== 1 ? "es" : ""} ${filter.hints.map(([k, label]) => `${k} ${label}`).join(" \xB7 ")}` })
3524
3611
  ] }) : repoFilter.size > 0 ? /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
3525
3612
  /* @__PURE__ */ jsx(Text3, { color: colors.accent, children: " \u25C9 " }),
3526
3613
  /* @__PURE__ */ jsx(Text3, { children: `${repoFilter.size} repo${repoFilter.size !== 1 ? "s" : ""}` }),
@@ -3558,6 +3645,8 @@ var BrowseScreen = ({
3558
3645
  cols: listCols,
3559
3646
  markerCols,
3560
3647
  uniformLabels,
3648
+ columns: trailingColumns,
3649
+ shed: trailingShed,
3561
3650
  gap: i > 0 && gapsAbove(section.items, viewStart + i)
3562
3651
  },
3563
3652
  `${viewStart + i}:${rowKey(item)}`
@@ -4144,4 +4233,4 @@ var matchesFilter = (repo, filter) => {
4144
4233
  };
4145
4234
  var parsePatterns = (value) => value.split(",").map((p) => p.trim()).filter(Boolean);
4146
4235
 
4147
- 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, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/gh-ink",
3
- "version": "0.61.3",
3
+ "version": "0.62.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",
@@ -50,7 +50,7 @@
50
50
  "dependencies": {
51
51
  "@kud/gh": "0.18.0",
52
52
  "@kud/gh-workflow": "0.13.1",
53
- "@kud/ink-ui": "0.30.0",
53
+ "@kud/ink-ui": "0.31.0",
54
54
  "zx": "8.8.5"
55
55
  },
56
56
  "devDependencies": {