@kud/gh-ink 0.76.0 → 0.76.2

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
@@ -995,9 +995,10 @@ declare const ActionMenu: ({ item, actions, cursor, cols, }: {
995
995
  cursor: number;
996
996
  /**
997
997
  * Content columns the menu may take. The width is fixed from the longest
998
- * row — clamp(longest + 4, 40, 56), capped at `cols - 4` — so it never
998
+ * row and the title — see `menuWidthFor` — so it never
999
999
  * resizes as the cursor moves. A host beside a rail passes what the list
1000
- * has; everywhere else the frame's own width is the right answer.
1000
+ * has; everywhere else the frame's own width is the right answer, read live
1001
+ * rather than from the load-time sample — see `useFrameCols`.
1001
1002
  */
1002
1003
  cols?: number;
1003
1004
  }) => React.JSX.Element;
package/dist/index.js CHANGED
@@ -2358,6 +2358,7 @@ var FRAME_PAD_X = 1;
2358
2358
  var FRAME_CHROME_COLS = 2 + FRAME_PAD_X * 2;
2359
2359
  var COLS = (process.stdout.columns ?? 120) - FRAME_CHROME_COLS;
2360
2360
  var MODAL_CHROME_COLS = 2 + 1 * 2;
2361
+ var useFrameCols = () => useWindowSize().columns - FRAME_CHROME_COLS;
2361
2362
  var ROW_MAX_COLS = 140;
2362
2363
  var OVERLAY_BG = "#22222e";
2363
2364
  var SELECTION_BG = "#16161f";
@@ -2829,6 +2830,8 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
2829
2830
  actions.push(...closing);
2830
2831
  return byGroup(actions);
2831
2832
  };
2833
+ var TAB_STRIP_ROWS = 3;
2834
+ var FILTER_BAR_ROWS = 2;
2832
2835
  var agoText = (ms) => {
2833
2836
  const d = (Date.now() - ms) / 1e3;
2834
2837
  if (d < 60) return "just now";
@@ -2852,6 +2855,7 @@ var InboxHeader = ({
2852
2855
  appliedSummary,
2853
2856
  fetchedAt
2854
2857
  }) => {
2858
+ const frameCols = useFrameCols();
2855
2859
  const total = sections.reduce((n, s) => n + workCount(s), 0);
2856
2860
  const countSeg = loading ? " loading\u2026 " : quiet ? " " : ` ${String(total).padStart(3)} item${total !== 1 ? "s" : ""} \xB7 `;
2857
2861
  const userSeg = loading || quiet ? "" : `@${login} `;
@@ -2861,7 +2865,7 @@ var InboxHeader = ({
2861
2865
  const statusSeg = statusText ? statusText + " " : "";
2862
2866
  const fill = Math.max(
2863
2867
  4,
2864
- COLS - brand.length - countSeg.length - userSeg.length - workLabel.length - budgetSeg.length - statusSeg.length
2868
+ frameCols - brand.length - countSeg.length - userSeg.length - workLabel.length - budgetSeg.length - statusSeg.length
2865
2869
  );
2866
2870
  return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
2867
2871
  /* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: true, children: brand }),
@@ -3000,7 +3004,7 @@ var ItemRow = ({
3000
3004
  prefix = "",
3001
3005
  parent,
3002
3006
  sparkFrame = 0,
3003
- cols = COLS,
3007
+ cols,
3004
3008
  markerCols = 0,
3005
3009
  uniformLabels = [],
3006
3010
  columns,
@@ -3188,12 +3192,20 @@ var useActionMenu = () => {
3188
3192
  };
3189
3193
  return { actions, cursor, open, close: () => setActions(null), handleKey };
3190
3194
  };
3195
+ var TITLE_SLACK = 1;
3196
+ var MENU_MAX_WIDTH = 88;
3197
+ var menuWidthFor = (cols, contentWidth, titleWidth) => Math.min(
3198
+ Math.max(contentWidth + 4, titleWidth + 4, 40),
3199
+ MENU_MAX_WIDTH,
3200
+ Math.max(20, cols - 4)
3201
+ );
3191
3202
  var ActionMenu = ({
3192
3203
  item,
3193
3204
  actions,
3194
3205
  cursor,
3195
- cols = COLS
3206
+ cols
3196
3207
  }) => {
3208
+ const frameCols = useFrameCols();
3197
3209
  const showIcons = getIconMode() === "nerd" && actions.some((row) => !isMenuGap(row) && row.icon !== void 0);
3198
3210
  const keyWidth = Math.max(
3199
3211
  0,
@@ -3209,19 +3221,16 @@ var ActionMenu = ({
3209
3221
  ]
3210
3222
  )
3211
3223
  );
3212
- const width = Math.min(
3213
- Math.max(contentWidth + 4, 40),
3214
- 56,
3215
- Math.max(20, cols - 4)
3216
- );
3217
- const inner = Math.max(1, width - 4);
3218
3224
  const confirming = isConfirmRows(actions);
3219
- const isCloseRow = (row) => menuTone(row) === "error";
3220
3225
  const number = item.kind === "pr" || item.kind === "issue" ? item.number : null;
3221
3226
  const leadNum = item.kind === "task" ? item.key : number !== null ? `#${number}` : "";
3222
3227
  const lead = leadNum ? `${leadNum} \xB7 ` : "";
3223
3228
  const rest = confirming ? `Close #${number}?` : item.kind === "task" ? item.summary : item.kind === "pr" || item.kind === "issue" ? item.title : "";
3224
- const restText = [...lead].length + [...rest].length <= inner ? rest : [...rest].slice(0, Math.max(0, inner - [...lead].length - 1)).join("") + "\u2026";
3229
+ const titleWidth = [...lead].length + [...rest].length + TITLE_SLACK;
3230
+ const width = menuWidthFor(cols ?? frameCols, contentWidth, titleWidth);
3231
+ const inner = Math.max(1, width - 4);
3232
+ const restText = [...lead].length + [...rest].length + TITLE_SLACK <= inner ? rest : [...rest].slice(0, Math.max(0, inner - [...lead].length - 1 - TITLE_SLACK)).join("") + "\u2026";
3233
+ const isCloseRow = (row) => menuTone(row) === "error";
3225
3234
  return /* @__PURE__ */ jsxs(
3226
3235
  Box,
3227
3236
  {
@@ -3461,26 +3470,29 @@ var HelpModal = ({
3461
3470
  }
3462
3471
  );
3463
3472
  };
3464
- var ExplainModal = ({ item, login }) => /* @__PURE__ */ jsxs(
3465
- Box,
3466
- {
3467
- flexDirection: "column",
3468
- borderStyle: "round",
3469
- borderColor: colors.info,
3470
- backgroundColor: OVERLAY_BG,
3471
- paddingX: 1,
3472
- width: Math.min(COLS, 78),
3473
- children: [
3474
- /* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: true, children: `#${item.number} \xB7 ${item.repo}` }),
3475
- /* @__PURE__ */ jsx(Text3, { children: item.title }),
3476
- explainItem(item, login).map((section) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
3477
- /* @__PURE__ */ jsx(Text3, { bold: true, dimColor: true, children: section.heading }),
3478
- section.lines.map((line, i) => /* @__PURE__ */ jsx(Text3, { children: " " + line }, i))
3479
- ] }, section.heading)),
3480
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text3, { dimColor: true, children: "esc \xB7 e close" }) })
3481
- ]
3482
- }
3483
- );
3473
+ var ExplainModal = ({ item, login }) => {
3474
+ const frameCols = useFrameCols();
3475
+ return /* @__PURE__ */ jsxs(
3476
+ Box,
3477
+ {
3478
+ flexDirection: "column",
3479
+ borderStyle: "round",
3480
+ borderColor: colors.info,
3481
+ backgroundColor: OVERLAY_BG,
3482
+ paddingX: 1,
3483
+ width: Math.min(frameCols, 78),
3484
+ children: [
3485
+ /* @__PURE__ */ jsx(Text3, { color: colors.accent, bold: true, children: `#${item.number} \xB7 ${item.repo}` }),
3486
+ /* @__PURE__ */ jsx(Text3, { children: item.title }),
3487
+ explainItem(item, login).map((section) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
3488
+ /* @__PURE__ */ jsx(Text3, { bold: true, dimColor: true, children: section.heading }),
3489
+ section.lines.map((line, i) => /* @__PURE__ */ jsx(Text3, { children: " " + line }, i))
3490
+ ] }, section.heading)),
3491
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text3, { dimColor: true, children: "esc \xB7 e close" }) })
3492
+ ]
3493
+ }
3494
+ );
3495
+ };
3484
3496
  var RepoPicker = ({
3485
3497
  repos,
3486
3498
  selected,
@@ -3581,6 +3593,7 @@ var BrowseScreen = ({
3581
3593
  onRestore
3582
3594
  }) => {
3583
3595
  const { rows } = useWindowSize();
3596
+ const frameCols = useFrameCols();
3584
3597
  const applyWork = (secs) => origin ? filterByOrigin(secs, origin.show, origin.match, login) : secs;
3585
3598
  const initialSections = applyWork(sections);
3586
3599
  const [localSections, setLocalSections] = useState(initialSections);
@@ -3750,8 +3763,8 @@ var BrowseScreen = ({
3750
3763
  useEffect(() => {
3751
3764
  onTyping?.(searchInput || palette !== null);
3752
3765
  }, [searchInput, palette, onTyping]);
3753
- const railCols = railWidth(COLS);
3754
- const listCols = showRail ? COLS - railCols : COLS;
3766
+ const railCols = railWidth(frameCols);
3767
+ const listCols = showRail ? frameCols - railCols : frameCols;
3755
3768
  const { trailingColumns, numberCols } = listColumnsOf(localSections);
3756
3769
  const rowCols = Math.min(listCols, ROW_MAX_COLS);
3757
3770
  const trailingShed = sectionShedOf(
@@ -4525,7 +4538,7 @@ var BrowseScreen = ({
4525
4538
  {
4526
4539
  strip: stripState.kind === "ready" ? stripState.strip : void 0,
4527
4540
  label: stripLabel,
4528
- width: COLS
4541
+ width: frameCols
4529
4542
  }
4530
4543
  ) : null,
4531
4544
  reserveFocusRow ? /* @__PURE__ */ jsx(
@@ -4534,7 +4547,7 @@ var BrowseScreen = ({
4534
4547
  focus,
4535
4548
  label: focusLabel,
4536
4549
  empty: focusEmpty,
4537
- width: COLS,
4550
+ width: frameCols,
4538
4551
  jumpKey: FOCUS_JUMP_KEY
4539
4552
  }
4540
4553
  ) : null,
@@ -4546,7 +4559,7 @@ var BrowseScreen = ({
4546
4559
  Tabs,
4547
4560
  {
4548
4561
  active: section.id,
4549
- width: COLS,
4562
+ width: frameCols,
4550
4563
  items: localSections.map((s) => ({
4551
4564
  value: s.id,
4552
4565
  label: s.label,
@@ -4600,7 +4613,21 @@ var BrowseScreen = ({
4600
4613
  // and footer below, the body where the list was. Fixed to the list's
4601
4614
  // own height so the frame holds still between browse and drill, and
4602
4615
  // clipped rather than spilling past the footer on a long body.
4603
- /* @__PURE__ */ jsx(Box, { flexDirection: "column", height: listHeight, overflow: "hidden", children: overlayBody })
4616
+ //
4617
+ // Plus the rows the overlay hides: the tab strip and, when a filter
4618
+ // is on, its bar. `listHeight` already paid for both, so a band of
4619
+ // exactly `listHeight` left the frame three rows short of the
4620
+ // terminal under every drill and extension body, five with a filter
4621
+ // kept — the bottom border floating above the screen's edge.
4622
+ /* @__PURE__ */ jsx(
4623
+ Box,
4624
+ {
4625
+ flexDirection: "column",
4626
+ height: listHeight + TAB_STRIP_ROWS + (filterActive ? FILTER_BAR_ROWS : 0),
4627
+ overflow: "hidden",
4628
+ children: overlayBody
4629
+ }
4630
+ )
4604
4631
  ) : /* @__PURE__ */ jsxs(
4605
4632
  Box,
4606
4633
  {
@@ -4748,6 +4775,7 @@ var App = ({
4748
4775
  onSettled
4749
4776
  }) => {
4750
4777
  const { rows } = useWindowSize();
4778
+ const frameCols = useFrameCols();
4751
4779
  const [launchCache] = useState(() => cacheKey ? readCache(cacheKey) : null);
4752
4780
  const launchPainted = !!launchCache && launchCache.sections.length > 0;
4753
4781
  const [state, setState] = useState(
@@ -5208,7 +5236,7 @@ var App = ({
5208
5236
  {
5209
5237
  strip: stripState.kind === "ready" ? stripState.strip : void 0,
5210
5238
  label: stripLabel,
5211
- width: COLS
5239
+ width: frameCols
5212
5240
  }
5213
5241
  ) : null,
5214
5242
  hasFocusSlot ? /* @__PURE__ */ jsx(
@@ -5217,7 +5245,7 @@ var App = ({
5217
5245
  focus: void 0,
5218
5246
  label: focusLabel,
5219
5247
  empty: focusEmpty,
5220
- width: COLS
5248
+ width: frameCols
5221
5249
  }
5222
5250
  ) : null,
5223
5251
  /* @__PURE__ */ jsx(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/gh-ink",
3
- "version": "0.76.0",
3
+ "version": "0.76.2",
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",