@kud/gh-ink 0.54.0 → 0.55.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
@@ -2,7 +2,7 @@ import React, { ReactNode } from 'react';
2
2
  import { PrComments, PrHealthData, PrCheck, Health } from '@kud/gh';
3
3
  import { StyledLine } from '@kud/ink-ui';
4
4
  import { AnyItem, Section, CiStatus, GHItem, OriginSplit } from '@kud/gh-workflow';
5
- export { AnyItem, CiStatus, GHDetail, GHItem, InboxConfig, Move, OriginSplit, PIN_MARK, RepoHeader, RepoProfile, Section, ShowLess, ShowMore, Standing, SubgroupHeader, TaskRow, checkoutDirs, configureInbox, filterByOrigin, filterByRepos, filterBySearch, impliedLabels, inboxConfig, insertRepoHeaders, labelPriority, layoutGHItems, profileOf, relativeTime, repoPriority, resetInboxConfig, sortByRecency, sortItems, whoseMove } from '@kud/gh-workflow';
5
+ 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';
6
6
 
7
7
  type CommentsPanelProps = {
8
8
  repo: string;
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import { readFileSync, mkdirSync, writeFileSync, existsSync, readdirSync, statSy
9
9
  import { join, dirname, basename } from 'path';
10
10
  import { homedir } from 'os';
11
11
  import { depthOf, checkoutDirs, profileOf, inboxConfig, relativeTime, filterBySearch, filterByRepos, filterByOrigin, PIN_MARK, sizeOf, sizePartsOf, impliedLabels, labelPriority } from '@kud/gh-workflow';
12
- export { PIN_MARK, checkoutDirs, configureInbox, filterByOrigin, filterByRepos, filterBySearch, impliedLabels, inboxConfig, insertRepoHeaders, labelPriority, layoutGHItems, profileOf, relativeTime, repoPriority, resetInboxConfig, sortByRecency, sortItems, whoseMove } from '@kud/gh-workflow';
12
+ 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';
13
13
 
14
14
  // src/components/comments-panel.tsx
15
15
  var ENTITIES = {
@@ -934,6 +934,66 @@ var tabsOfMarks = (sections, marks) => {
934
934
  }
935
935
  return out;
936
936
  };
937
+ var HOLD_MS = 5 * 60 * 1e3;
938
+ var anchorIndex = (prevItems, prevIndex, freshItems) => {
939
+ const freshAt = /* @__PURE__ */ new Map();
940
+ freshItems.forEach((item, i) => {
941
+ const key = keyOf(item);
942
+ if (key) freshAt.set(key, i);
943
+ });
944
+ for (let i = prevIndex - 1; i >= 0; i--) {
945
+ const key = keyOf(prevItems[i]);
946
+ const at = key === null ? void 0 : freshAt.get(key);
947
+ if (at !== void 0) return at + 1;
948
+ }
949
+ return Math.min(prevIndex, freshItems.length);
950
+ };
951
+ var reconcile = (prev, fresh, now, holdMs = HOLD_MS) => {
952
+ if (prev.length === 0) return fresh;
953
+ const present = /* @__PURE__ */ new Set();
954
+ for (const section of fresh)
955
+ for (const item of section.items) {
956
+ const key = keyOf(item);
957
+ if (key) present.add(key);
958
+ }
959
+ const bySection = /* @__PURE__ */ new Map();
960
+ const labels = /* @__PURE__ */ new Map();
961
+ prev.forEach((section, at) => {
962
+ if (section.sampled) return;
963
+ section.items.forEach((item, index) => {
964
+ if (item.kind !== "pr" && item.kind !== "issue") return;
965
+ const row = item;
966
+ if (present.has(row.url)) return;
967
+ const heldSince = row.heldSince ?? now;
968
+ if (now - heldSince > holdMs) return;
969
+ const held = { ...row, heldSince };
970
+ const list = bySection.get(section.id);
971
+ if (list) list.push({ item: held, index });
972
+ else bySection.set(section.id, [{ item: held, index }]);
973
+ labels.set(section.id, { label: section.label, at });
974
+ });
975
+ });
976
+ if (bySection.size === 0) return fresh;
977
+ const out = fresh.map((section) => {
978
+ const rows = bySection.get(section.id);
979
+ if (!rows) return section;
980
+ bySection.delete(section.id);
981
+ const prevItems = prev.find((s) => s.id === section.id)?.items ?? [];
982
+ const items = [...section.items];
983
+ for (const row of [...rows].sort((a, b) => a.index - b.index))
984
+ items.splice(anchorIndex(prevItems, row.index, items), 0, row.item);
985
+ return { ...section, items };
986
+ });
987
+ for (const [id, rows] of bySection) {
988
+ const { label, at } = labels.get(id);
989
+ out.splice(Math.min(at, out.length), 0, {
990
+ id,
991
+ label,
992
+ items: rows.sort((a, b) => a.index - b.index).map((r) => r.item)
993
+ });
994
+ }
995
+ return out;
996
+ };
937
997
  var quietly = $({ quiet: true });
938
998
  var healthSentence = (item) => {
939
999
  const glyph = displayFor(item.health).glyph.trim();
@@ -1895,7 +1955,8 @@ var ItemRow = ({
1895
1955
  prefix = "",
1896
1956
  parent,
1897
1957
  sparkFrame = 0,
1898
- cols = COLS
1958
+ cols = COLS,
1959
+ markerCols = 0
1899
1960
  }) => {
1900
1961
  const backdropped = useBackdropped();
1901
1962
  const transient = leaving ? "out" : refreshMark;
@@ -1928,13 +1989,14 @@ var ItemRow = ({
1928
1989
  const transitIcon = !transient ? " " : isDeparture(transient) ? TRANSIT_OUT_FRAMES[rampAt(TRANSIT_OUT_FRAMES.length)] : isArrival(transient) ? TRANSIT_IN_FRAMES[rampAt(TRANSIT_IN_FRAMES.length)] : "\u25C9";
1929
1990
  const titleMax2 = Math.max(
1930
1991
  1,
1931
- cols - item.key.length - note.length - (item.pill ? pillWidth(item.pill) + 1 : 0) - (farewellLabel ? pillWidth(farewellLabel) + 2 : 0) - prefix.length - 12
1992
+ cols - item.key.length - note.length - (item.pill ? pillWidth(item.pill) + 1 : 0) - (farewellLabel ? pillWidth(farewellLabel) + 2 : 0) - prefix.length - (markerCols > 0 ? markerCols + 1 : 0) - 12
1932
1993
  );
1933
1994
  return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
1934
1995
  /* @__PURE__ */ jsx(Text3, { color: "cyan", children: active ? "\u276F " : " " }),
1935
1996
  /* @__PURE__ */ jsx(Text3, { dimColor: true, children: prefix }),
1936
1997
  /* @__PURE__ */ jsx(Text3, { dimColor: true, children: parent ? "\u252C " : " " }),
1937
1998
  /* @__PURE__ */ jsx(Text3, { bold: true, color: transient ? TRANSIT_COLOUR[transient] : void 0, children: transitIcon + " " }),
1999
+ markerCols > 0 ? /* @__PURE__ */ jsx(Text3, { color: item.markerColor, children: (item.marker ?? "").padEnd(markerCols) + " " }) : null,
1938
2000
  /* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: active, children: item.key + " " }),
1939
2001
  /* @__PURE__ */ jsx(
1940
2002
  Text3,
@@ -2511,6 +2573,10 @@ var BrowseScreen = ({
2511
2573
  const viewStart = viewStarts[activeId] ?? 0;
2512
2574
  const visibleCount = windowCount(section.items, viewStart, listHeight);
2513
2575
  const visibleItems = section.items.slice(viewStart, viewStart + visibleCount);
2576
+ const markerCols = section.items.reduce(
2577
+ (w, i) => i.kind === "task" ? Math.max(w, [...i.marker ?? ""].length) : w,
2578
+ 0
2579
+ );
2514
2580
  const hasMore = viewStart + visibleCount < section.items.length;
2515
2581
  const activeItem = section.items[cursor];
2516
2582
  const showFlash = (msg) => {
@@ -3130,6 +3196,7 @@ var BrowseScreen = ({
3130
3196
  parent: item.kind === "task" && depthOf(section.items[viewStart + i + 1]) > depthOf(item),
3131
3197
  sparkFrame,
3132
3198
  cols: listCols,
3199
+ markerCols,
3133
3200
  gap: i > 0 && gapsAbove(section.items, viewStart + i)
3134
3201
  },
3135
3202
  `${viewStart + i}:${rowKey(item)}`
@@ -3351,7 +3418,15 @@ var App = ({
3351
3418
  }
3352
3419
  setSkippedForBudget(false);
3353
3420
  if (manual) setRefreshing(true);
3354
- fetcher().then((fresh) => {
3421
+ fetcher().then((fetched) => {
3422
+ const fresh = {
3423
+ ...fetched,
3424
+ sections: reconcile(
3425
+ displayedSections.current,
3426
+ fetched.sections,
3427
+ Date.now()
3428
+ )
3429
+ };
3355
3430
  if (fresh.budget) setBudget(fresh.budget);
3356
3431
  if (fresh.sidebar !== void 0) setSidebar(fresh.sidebar);
3357
3432
  if (cacheKey) writeCache(cacheKey, fresh);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/gh-ink",
3
- "version": "0.54.0",
3
+ "version": "0.55.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.16.0",
52
- "@kud/gh-workflow": "0.11.0",
52
+ "@kud/gh-workflow": "0.12.0",
53
53
  "@kud/ink-ui": "0.29.0",
54
54
  "zx": "8.8.5"
55
55
  },