@kud/gh-ink 0.39.0 → 0.41.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
@@ -44,6 +44,17 @@ type SidebarRow = {
44
44
  * hard 0 asserts the first from evidence for neither.
45
45
  */
46
46
  live?: number;
47
+ /**
48
+ * How far through it is — `done` of `total` children resolved.
49
+ *
50
+ * Both or neither, and only ever drawn together: a numerator with no
51
+ * denominator is not progress, it is a number. Absent for the same reason
52
+ * `live` is — a host that cannot count says nothing rather than claiming zero,
53
+ * and the two counts genuinely can be unavailable while `live` is known, since
54
+ * `live` is what the board already drew and this needs asking Jira again.
55
+ */
56
+ done?: number;
57
+ total?: number;
47
58
  /** Something under it is waiting on you. */
48
59
  wantsYou?: boolean;
49
60
  /**
@@ -66,6 +77,16 @@ type Sidebar = {
66
77
  * scrolls the panel rather than clipping a row.
67
78
  */
68
79
  declare const SIDEBAR_COLS = 40;
80
+ /**
81
+ * The dim figures after the key: how far through, and how much is moving.
82
+ *
83
+ * Either half may be missing and the other still worth saying, so this is a join
84
+ * of what is known rather than one of three fixed shapes. `done`/`total` are
85
+ * treated as a pair — a numerator with no denominator is not progress, it is a
86
+ * number — and a zero is printed wherever it was counted, because "nothing is
87
+ * moving" is exactly the thing a roadmap is read to notice.
88
+ */
89
+ declare const counts: (row: SidebarRow) => string;
69
90
  /**
70
91
  * How many rows fit in `height` — one fewer than would physically fit whenever
71
92
  * that means anything is left over, to buy the line that says so.
@@ -698,4 +719,4 @@ declare const matchesFilter: (repo: string, filter: RepoFilter) => boolean;
698
719
  */
699
720
  declare const parsePatterns: (value: string) => string[];
700
721
 
701
- 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 InboxBudget, type InboxConfig, type InboxExtension, type JiraTransition, type OriginSplit, PIN_MARK, type RepoFilter, type RepoHeader, type RepoProfile, SIDEBAR_COLS, type Section, type ShowLess, type ShowMore, SidePanel, type Sidebar, type SidebarRow, type Standing, type SubgroupHeader, type TaskRow, budgetNotice, buildActions, buildCheckoutCmd, checkoutDirs, clipboard, configureInbox, drillCmd, explainGhAction, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, profileOf, railCapacity, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, whoseMove, windowCount, withHeaders, withoutItem, writeCache };
722
+ 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 InboxBudget, type InboxConfig, type InboxExtension, type JiraTransition, type OriginSplit, PIN_MARK, type RepoFilter, type RepoHeader, type RepoProfile, SIDEBAR_COLS, type Section, type ShowLess, type ShowMore, SidePanel, type Sidebar, type SidebarRow, type Standing, type SubgroupHeader, type TaskRow, budgetNotice, buildActions, buildCheckoutCmd, checkoutDirs, clipboard, configureInbox, counts, drillCmd, explainGhAction, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, profileOf, railCapacity, 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
@@ -590,6 +590,10 @@ var PAD = 2;
590
590
  var CONTENT = SIDEBAR_COLS - RULE - PAD;
591
591
  var LABEL_INDENT = 2;
592
592
  var RULE_COLOR = "gray";
593
+ var counts = (row) => [
594
+ row.done !== void 0 && row.total !== void 0 ? `${row.done}/${row.total}` : "",
595
+ row.live !== void 0 ? `${row.live} live` : ""
596
+ ].filter(Boolean).join(" \xB7 ");
593
597
  var truncate = (text, max) => [...text].length <= max ? text : [...text].slice(0, Math.max(0, max - 1)).join("") + "\u2026";
594
598
  var ROW_LINES = 3;
595
599
  var HEADING_LINES = 2;
@@ -640,7 +644,7 @@ var SidePanel = ({
640
644
  /* @__PURE__ */ jsx(Text, { color: "cyan", children: active ? "\u276F " : " " }),
641
645
  /* @__PURE__ */ jsx(Text, { color: ACCENT, bold: true, children: row.wantsYou ? "\u2190 " : " " }),
642
646
  /* @__PURE__ */ jsx(Text, { color: ACCENT, bold: active, children: row.key }),
643
- row.live !== void 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${row.live} live` }) : null
647
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${counts(row)}` })
644
648
  ] }),
645
649
  /* @__PURE__ */ jsx(Box, { paddingLeft: LABEL_INDENT + 2, children: /* @__PURE__ */ jsx(Text, { dimColor: !active, children: truncate(row.label, CONTENT - LABEL_INDENT - 2) }) })
646
650
  ] }, row.key);
@@ -858,11 +862,11 @@ var diffSections = (prev, next) => {
858
862
  counts: { added, removed, changed: changedRows.size }
859
863
  };
860
864
  };
861
- var summariseDiff = (counts) => {
865
+ var summariseDiff = (counts2) => {
862
866
  const parts = [];
863
- if (counts.added) parts.push(`${counts.added} new`);
864
- if (counts.removed) parts.push(`${counts.removed} gone`);
865
- if (counts.changed) parts.push(`${counts.changed} moved`);
867
+ if (counts2.added) parts.push(`${counts2.added} new`);
868
+ if (counts2.removed) parts.push(`${counts2.removed} gone`);
869
+ if (counts2.changed) parts.push(`${counts2.changed} moved`);
866
870
  return parts.join(" \xB7 ");
867
871
  };
868
872
  var transientOf = (transients, item, sectionId) => {
@@ -2000,8 +2004,8 @@ var ItemRow = ({
2000
2004
  const transitIcon = !transient ? " " : isDeparture(transient) ? TRANSIT_OUT_FRAMES[sparkFrame % TRANSIT_OUT_FRAMES.length] : isArrival(transient) ? TRANSIT_IN_FRAMES[sparkFrame % TRANSIT_IN_FRAMES.length] : "\u25C9";
2001
2005
  const transitLabel2 = transient ? TRANSIT_LABEL[transient] : "";
2002
2006
  const titleMax2 = Math.max(
2003
- 20,
2004
- cols - item.key.length - note.length - (item.pill ? pillWidth(item.pill) + 1 : 0) - transitLabel2.length - prefix.length - 12
2007
+ 1,
2008
+ cols - item.key.length - note.length - (item.pill ? pillWidth(item.pill) + 1 : 0) - (transitLabel2 ? pillWidth(transitLabel2) : 0) - prefix.length - 12
2005
2009
  );
2006
2010
  return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
2007
2011
  /* @__PURE__ */ jsx(Text3, { color: "cyan", children: active ? "\u276F " : " " }),
@@ -2023,7 +2027,10 @@ var ItemRow = ({
2023
2027
  /* @__PURE__ */ jsx(Pill, { variant: item.pillVariant ?? "muted", children: item.pill })
2024
2028
  ] }) : null,
2025
2029
  note ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: ` ${note}` }) : null,
2026
- transitLabel2 ? /* @__PURE__ */ jsx(Text3, { bold: true, color: TRANSIT_COLOUR[transient], children: " " + transitLabel2 }) : null
2030
+ transitLabel2 ? /* @__PURE__ */ jsxs(Fragment, { children: [
2031
+ /* @__PURE__ */ jsx(Text3, { children: " " }),
2032
+ /* @__PURE__ */ jsx(Pill, { color: TRANSIT_COLOUR[transient], children: transitLabel2 })
2033
+ ] }) : null
2027
2034
  ] });
2028
2035
  }
2029
2036
  const { glyph: healthIcon, color: healthColor2 } = healthDisplay[item.health];
@@ -2037,16 +2044,37 @@ var ItemRow = ({
2037
2044
  const ageLabel = item.activityAge && item.activityAge !== item.age ? `${item.activityAge} \xB7 ${item.age}` : item.age;
2038
2045
  const mergedLabel = merged ? "MERGED" : "";
2039
2046
  const transitLabel = merged || !transient ? "" : TRANSIT_LABEL[transient];
2040
- const suffix = [
2041
- ageLabel || "",
2042
- unresolvedLabel,
2043
- showAuthor ? `by ${item.author}` : "",
2047
+ const pillCaps = [mergedLabel, transitLabel].filter(Boolean).length * 2;
2048
+ const repoLabel = depthOf(item) > 0 ? item.repo : "";
2049
+ const givingUp = { author: false, threads: false, age: false, repo: false };
2050
+ const widthOf2 = () => {
2051
+ const suffix2 = [
2052
+ givingUp.age ? "" : ageLabel || "",
2053
+ givingUp.threads ? "" : unresolvedLabel,
2054
+ showAuthor && !givingUp.author ? `by ${item.author}` : "",
2055
+ mergedLabel,
2056
+ transitLabel
2057
+ ].filter(Boolean).join(" ");
2058
+ return 2 + prefix.length + 2 + 2 + 7 + (givingUp.repo ? 0 : repoLabel.length) + suffix2.length + pillCaps + 6;
2059
+ };
2060
+ const MIN_TITLE = 24;
2061
+ for (const give of [
2062
+ () => givingUp.author = true,
2063
+ () => givingUp.threads = true,
2064
+ () => givingUp.repo = true,
2065
+ () => givingUp.age = true
2066
+ ]) {
2067
+ if (cols - widthOf2() >= MIN_TITLE) break;
2068
+ give();
2069
+ }
2070
+ [
2071
+ givingUp.age ? "" : ageLabel || "",
2072
+ givingUp.threads ? "" : unresolvedLabel,
2073
+ showAuthor && !givingUp.author ? `by ${item.author}` : "",
2044
2074
  mergedLabel,
2045
2075
  transitLabel
2046
2076
  ].filter(Boolean).join(" ");
2047
- const repoLabel = depthOf(item) > 0 ? item.repo : "";
2048
- const fixedWidth = 2 + prefix.length + 2 + 2 + 7 + repoLabel.length + suffix.length + 6;
2049
- const titleMax = Math.max(20, cols - fixedWidth);
2077
+ const titleMax = Math.max(1, cols - widthOf2());
2050
2078
  return /* @__PURE__ */ jsxs(Box, { children: [
2051
2079
  /* @__PURE__ */ jsx(Text3, { color: "cyan", children: active ? "\u276F " : " " }),
2052
2080
  /* @__PURE__ */ jsx(Text3, { dimColor: true, children: prefix }),
@@ -2062,12 +2090,18 @@ var ItemRow = ({
2062
2090
  children: truncate2(item.title, titleMax) + " "
2063
2091
  }
2064
2092
  ),
2065
- repoLabel ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: repoLabel }) : null,
2066
- unresolvedLabel ? /* @__PURE__ */ jsx(Text3, { bold: !spokeLast, color: spokeLast ? "#888888" : "#FF8700", children: " " + unresolvedLabel }) : null,
2067
- showAuthor ? /* @__PURE__ */ jsx(Text3, { dimColor: true, italic: true, children: " by " + item.author }) : null,
2068
- ageLabel ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: " " + ageLabel }) : null,
2069
- mergedLabel ? /* @__PURE__ */ jsx(Text3, { bold: true, color: MERGED_COLOUR, children: " " + mergedLabel }) : null,
2070
- transitLabel ? /* @__PURE__ */ jsx(Text3, { bold: true, color: TRANSIT_COLOUR[transient], children: " " + transitLabel }) : null
2093
+ repoLabel && !givingUp.repo ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: repoLabel }) : null,
2094
+ unresolvedLabel && !givingUp.threads ? /* @__PURE__ */ jsx(Text3, { bold: !spokeLast, color: spokeLast ? "#888888" : "#FF8700", children: " " + unresolvedLabel }) : null,
2095
+ showAuthor && !givingUp.author ? /* @__PURE__ */ jsx(Text3, { dimColor: true, italic: true, children: " by " + item.author }) : null,
2096
+ ageLabel && !givingUp.age ? /* @__PURE__ */ jsx(Text3, { dimColor: true, children: " " + ageLabel }) : null,
2097
+ mergedLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
2098
+ /* @__PURE__ */ jsx(Text3, { children: " " }),
2099
+ /* @__PURE__ */ jsx(Pill, { color: MERGED_COLOUR, children: mergedLabel })
2100
+ ] }) : null,
2101
+ transitLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
2102
+ /* @__PURE__ */ jsx(Text3, { children: " " }),
2103
+ /* @__PURE__ */ jsx(Pill, { color: TRANSIT_COLOUR[transient], children: transitLabel })
2104
+ ] }) : null
2071
2105
  ] });
2072
2106
  };
2073
2107
  var useActionMenu = () => {
@@ -3288,8 +3322,8 @@ var App = ({
3288
3322
  }
3289
3323
  showData(fresh.sections, fresh.login);
3290
3324
  } else if (freshKey !== displayedKey.current) {
3291
- const { counts } = diffSections(displayedSections.current, fresh.sections);
3292
- if (counts.added + counts.removed + counts.changed === 0)
3325
+ const { counts: counts2 } = diffSections(displayedSections.current, fresh.sections);
3326
+ if (counts2.added + counts2.removed + counts2.changed === 0)
3293
3327
  showData(fresh.sections, fresh.login);
3294
3328
  else setPending(fresh);
3295
3329
  } else {
@@ -3533,4 +3567,4 @@ var matchesFilter = (repo, filter) => {
3533
3567
  };
3534
3568
  var parsePatterns = (value) => value.split(",").map((p) => p.trim()).filter(Boolean);
3535
3569
 
3536
- export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, PIN_MARK, SIDEBAR_COLS, SidePanel, budgetNotice, buildActions, buildCheckoutCmd, checkoutDirs, clipboard, configureInbox, drillCmd, explainGhAction, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, profileOf, railCapacity, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate2 as truncate, useActionMenu, whoseMove, windowCount, withHeaders, withoutItem, writeCache };
3570
+ export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, PIN_MARK, SIDEBAR_COLS, SidePanel, budgetNotice, buildActions, buildCheckoutCmd, checkoutDirs, clipboard, configureInbox, counts, drillCmd, explainGhAction, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, profileOf, railCapacity, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate2 as 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.39.0",
3
+ "version": "0.41.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",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@kud/gh": "0.9.0",
52
- "@kud/ink-ui": "0.17.0",
52
+ "@kud/ink-ui": "0.18.0",
53
53
  "zx": "8.8.5"
54
54
  },
55
55
  "devDependencies": {