@kud/gh-ink 0.12.0 → 0.14.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
@@ -76,15 +76,35 @@ type GHItem = {
76
76
  detail?: GHDetail;
77
77
  indent: boolean;
78
78
  };
79
- type JiraRow = {
80
- kind: "jira";
79
+ type TaskRow = {
80
+ kind: "task";
81
81
  key: string;
82
82
  summary: string;
83
83
  url: string;
84
- jiraStatus: string;
84
+ status: string;
85
85
  age: string;
86
86
  indent: boolean;
87
87
  instanceKey?: string;
88
+ /**
89
+ * Trailing annotation, rendered dim after the summary — a recurrence marker,
90
+ * a source hint, anything secondary to the title. Its own node rather than
91
+ * part of `summary` so it can be dimmed, and so its width is measured
92
+ * separately instead of being smuggled past the truncation maths.
93
+ */
94
+ note?: string;
95
+ /**
96
+ * The Jira issue key behind this row, when one exists. Its PRESENCE is what
97
+ * turns on the ticket affordances — ↵ opens a menu led by `jira issue view`,
98
+ * and `t` transitions the issue. A row without it is just a task: ↵ opens its
99
+ * URL and nothing here shells out to `jira`.
100
+ *
101
+ * Separate from `key` because the two are not the same thing. `key` is the
102
+ * left column, and a caller is free to put anything legible there: cockpit
103
+ * puts the ticket key, `life` puts a Todoist project name. Reading the drill
104
+ * off `key` is what made `life` run `jira issue view "Maison "` and
105
+ * label it "View ticket" on a surface that has never touched Jira.
106
+ */
107
+ ticket?: string;
88
108
  };
89
109
  type RepoHeader = {
90
110
  kind: "repo-header";
@@ -108,7 +128,7 @@ type SubgroupHeader = {
108
128
  age: string;
109
129
  indent: boolean;
110
130
  };
111
- type AnyItem = GHItem | JiraRow | RepoHeader | SubgroupHeader | ShowMore | ShowLess;
131
+ type AnyItem = GHItem | TaskRow | RepoHeader | SubgroupHeader | ShowMore | ShowLess;
112
132
  type CiStatus = {
113
133
  job: string;
114
134
  buildNumber: number;
@@ -268,4 +288,4 @@ declare const writeCache: (key: string, data: {
268
288
  login: string;
269
289
  }) => void;
270
290
 
271
- 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 InboxExtension, type JiraRow, type JiraTransition, type RepoHeader, type Section, type ShowLess, type ShowMore, type SubgroupHeader, buildActions, buildCheckoutCmd, clipboard, drillCmd, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, healthColor, healthDisplay, healthGlyph, healthLegend, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, maxViewStart, moveCursor, openInTab, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, windowCount, withHeaders, withoutItem, writeCache };
291
+ 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 InboxExtension, type JiraTransition, type RepoHeader, type Section, type ShowLess, type ShowMore, type SubgroupHeader, type TaskRow, buildActions, buildCheckoutCmd, clipboard, drillCmd, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, healthColor, healthDisplay, healthGlyph, healthLegend, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, maxViewStart, moveCursor, openInTab, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, windowCount, withHeaders, withoutItem, writeCache };
package/dist/index.js CHANGED
@@ -641,9 +641,9 @@ var invalidateCache = (key) => {
641
641
  // src/inbox/diff.ts
642
642
  var keyOf = (item) => {
643
643
  if (item.kind === "pr" || item.kind === "issue") return item.url;
644
- if (item.kind === "jira") {
644
+ if (item.kind === "task") {
645
645
  const row = item;
646
- return row.url || `jira:${row.key}`;
646
+ return row.url || `task:${row.key}`;
647
647
  }
648
648
  return null;
649
649
  };
@@ -659,9 +659,9 @@ var renderedState = (item) => {
659
659
  i.author ?? ""
660
660
  ].join("|");
661
661
  }
662
- if (item.kind === "jira") {
662
+ if (item.kind === "task") {
663
663
  const j = item;
664
- return [j.summary, j.jiraStatus].join("|");
664
+ return [j.summary, j.status].join("|");
665
665
  }
666
666
  return "";
667
667
  };
@@ -881,7 +881,7 @@ var filterByOrigin = (sections, keep, isWorkRepo) => sections.map((s) => {
881
881
  (i) => i.kind !== "repo-header" && i.kind !== "subgroup-header"
882
882
  )
883
883
  );
884
- var searchText = (i) => i.kind === "pr" || i.kind === "issue" ? `${i.title} ${i.repo} #${i.number}` : i.kind === "jira" ? `${i.summary} ${i.key}` : "";
884
+ var searchText = (i) => i.kind === "pr" || i.kind === "issue" ? `${i.title} ${i.repo} #${i.number}` : i.kind === "task" ? `${i.summary} ${i.key}` : "";
885
885
  var filterBySearch = (sections, query) => {
886
886
  const q = query.trim().toLowerCase();
887
887
  if (!q) return sections;
@@ -1202,11 +1202,12 @@ var topLevelCount = (s) => s.items.filter(
1202
1202
  (i) => i.kind !== "repo-header" && i.kind !== "subgroup-header" && !i.indent
1203
1203
  ).length;
1204
1204
  var drillCmd = (item) => {
1205
- if (item.kind === "jira") return `jira issue view ${item.key}`;
1205
+ if (item.kind === "task")
1206
+ return item.ticket ? `jira issue view ${item.ticket}` : null;
1206
1207
  return null;
1207
1208
  };
1208
1209
  var drillLabel = (item) => {
1209
- if (item.kind === "jira") return "View ticket";
1210
+ if (item.kind === "task") return "View ticket";
1210
1211
  if (item.kind === "issue") return "View issue";
1211
1212
  if (item.kind === "pr") return "Open PR";
1212
1213
  return "Drill in";
@@ -1228,7 +1229,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1228
1229
  hint: "c",
1229
1230
  run: () => {
1230
1231
  clipboard(item.url);
1231
- const label = item.kind === "jira" ? item.key : `#${item.number}`;
1232
+ const label = item.kind === "task" ? item.key : `#${item.number}`;
1232
1233
  showFlash(`\u2713 Copied URL for ${label}`);
1233
1234
  }
1234
1235
  };
@@ -1246,9 +1247,9 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1246
1247
  }
1247
1248
  }
1248
1249
  } : null;
1249
- if (item.kind === "jira") {
1250
+ if (item.kind === "task") {
1250
1251
  const base = drillAction ? [drillAction, open, copyUrl] : [open, copyUrl];
1251
- if (jiraTransitions && jiraTransitions.length > 0) {
1252
+ if (item.ticket && jiraTransitions && jiraTransitions.length > 0) {
1252
1253
  base.push({
1253
1254
  label: "Move status",
1254
1255
  hint: "t",
@@ -1265,7 +1266,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1265
1266
  hint: "",
1266
1267
  run: () => {
1267
1268
  showFlash(`\u22EF ${label} \xB7 ${resolution}\u2026`);
1268
- void quietly`jira issue move ${item.key} ${state} --resolution ${resolution}`.then(() => {
1269
+ void quietly`jira issue move ${item.ticket} ${state} --resolution ${resolution}`.then(() => {
1269
1270
  showFlash(`\u2713 ${label} \xB7 ${resolution}`);
1270
1271
  ext?.onActed?.();
1271
1272
  }).catch(() => showFlash(`\u2717 Move to ${label} failed`));
@@ -1276,7 +1277,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1276
1277
  hint: "",
1277
1278
  run: () => {
1278
1279
  showFlash(`\u22EF Moving to ${label}\u2026`);
1279
- void quietly`jira issue move ${item.key} ${state}`.then(() => {
1280
+ void quietly`jira issue move ${item.ticket} ${state}`.then(() => {
1280
1281
  showFlash(`\u2713 Moved to ${label}`);
1281
1282
  ext?.onActed?.();
1282
1283
  }).catch(() => showFlash(`\u2717 Move to ${label} failed`));
@@ -1604,12 +1605,14 @@ var ItemRow = ({
1604
1605
  /* @__PURE__ */ jsx(Text2, { dimColor: true, children: active ? "\u21B5 " : " " }),
1605
1606
  /* @__PURE__ */ jsx(Text2, { dimColor: true, children: "show less" })
1606
1607
  ] });
1607
- if (item.kind === "jira") {
1608
- const titleMax2 = Math.max(20, COLS - item.key.length - 10);
1608
+ if (item.kind === "task") {
1609
+ const note = item.note ?? "";
1610
+ const titleMax2 = Math.max(20, COLS - item.key.length - note.length - 10);
1609
1611
  return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
1610
1612
  /* @__PURE__ */ jsx(Text2, { color: "cyan", children: active ? "\u276F " : " " }),
1611
1613
  /* @__PURE__ */ jsx(Text2, { color: "#FF8700", bold: active, children: item.key + " " }),
1612
- /* @__PURE__ */ jsx(Text2, { bold: active, children: truncate(item.summary, titleMax2) })
1614
+ /* @__PURE__ */ jsx(Text2, { bold: active, children: truncate(item.summary, titleMax2) }),
1615
+ note ? /* @__PURE__ */ jsx(Text2, { dimColor: true, children: ` ${note}` }) : null
1613
1616
  ] });
1614
1617
  }
1615
1618
  const { glyph: healthIcon, color: healthColor2 } = healthDisplay[item.health];
@@ -1687,7 +1690,7 @@ var ActionMenu = ({
1687
1690
  actions,
1688
1691
  cursor
1689
1692
  }) => {
1690
- const title = item.kind === "jira" ? item.key : item.kind === "pr" || item.kind === "issue" ? `#${item.number}` : "";
1693
+ const title = item.kind === "task" ? item.key : item.kind === "pr" || item.kind === "issue" ? `#${item.number}` : "";
1691
1694
  return /* @__PURE__ */ jsxs(
1692
1695
  Box,
1693
1696
  {
@@ -2220,6 +2223,12 @@ var BrowseScreen = ({
2220
2223
  return;
2221
2224
  if (key.return) {
2222
2225
  if (openDrillView(activeItem)) return;
2226
+ if (activeItem.kind === "task" && !activeItem.ticket) {
2227
+ void quietly`open ${activeItem.url}`.catch(() => {
2228
+ });
2229
+ showFlash("\u2197 Opened in browser");
2230
+ return;
2231
+ }
2223
2232
  openMenu();
2224
2233
  return;
2225
2234
  }
@@ -2234,13 +2243,13 @@ var BrowseScreen = ({
2234
2243
  if (input === "o") {
2235
2244
  quietly`open ${activeItem.url}`.catch(() => {
2236
2245
  });
2237
- const label = activeItem.kind === "jira" ? activeItem.key : `#${activeItem.number}`;
2246
+ const label = activeItem.kind === "task" ? activeItem.key : `#${activeItem.number}`;
2238
2247
  showFlash(`\u2197 Opened ${label}`);
2239
2248
  return;
2240
2249
  }
2241
2250
  if (input === "c") {
2242
2251
  clipboard(activeItem.url);
2243
- const label = activeItem.kind === "jira" ? activeItem.key : `#${activeItem.number}`;
2252
+ const label = activeItem.kind === "task" ? activeItem.key : `#${activeItem.number}`;
2244
2253
  showFlash(`\u2713 Copied URL for ${label}`);
2245
2254
  return;
2246
2255
  }
@@ -2259,7 +2268,7 @@ var BrowseScreen = ({
2259
2268
  showFlash(`\u2713 Copied ${activeItem.branch}`);
2260
2269
  return;
2261
2270
  }
2262
- if (activeItem.kind !== "jira") {
2271
+ if (activeItem.kind !== "task") {
2263
2272
  if (input === "s" && activeItem.kind === "pr" && activeItem.branch) {
2264
2273
  const script = [
2265
2274
  "delay 0.5",
@@ -2284,8 +2293,8 @@ var BrowseScreen = ({
2284
2293
  return;
2285
2294
  }
2286
2295
  }
2287
- if (input === "t" && activeItem && activeItem.kind === "jira" && jiraTransitions && jiraTransitions.length > 0) {
2288
- const jiraKey = activeItem.key;
2296
+ if (input === "t" && activeItem && activeItem.kind === "task" && activeItem.ticket && jiraTransitions && jiraTransitions.length > 0) {
2297
+ const jiraKey = activeItem.ticket;
2289
2298
  const actions = jiraTransitions.map(
2290
2299
  ({ label, state, resolutions }) => resolutions && resolutions.length > 0 ? {
2291
2300
  label,
@@ -2412,16 +2421,16 @@ var BrowseScreen = ({
2412
2421
  // the whole panel up a line instead of clipping.
2413
2422
  i > 0 && (item.kind === "repo-header" || item.kind === "subgroup-header" || // A header is always followed by a blank line before its
2414
2423
  // first child — in Other PRs that's "free" because the
2415
- // child is itself a repo-header (gap above). A jira row
2424
+ // child is itself a repo-header (gap above). A task row
2416
2425
  // has no such stand-in, so it needs this explicitly. Never
2417
2426
  // applies between two tickets/PRs — only right after a
2418
2427
  // header.
2419
- item.kind === "jira" && ["repo-header", "subgroup-header"].includes(
2428
+ item.kind === "task" && ["repo-header", "subgroup-header"].includes(
2420
2429
  section.items[viewStart + i - 1]?.kind
2421
2430
  ))
2422
2431
  )
2423
2432
  },
2424
- `${viewStart + i}:${item.kind === "jira" ? item.instanceKey ?? item.key : item.kind === "repo-header" ? `header:${item.repo}` : item.kind === "subgroup-header" ? `subgroup:${item.label}` : item.kind === "show-more" ? `show-more:${item.hidden[0]?.repo ?? i}` : item.kind === "show-less" ? `show-less:${item.toHide[0]?.repo ?? i}` : `${item.repo}/${item.number}`}`
2433
+ `${viewStart + i}:${item.kind === "task" ? item.instanceKey ?? item.key : item.kind === "repo-header" ? `header:${item.repo}` : item.kind === "subgroup-header" ? `subgroup:${item.label}` : item.kind === "show-more" ? `show-more:${item.hidden[0]?.repo ?? i}` : item.kind === "show-less" ? `show-less:${item.toHide[0]?.repo ?? i}` : `${item.repo}/${item.number}`}`
2425
2434
  )) }),
2426
2435
  hasMore && /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
2427
2436
  " ",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/gh-ink",
3
- "version": "0.12.0",
3
+ "version": "0.14.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",