@kud/gh-ink 0.30.0 → 0.31.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.
Files changed (2) hide show
  1. package/dist/index.js +33 -15
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1778,6 +1778,7 @@ var TRANSIT_LABEL = {
1778
1778
  out: "GONE",
1779
1779
  changed: "UPDATED"
1780
1780
  };
1781
+ var LEAVING_HOLD_MS = 2500;
1781
1782
  var TAB_MARK = "\u25CF";
1782
1783
  var tabLabel = (label, marked, id) => marked.size === 0 ? label : `${marked.has(id) ? TAB_MARK : " "} ${label}`;
1783
1784
  var ItemRow = ({
@@ -1786,11 +1787,13 @@ var ItemRow = ({
1786
1787
  gap,
1787
1788
  login,
1788
1789
  merged,
1789
- transient,
1790
+ transient: refreshMark,
1791
+ leaving,
1790
1792
  lastChild,
1791
1793
  parent,
1792
1794
  sparkFrame = 0
1793
1795
  }) => {
1796
+ const transient = leaving ? "out" : refreshMark;
1794
1797
  if (item.kind === "repo-header")
1795
1798
  return /* @__PURE__ */ jsx(RepoHeaderRow, { repo: item.repo, gap: gap ?? false });
1796
1799
  if (item.kind === "subgroup-header")
@@ -2212,6 +2215,8 @@ var BrowseScreen = ({
2212
2215
  skippedForBudget,
2213
2216
  brand,
2214
2217
  mergedUrls,
2218
+ leavingUrls,
2219
+ onLeave,
2215
2220
  transients,
2216
2221
  onTabChange
2217
2222
  }) => {
@@ -2281,7 +2286,7 @@ var BrowseScreen = ({
2281
2286
  )
2282
2287
  );
2283
2288
  }, [localSections, listHeight]);
2284
- const removeItemFromSections = (target) => setLocalSections((prev) => withoutItem(prev, target));
2289
+ const dismissItem = (target) => onLeave ? onLeave(target) : setLocalSections((prev) => withoutItem(prev, target));
2285
2290
  const rawSection = localSections[safeTabIdx] ?? {
2286
2291
  id: "empty",
2287
2292
  label: "",
@@ -2313,7 +2318,7 @@ var BrowseScreen = ({
2313
2318
  return out;
2314
2319
  }, [localSections, transients]);
2315
2320
  const [sparkFrame, setSparkFrame] = useState(0);
2316
- const sparkling = (mergedUrls?.length ?? 0) > 0 || !!transients?.size && section.items.some((item) => transientOf(transients, item));
2321
+ const sparkling = (mergedUrls?.length ?? 0) > 0 || (leavingUrls?.length ?? 0) > 0 || !!transients?.size && section.items.some((item) => transientOf(transients, item));
2317
2322
  useEffect(() => {
2318
2323
  if (!sparkling) return;
2319
2324
  const id = setInterval(() => setSparkFrame((f) => f + 1), MERGED_FRAME_MS);
@@ -2346,7 +2351,7 @@ var BrowseScreen = ({
2346
2351
  jiraKeyRe,
2347
2352
  jiraTransitions,
2348
2353
  onRefresh,
2349
- removeItemFromSections,
2354
+ dismissItem,
2350
2355
  openDrillView,
2351
2356
  { extensions, onOpenExt, onActed }
2352
2357
  );
@@ -2453,7 +2458,7 @@ var BrowseScreen = ({
2453
2458
  item: activeItem ?? void 0,
2454
2459
  ciJob: ciStatus?.job,
2455
2460
  login,
2456
- onRemove: (row) => removeItemFromSections(row),
2461
+ onRemove: (row) => dismissItem(row),
2457
2462
  showFlash
2458
2463
  });
2459
2464
  return;
@@ -2562,7 +2567,7 @@ var BrowseScreen = ({
2562
2567
  return;
2563
2568
  }
2564
2569
  if (input === "x" && activeItem.kind === "pr" && activeItem.standing === "queued" && login) {
2565
- removeItemFromSections(activeItem);
2570
+ dismissItem(activeItem);
2566
2571
  showFlash(`\u22EF Removing you from #${activeItem.number}\u2026`);
2567
2572
  void quietly`gh pr edit ${activeItem.number} --repo ${activeItem.repo} --remove-reviewer ${login}`.then(() => {
2568
2573
  showFlash(`\u2713 Removed you as reviewer on #${activeItem.number}`);
@@ -2729,6 +2734,7 @@ var BrowseScreen = ({
2729
2734
  active: viewStart + i === cursor,
2730
2735
  login,
2731
2736
  merged: (item.kind === "pr" || item.kind === "issue") && !!mergedUrls?.includes(item.url),
2737
+ leaving: (item.kind === "pr" || item.kind === "issue") && !!leavingUrls?.includes(item.url),
2732
2738
  transient: transientOf(transients, item),
2733
2739
  lastChild: "indent" in item && item.indent ? !isChildRow(section.items[viewStart + i + 1]) : void 0,
2734
2740
  parent: item.kind === "task" && isChildRow(section.items[viewStart + i + 1]),
@@ -3043,8 +3049,9 @@ var App = ({
3043
3049
  );
3044
3050
  const [skippedForBudget, setSkippedForBudget] = useState(false);
3045
3051
  const [mergedUrls, setMergedUrls] = useState([]);
3046
- const mergeTimers = useRef([]);
3047
- useEffect(() => () => mergeTimers.current.forEach(clearTimeout), []);
3052
+ const [leavingUrls, setLeavingUrls] = useState([]);
3053
+ const holdTimers = useRef([]);
3054
+ useEffect(() => () => holdTimers.current.forEach(clearTimeout), []);
3048
3055
  if (state.phase === "loading" || state.phase === "empty" || state.phase === "failed")
3049
3056
  return /* @__PURE__ */ jsxs(
3050
3057
  Box,
@@ -3092,17 +3099,26 @@ var App = ({
3092
3099
  target: state.target
3093
3100
  } : null;
3094
3101
  const toBrowse = () => setState({ phase: "browse", sections: state.sections, login: state.login });
3095
- const removeAndReturn = (target) => setState({
3096
- phase: "browse",
3097
- sections: withoutItem(state.sections, target),
3098
- login: state.login
3099
- });
3102
+ const markLeaving = (target) => {
3103
+ if (state.phase !== "browse") toBrowse();
3104
+ setLeavingUrls(
3105
+ (prev) => prev.includes(target.url) ? prev : [...prev, target.url]
3106
+ );
3107
+ holdTimers.current.push(
3108
+ setTimeout(() => {
3109
+ setLeavingUrls((prev) => prev.filter((u) => u !== target.url));
3110
+ setState(
3111
+ (s) => s.phase === "browse" ? { ...s, sections: withoutItem(s.sections, target) } : s
3112
+ );
3113
+ }, LEAVING_HOLD_MS)
3114
+ );
3115
+ };
3100
3116
  const markMerged = (target) => {
3101
3117
  toBrowse();
3102
3118
  setMergedUrls(
3103
3119
  (prev) => prev.includes(target.url) ? prev : [...prev, target.url]
3104
3120
  );
3105
- mergeTimers.current.push(
3121
+ holdTimers.current.push(
3106
3122
  setTimeout(() => {
3107
3123
  setMergedUrls((prev) => prev.filter((u) => u !== target.url));
3108
3124
  setState(
@@ -3133,6 +3149,8 @@ var App = ({
3133
3149
  skippedForBudget,
3134
3150
  hidden: overlay !== null,
3135
3151
  mergedUrls,
3152
+ leavingUrls,
3153
+ onLeave: markLeaving,
3136
3154
  transients,
3137
3155
  onTabChange: setVisibleTab,
3138
3156
  ciStatusState: hasCiStatus ? ciStatusState : void 0,
@@ -3166,7 +3184,7 @@ var App = ({
3166
3184
  login: state.login,
3167
3185
  onBack: toBrowse,
3168
3186
  onRefresh: applyOrRefresh,
3169
- onRemove: removeAndReturn,
3187
+ onRemove: markLeaving,
3170
3188
  onMerged: markMerged
3171
3189
  }),
3172
3190
  overlay?.kind === "ext" && extensions?.find((e) => e.id === overlay.extId)?.body(toBrowse, overlay.target)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/gh-ink",
3
- "version": "0.30.0",
3
+ "version": "0.31.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",