@kud/gh-ink 0.23.0 → 0.23.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
@@ -282,6 +282,21 @@ declare const CiStatusLine: ({ state, job, }: {
282
282
  state: CiStatusState;
283
283
  job?: string;
284
284
  }) => 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>;
285
300
  declare const useActionMenu: () => {
286
301
  actions: Action[] | null;
287
302
  cursor: number;
@@ -429,4 +444,4 @@ declare const matchesFilter: (repo: string, filter: RepoFilter) => boolean;
429
444
  */
430
445
  declare const parsePatterns: (value: string) => string[];
431
446
 
432
- 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, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, whoseMove, windowCount, withHeaders, withoutItem, writeCache };
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, repeatedTaskRows, 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
@@ -1685,6 +1685,16 @@ var TRANSIT_LABEL = {
1685
1685
  };
1686
1686
  var TAB_MARK = "\u25CF";
1687
1687
  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
+ };
1688
1698
  var isChildRow = (item) => !!item && (item.kind === "show-more" || item.kind === "show-less" || "indent" in item && item.indent === true);
1689
1699
  var ItemRow = ({
1690
1700
  item,
@@ -1695,6 +1705,7 @@ var ItemRow = ({
1695
1705
  transient,
1696
1706
  lastChild,
1697
1707
  parent,
1708
+ repeat,
1698
1709
  sparkFrame = 0
1699
1710
  }) => {
1700
1711
  if (item.kind === "repo-header")
@@ -1730,8 +1741,8 @@ var ItemRow = ({
1730
1741
  /* @__PURE__ */ jsx(Text2, { color: "cyan", children: active ? "\u276F " : " " }),
1731
1742
  /* @__PURE__ */ jsx(Text2, { bold: true, color: transient ? TRANSIT_COLOUR[transient] : void 0, children: transitIcon + " " }),
1732
1743
  /* @__PURE__ */ jsx(Text2, { dimColor: true, children: parent ? "\u252C " : " " }),
1733
- /* @__PURE__ */ jsx(Text2, { color: "#FF8700", bold: active, children: item.key + " " }),
1734
- /* @__PURE__ */ jsx(
1744
+ /* @__PURE__ */ jsx(Text2, { color: repeat ? void 0 : "#FF8700", dimColor: repeat, bold: active, children: item.key + " " }),
1745
+ repeat ? null : /* @__PURE__ */ jsx(
1735
1746
  Text2,
1736
1747
  {
1737
1748
  bold: active || transient === "in",
@@ -1740,7 +1751,7 @@ var ItemRow = ({
1740
1751
  children: truncate(item.summary, titleMax2)
1741
1752
  }
1742
1753
  ),
1743
- note ? /* @__PURE__ */ jsx(Text2, { dimColor: true, children: ` ${note}` }) : null,
1754
+ note && !repeat ? /* @__PURE__ */ jsx(Text2, { dimColor: true, children: ` ${note}` }) : null,
1744
1755
  transitLabel2 ? /* @__PURE__ */ jsx(Text2, { bold: true, color: TRANSIT_COLOUR[transient], children: " " + transitLabel2 }) : null
1745
1756
  ] });
1746
1757
  }
@@ -2198,6 +2209,10 @@ var BrowseScreen = ({
2198
2209
  { vimKeys: false, isActive: repoPicker }
2199
2210
  );
2200
2211
  const cursor = cursors[activeId] ?? 0;
2212
+ const repeatedTasks = useMemo(
2213
+ () => repeatedTaskRows(section.items),
2214
+ [section.items]
2215
+ );
2201
2216
  const viewStart = viewStarts[activeId] ?? 0;
2202
2217
  const visibleCount = windowCount(section.items, viewStart, listHeight);
2203
2218
  const visibleItems = section.items.slice(viewStart, viewStart + visibleCount);
@@ -2609,6 +2624,7 @@ var BrowseScreen = ({
2609
2624
  transient: transientOf(transients, item),
2610
2625
  lastChild: "indent" in item && item.indent ? !isChildRow(section.items[viewStart + i + 1]) : void 0,
2611
2626
  parent: item.kind === "task" && isChildRow(section.items[viewStart + i + 1]),
2627
+ repeat: repeatedTasks.has(viewStart + i),
2612
2628
  sparkFrame,
2613
2629
  gap: (
2614
2630
  // Window-relative, never `viewStart + i`. fitCount prices the
@@ -3019,4 +3035,4 @@ var matchesFilter = (repo, filter) => {
3019
3035
  };
3020
3036
  var parsePatterns = (value) => value.split(",").map((p) => p.trim()).filter(Boolean);
3021
3037
 
3022
- 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, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, whoseMove, windowCount, withHeaders, withoutItem, writeCache };
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, repeatedTaskRows, 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.0",
3
+ "version": "0.23.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",