@ondrej-svec/hog 1.9.3 → 1.10.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/cli.js CHANGED
@@ -1999,7 +1999,8 @@ function useKeyboard({
1999
1999
  selectedRepoStatusOptionsLength,
2000
2000
  actions,
2001
2001
  onSearchEscape,
2002
- tabNav
2002
+ tabNav,
2003
+ statusNav
2003
2004
  }) {
2004
2005
  const {
2005
2006
  exit,
@@ -2096,6 +2097,14 @@ function useKeyboard({
2096
2097
  return;
2097
2098
  }
2098
2099
  if (input2 === "s") {
2100
+ statusNav?.next();
2101
+ return;
2102
+ }
2103
+ if (input2 === "S") {
2104
+ statusNav?.prev();
2105
+ return;
2106
+ }
2107
+ if (input2 === "o") {
2099
2108
  handleSlack();
2100
2109
  return;
2101
2110
  }
@@ -2187,6 +2196,7 @@ function useKeyboard({
2187
2196
  ui,
2188
2197
  nav,
2189
2198
  tabNav,
2199
+ statusNav,
2190
2200
  exit,
2191
2201
  refresh,
2192
2202
  handleSlack,
@@ -3018,7 +3028,7 @@ function HintBar({ uiMode, multiSelectCount, searchQuery, mineOnly, hasUndoable
3018
3028
  }
3019
3029
  return /* @__PURE__ */ jsxs3(Box3, { children: [
3020
3030
  /* @__PURE__ */ jsxs3(Text3, { color: "gray", children: [
3021
- "j/k:nav Tab:next-tab 1-9:jump Enter:open m:status c:comment F:find t:@me e:edit",
3031
+ "j/k:nav Tab:repo s/S:status Enter:open m:status c:comment F:find t:@me e:edit",
3022
3032
  hasUndoable ? " u:undo" : "",
3023
3033
  " ?:more q:quit"
3024
3034
  ] }),
@@ -4067,9 +4077,10 @@ var init_help_overlay = __esm({
4067
4077
  items: [
4068
4078
  { key: "j / Down", desc: "Move down" },
4069
4079
  { key: "k / Up", desc: "Move up" },
4070
- { key: "Tab", desc: "Next tab" },
4071
- { key: "Shift+Tab", desc: "Previous tab" },
4072
- { key: "1-9", desc: "Jump to tab by number" }
4080
+ { key: "Tab", desc: "Next repo tab" },
4081
+ { key: "Shift+Tab", desc: "Previous repo tab" },
4082
+ { key: "1-9", desc: "Jump to repo tab by number" },
4083
+ { key: "s / S", desc: "Next / prev status tab" }
4073
4084
  ]
4074
4085
  },
4075
4086
  {
@@ -4094,7 +4105,7 @@ var init_help_overlay = __esm({
4094
4105
  { key: "c", desc: "Comment on issue" },
4095
4106
  { key: "m", desc: "Move status" },
4096
4107
  { key: "e", desc: "Edit issue in $EDITOR" },
4097
- { key: "s", desc: "Open Slack thread" },
4108
+ { key: "o", desc: "Open Slack thread" },
4098
4109
  { key: "y", desc: "Copy issue link to clipboard" },
4099
4110
  { key: "n", desc: "Create new issue" },
4100
4111
  { key: "I", desc: "Natural-language issue create" },
@@ -4904,13 +4915,36 @@ var init_row_renderer = __esm({
4904
4915
  }
4905
4916
  });
4906
4917
 
4907
- // src/board/components/tab-bar.tsx
4918
+ // src/board/components/status-tab-bar.tsx
4908
4919
  import { Box as Box19, Text as Text19 } from "ink";
4909
4920
  import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
4910
- function TabBar({ tabs, activeTabId, totalWidth }) {
4911
- return /* @__PURE__ */ jsx20(Box19, { width: totalWidth, children: tabs.map((tab, i) => {
4921
+ function StatusTabBar({ tabs, activeTabId, totalWidth }) {
4922
+ if (tabs.length === 0) return null;
4923
+ return /* @__PURE__ */ jsx20(Box19, { width: totalWidth, children: tabs.map((tab) => {
4912
4924
  const isActive = tab.id === activeTabId;
4913
4925
  return /* @__PURE__ */ jsx20(Box19, { marginRight: 2, children: /* @__PURE__ */ jsxs20(Text19, { bold: isActive, color: isActive ? "cyan" : "gray", children: [
4926
+ "[",
4927
+ isActive ? "\u25BA " : "",
4928
+ tab.label,
4929
+ " ",
4930
+ tab.count,
4931
+ "]"
4932
+ ] }) }, tab.id);
4933
+ }) });
4934
+ }
4935
+ var init_status_tab_bar = __esm({
4936
+ "src/board/components/status-tab-bar.tsx"() {
4937
+ "use strict";
4938
+ }
4939
+ });
4940
+
4941
+ // src/board/components/tab-bar.tsx
4942
+ import { Box as Box20, Text as Text20 } from "ink";
4943
+ import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
4944
+ function TabBar({ tabs, activeTabId, totalWidth }) {
4945
+ return /* @__PURE__ */ jsx21(Box20, { width: totalWidth, children: tabs.map((tab, i) => {
4946
+ const isActive = tab.id === activeTabId;
4947
+ return /* @__PURE__ */ jsx21(Box20, { marginRight: 2, children: /* @__PURE__ */ jsxs21(Text20, { bold: isActive, color: isActive ? "cyan" : "gray", children: [
4914
4948
  i + 1,
4915
4949
  ":",
4916
4950
  tab.label,
@@ -4928,21 +4962,21 @@ var init_tab_bar = __esm({
4928
4962
 
4929
4963
  // src/board/components/toast-container.tsx
4930
4964
  import { Spinner as Spinner3 } from "@inkjs/ui";
4931
- import { Box as Box20, Text as Text20 } from "ink";
4932
- import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
4965
+ import { Box as Box21, Text as Text21 } from "ink";
4966
+ import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
4933
4967
  function ToastContainer({ toasts }) {
4934
4968
  if (toasts.length === 0) return null;
4935
- return /* @__PURE__ */ jsx21(Box20, { flexDirection: "column", children: toasts.map((t) => /* @__PURE__ */ jsx21(Box20, { children: t.type === "loading" ? /* @__PURE__ */ jsxs21(Fragment4, { children: [
4936
- /* @__PURE__ */ jsx21(Spinner3, { label: "" }),
4937
- /* @__PURE__ */ jsxs21(Text20, { color: "cyan", children: [
4969
+ return /* @__PURE__ */ jsx22(Box21, { flexDirection: "column", children: toasts.map((t) => /* @__PURE__ */ jsx22(Box21, { children: t.type === "loading" ? /* @__PURE__ */ jsxs22(Fragment4, { children: [
4970
+ /* @__PURE__ */ jsx22(Spinner3, { label: "" }),
4971
+ /* @__PURE__ */ jsxs22(Text21, { color: "cyan", children: [
4938
4972
  " ",
4939
4973
  t.message
4940
4974
  ] })
4941
- ] }) : /* @__PURE__ */ jsxs21(Text20, { color: TYPE_COLORS[t.type], children: [
4975
+ ] }) : /* @__PURE__ */ jsxs22(Text21, { color: TYPE_COLORS[t.type], children: [
4942
4976
  TYPE_PREFIXES[t.type],
4943
4977
  " ",
4944
4978
  t.message,
4945
- t.type === "error" ? /* @__PURE__ */ jsx21(Text20, { color: "gray", children: t.retry ? " [r]etry [d]ismiss" : " [d]ismiss" }) : null
4979
+ t.type === "error" ? /* @__PURE__ */ jsx22(Text21, { color: "gray", children: t.retry ? " [r]etry [d]ismiss" : " [d]ismiss" }) : null
4946
4980
  ] }) }, t.id)) });
4947
4981
  }
4948
4982
  var TYPE_COLORS, TYPE_PREFIXES;
@@ -4966,9 +5000,9 @@ var init_toast_container = __esm({
4966
5000
  // src/board/components/dashboard.tsx
4967
5001
  import { execFileSync as execFileSync3, spawnSync as spawnSync4 } from "child_process";
4968
5002
  import { Spinner as Spinner4 } from "@inkjs/ui";
4969
- import { Box as Box21, Text as Text21, useApp, useStdout } from "ink";
5003
+ import { Box as Box22, Text as Text22, useApp, useStdout } from "ink";
4970
5004
  import { useCallback as useCallback11, useEffect as useEffect9, useMemo as useMemo3, useRef as useRef13, useState as useState15 } from "react";
4971
- import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
5005
+ import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs23 } from "react/jsx-runtime";
4972
5006
  function resolveStatusGroups(statusOptions, configuredGroups) {
4973
5007
  if (configuredGroups && configuredGroups.length > 0) {
4974
5008
  return configuredGroups.map((entry) => {
@@ -5049,7 +5083,16 @@ function buildTabs(tree) {
5049
5083
  tabs.push({ id: "ticktick", label: "Tasks", count: tree.tasks.length });
5050
5084
  return tabs;
5051
5085
  }
5052
- function buildNavItemsForTab(tabId, tree) {
5086
+ function isRepoTab(tabId) {
5087
+ return tabId !== null && tabId !== "activity" && tabId !== "ticktick";
5088
+ }
5089
+ function buildStatusTabs(tabId, tree) {
5090
+ if (!isRepoTab(tabId)) return [];
5091
+ const section = tree.sections.find((s) => s.sectionId === tabId);
5092
+ if (!section) return [];
5093
+ return section.groups.map((g) => ({ id: g.subId, label: g.label, count: g.issues.length }));
5094
+ }
5095
+ function buildNavItemsForTab(tabId, tree, activeStatusId) {
5053
5096
  if (tabId === "activity") return [];
5054
5097
  if (tabId === "ticktick")
5055
5098
  return tree.tasks.map((task2) => ({
@@ -5059,15 +5102,15 @@ function buildNavItemsForTab(tabId, tree) {
5059
5102
  }));
5060
5103
  const section = tree.sections.find((s) => s.sectionId === tabId);
5061
5104
  if (!section) return [];
5062
- return section.groups.flatMap(
5063
- (group) => group.issues.map((issue) => ({
5064
- id: `gh:${section.repo.name}:${issue.number}`,
5065
- section: tabId,
5066
- type: "item"
5067
- }))
5068
- );
5105
+ const activeGroup = section.groups.find((g) => g.subId === activeStatusId) ?? section.groups[0];
5106
+ if (!activeGroup) return [];
5107
+ return activeGroup.issues.map((issue) => ({
5108
+ id: `gh:${section.repo.name}:${issue.number}`,
5109
+ section: tabId,
5110
+ type: "item"
5111
+ }));
5069
5112
  }
5070
- function buildFlatRowsForTab(tabId, tree) {
5113
+ function buildFlatRowsForTab(tabId, tree, activeStatusId) {
5071
5114
  if (tabId === "activity")
5072
5115
  return tree.activity.map((event, i) => ({
5073
5116
  type: "activity",
@@ -5090,30 +5133,15 @@ function buildFlatRowsForTab(tabId, tree) {
5090
5133
  return [
5091
5134
  { type: "subHeader", key: `empty:${tabId}`, navId: null, text: "No open issues" }
5092
5135
  ];
5093
- const rows = [];
5094
- let isFirst = true;
5095
- for (const group of section.groups) {
5096
- if (!isFirst)
5097
- rows.push({ type: "gap", key: `gap:${tabId}:${group.label}`, navId: null });
5098
- isFirst = false;
5099
- rows.push({
5100
- type: "subHeader",
5101
- key: group.subId,
5102
- navId: null,
5103
- text: group.label,
5104
- count: group.issues.length,
5105
- isCollapsed: false
5106
- });
5107
- for (const issue of group.issues)
5108
- rows.push({
5109
- type: "issue",
5110
- key: `gh:${section.repo.name}:${issue.number}`,
5111
- navId: `gh:${section.repo.name}:${issue.number}`,
5112
- issue,
5113
- repoName: section.repo.name
5114
- });
5115
- }
5116
- return rows;
5136
+ const activeGroup = section.groups.find((g) => g.subId === activeStatusId) ?? section.groups[0];
5137
+ if (!activeGroup) return [];
5138
+ return activeGroup.issues.map((issue) => ({
5139
+ type: "issue",
5140
+ key: `gh:${section.repo.name}:${issue.number}`,
5141
+ navId: `gh:${section.repo.name}:${issue.number}`,
5142
+ issue,
5143
+ repoName: section.repo.name
5144
+ }));
5117
5145
  }
5118
5146
  function openInBrowser(url) {
5119
5147
  if (!(url.startsWith("https://") || url.startsWith("http://"))) return;
@@ -5139,7 +5167,7 @@ function RefreshAge({ lastRefresh }) {
5139
5167
  return () => clearInterval(id);
5140
5168
  }, []);
5141
5169
  if (!lastRefresh) return null;
5142
- return /* @__PURE__ */ jsxs22(Text21, { color: refreshAgeColor(lastRefresh), children: [
5170
+ return /* @__PURE__ */ jsxs23(Text22, { color: refreshAgeColor(lastRefresh), children: [
5143
5171
  "Updated ",
5144
5172
  timeAgo(lastRefresh)
5145
5173
  ] });
@@ -5215,22 +5243,46 @@ function Dashboard({ config: config2, options, activeProfile }) {
5215
5243
  const nextTab = useCallback11(() => {
5216
5244
  if (tabs.length === 0) return;
5217
5245
  setActiveTabId(tabs[(Math.max(activeTabIdx, 0) + 1) % tabs.length]?.id ?? null);
5246
+ setActiveStatusId(null);
5218
5247
  }, [activeTabIdx, tabs]);
5219
5248
  const prevTab = useCallback11(() => {
5220
5249
  if (tabs.length === 0) return;
5221
5250
  setActiveTabId(tabs[(Math.max(activeTabIdx, 0) - 1 + tabs.length) % tabs.length]?.id ?? null);
5251
+ setActiveStatusId(null);
5222
5252
  }, [activeTabIdx, tabs]);
5223
5253
  const jumpToTab = useCallback11(
5224
5254
  (idx) => {
5225
5255
  const tab = tabs[idx];
5226
- if (tab) setActiveTabId(tab.id);
5256
+ if (tab) {
5257
+ setActiveTabId(tab.id);
5258
+ setActiveStatusId(null);
5259
+ }
5227
5260
  },
5228
5261
  [tabs]
5229
5262
  );
5230
- const navItems = useMemo3(
5231
- () => buildNavItemsForTab(effectiveTabId ?? "", boardTree),
5263
+ const [activeStatusId, setActiveStatusId] = useState15(null);
5264
+ const statusTabs = useMemo3(
5265
+ () => buildStatusTabs(effectiveTabId, boardTree),
5232
5266
  [effectiveTabId, boardTree]
5233
5267
  );
5268
+ const effectiveStatusId = activeStatusId ?? statusTabs[0]?.id ?? null;
5269
+ const activeStatusIdx = statusTabs.findIndex((t) => t.id === effectiveStatusId);
5270
+ const nextStatus = useCallback11(() => {
5271
+ if (statusTabs.length === 0) return;
5272
+ setActiveStatusId(
5273
+ statusTabs[(Math.max(activeStatusIdx, 0) + 1) % statusTabs.length]?.id ?? null
5274
+ );
5275
+ }, [activeStatusIdx, statusTabs]);
5276
+ const prevStatus = useCallback11(() => {
5277
+ if (statusTabs.length === 0) return;
5278
+ setActiveStatusId(
5279
+ statusTabs[(Math.max(activeStatusIdx, 0) - 1 + statusTabs.length) % statusTabs.length]?.id ?? null
5280
+ );
5281
+ }, [activeStatusIdx, statusTabs]);
5282
+ const navItems = useMemo3(
5283
+ () => buildNavItemsForTab(effectiveTabId ?? "", boardTree, effectiveStatusId),
5284
+ [effectiveTabId, boardTree, effectiveStatusId]
5285
+ );
5234
5286
  const nav = useNavigation(navItems);
5235
5287
  const getRepoForId = useCallback11((id) => {
5236
5288
  if (id.startsWith("gh:")) {
@@ -5377,13 +5429,14 @@ function Dashboard({ config: config2, options, activeProfile }) {
5377
5429
  const overlayBarRows = ui.state.mode === "search" || ui.state.mode === "overlay:comment" ? 1 : 0;
5378
5430
  const toastRows = toasts.length;
5379
5431
  const logPaneRows = logVisible ? 4 : 0;
5432
+ const chromeRows = isRepoTab(effectiveTabId) ? CHROME_ROWS_REPO : CHROME_ROWS_OTHER;
5380
5433
  const viewportHeight = Math.max(
5381
5434
  5,
5382
- termSize.rows - CHROME_ROWS - overlayBarRows - toastRows - logPaneRows
5435
+ termSize.rows - chromeRows - overlayBarRows - toastRows - logPaneRows
5383
5436
  );
5384
5437
  const flatRows = useMemo3(
5385
- () => buildFlatRowsForTab(effectiveTabId ?? "", boardTree),
5386
- [effectiveTabId, boardTree]
5438
+ () => buildFlatRowsForTab(effectiveTabId ?? "", boardTree, effectiveStatusId),
5439
+ [effectiveTabId, boardTree, effectiveStatusId]
5387
5440
  );
5388
5441
  const scrollRef = useRef13(0);
5389
5442
  const prevTabIdRef = useRef13(null);
@@ -5395,14 +5448,6 @@ function Dashboard({ config: config2, options, activeProfile }) {
5395
5448
  () => flatRows.findIndex((r) => r.navId === nav.selectedId),
5396
5449
  [flatRows, nav.selectedId]
5397
5450
  );
5398
- const stickyHeader = useMemo3(() => {
5399
- if (selectedRowIdx < 0) return null;
5400
- for (let i = selectedRowIdx; i >= 0; i--) {
5401
- const row = flatRows[i];
5402
- if (row?.type === "subHeader") return { text: row.text, count: row.count };
5403
- }
5404
- return null;
5405
- }, [flatRows, selectedRowIdx]);
5406
5451
  if (selectedRowIdx >= 0) {
5407
5452
  if (selectedRowIdx < scrollRef.current) {
5408
5453
  scrollRef.current = selectedRowIdx;
@@ -5559,13 +5604,23 @@ function Dashboard({ config: config2, options, activeProfile }) {
5559
5604
  nav.select(navId);
5560
5605
  if (navId.startsWith("gh:")) {
5561
5606
  const parts = navId.split(":");
5562
- if (parts.length >= 3 && parts[1]) setActiveTabId(parts[1]);
5607
+ const repoName = parts[1];
5608
+ if (parts.length >= 3 && repoName) {
5609
+ setActiveTabId(repoName);
5610
+ const section = boardTree.sections.find((s) => s.sectionId === repoName);
5611
+ const issueNum = parts[2] ? Number(parts[2]) : null;
5612
+ const targetGroup = section?.groups.find(
5613
+ (g) => g.issues.some((iss) => iss.number === issueNum)
5614
+ );
5615
+ setActiveStatusId(targetGroup?.subId ?? null);
5616
+ }
5563
5617
  } else if (navId.startsWith("tt:")) {
5564
5618
  setActiveTabId("ticktick");
5619
+ setActiveStatusId(null);
5565
5620
  }
5566
5621
  ui.exitToNormal();
5567
5622
  },
5568
- [nav, ui]
5623
+ [nav, ui, boardTree]
5569
5624
  );
5570
5625
  const onSearchEscape = useCallback11(() => {
5571
5626
  ui.exitOverlay();
@@ -5597,10 +5652,11 @@ function Dashboard({ config: config2, options, activeProfile }) {
5597
5652
  handleToggleLog: () => setLogVisible((v) => !v)
5598
5653
  },
5599
5654
  onSearchEscape,
5600
- tabNav: { next: nextTab, prev: prevTab, jumpTo: jumpToTab, count: tabs.length }
5655
+ tabNav: { next: nextTab, prev: prevTab, jumpTo: jumpToTab, count: tabs.length },
5656
+ statusNav: isRepoTab(effectiveTabId) ? { next: nextStatus, prev: prevStatus } : null
5601
5657
  });
5602
5658
  if (status === "loading" && !data) {
5603
- return /* @__PURE__ */ jsx22(Box21, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx22(Spinner4, { label: "Loading dashboard..." }) });
5659
+ return /* @__PURE__ */ jsx23(Box22, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx23(Spinner4, { label: "Loading dashboard..." }) });
5604
5660
  }
5605
5661
  const now = data?.fetchedAt ?? /* @__PURE__ */ new Date();
5606
5662
  const dateStr = now.toLocaleDateString("en-US", {
@@ -5608,36 +5664,36 @@ function Dashboard({ config: config2, options, activeProfile }) {
5608
5664
  day: "numeric",
5609
5665
  year: "numeric"
5610
5666
  });
5611
- return /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", paddingX: 1, children: [
5612
- /* @__PURE__ */ jsxs22(Box21, { children: [
5613
- /* @__PURE__ */ jsx22(Text21, { color: "cyan", bold: true, children: "HOG BOARD" }),
5614
- activeProfile ? /* @__PURE__ */ jsxs22(Text21, { color: "yellow", children: [
5667
+ return /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", paddingX: 1, children: [
5668
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5669
+ /* @__PURE__ */ jsx23(Text22, { color: "cyan", bold: true, children: "HOG BOARD" }),
5670
+ activeProfile ? /* @__PURE__ */ jsxs23(Text22, { color: "yellow", children: [
5615
5671
  " [",
5616
5672
  activeProfile,
5617
5673
  "]"
5618
5674
  ] }) : null,
5619
- /* @__PURE__ */ jsxs22(Text21, { color: "gray", children: [
5675
+ /* @__PURE__ */ jsxs23(Text22, { color: "gray", children: [
5620
5676
  " ",
5621
5677
  "\u2014",
5622
5678
  " ",
5623
5679
  dateStr
5624
5680
  ] }),
5625
- /* @__PURE__ */ jsx22(Text21, { children: " " }),
5626
- isRefreshing ? /* @__PURE__ */ jsxs22(Fragment5, { children: [
5627
- /* @__PURE__ */ jsx22(Spinner4, { label: "" }),
5628
- /* @__PURE__ */ jsx22(Text21, { color: "cyan", children: " Refreshing..." })
5629
- ] }) : /* @__PURE__ */ jsxs22(Fragment5, { children: [
5630
- /* @__PURE__ */ jsx22(RefreshAge, { lastRefresh }),
5631
- consecutiveFailures > 0 ? /* @__PURE__ */ jsx22(Text21, { color: "red", children: " (!)" }) : null
5681
+ /* @__PURE__ */ jsx23(Text22, { children: " " }),
5682
+ isRefreshing ? /* @__PURE__ */ jsxs23(Fragment5, { children: [
5683
+ /* @__PURE__ */ jsx23(Spinner4, { label: "" }),
5684
+ /* @__PURE__ */ jsx23(Text22, { color: "cyan", children: " Refreshing..." })
5685
+ ] }) : /* @__PURE__ */ jsxs23(Fragment5, { children: [
5686
+ /* @__PURE__ */ jsx23(RefreshAge, { lastRefresh }),
5687
+ consecutiveFailures > 0 ? /* @__PURE__ */ jsx23(Text22, { color: "red", children: " (!)" }) : null
5632
5688
  ] }),
5633
- autoRefreshPaused ? /* @__PURE__ */ jsx22(Text21, { color: "yellow", children: " Auto-refresh paused \u2014 press r to retry" }) : null
5689
+ autoRefreshPaused ? /* @__PURE__ */ jsx23(Text22, { color: "yellow", children: " Auto-refresh paused \u2014 press r to retry" }) : null
5634
5690
  ] }),
5635
- error ? /* @__PURE__ */ jsxs22(Text21, { color: "red", children: [
5691
+ error ? /* @__PURE__ */ jsxs23(Text22, { color: "red", children: [
5636
5692
  "Error: ",
5637
5693
  error
5638
5694
  ] }) : null,
5639
- /* @__PURE__ */ jsx22(TabBar, { tabs, activeTabId: effectiveTabId, totalWidth: termSize.cols }),
5640
- /* @__PURE__ */ jsx22(
5695
+ /* @__PURE__ */ jsx23(TabBar, { tabs, activeTabId: effectiveTabId, totalWidth: termSize.cols }),
5696
+ /* @__PURE__ */ jsx23(
5641
5697
  OverlayRenderer,
5642
5698
  {
5643
5699
  uiState: ui.state,
@@ -5679,28 +5735,25 @@ function Dashboard({ config: config2, options, activeProfile }) {
5679
5735
  onPushEntry: pushEntry
5680
5736
  }
5681
5737
  ),
5682
- !ui.state.helpVisible && ui.state.mode !== "overlay:status" && ui.state.mode !== "overlay:create" && ui.state.mode !== "overlay:createNl" && ui.state.mode !== "overlay:bulkAction" && ui.state.mode !== "overlay:confirmPick" && ui.state.mode !== "focus" ? /* @__PURE__ */ jsxs22(Fragment5, { children: [
5683
- /* @__PURE__ */ jsx22(Box21, { children: stickyHeader ? /* @__PURE__ */ jsxs22(Fragment5, { children: [
5684
- /* @__PURE__ */ jsxs22(Text21, { bold: true, color: "white", children: [
5685
- " ",
5686
- stickyHeader.text
5687
- ] }),
5688
- stickyHeader.count != null ? /* @__PURE__ */ jsxs22(Text21, { color: "gray", children: [
5689
- " (",
5690
- stickyHeader.count,
5691
- ")"
5692
- ] }) : null
5693
- ] }) : null }),
5694
- /* @__PURE__ */ jsxs22(Box21, { height: viewportHeight, children: [
5695
- /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", flexGrow: 1, children: [
5696
- hasMoreAbove ? /* @__PURE__ */ jsxs22(Text21, { color: "gray", dimColor: true, children: [
5738
+ !ui.state.helpVisible && ui.state.mode !== "overlay:status" && ui.state.mode !== "overlay:create" && ui.state.mode !== "overlay:createNl" && ui.state.mode !== "overlay:bulkAction" && ui.state.mode !== "overlay:confirmPick" && ui.state.mode !== "focus" ? /* @__PURE__ */ jsxs23(Fragment5, { children: [
5739
+ isRepoTab(effectiveTabId) ? /* @__PURE__ */ jsx23(
5740
+ StatusTabBar,
5741
+ {
5742
+ tabs: statusTabs,
5743
+ activeTabId: effectiveStatusId,
5744
+ totalWidth: termSize.cols
5745
+ }
5746
+ ) : null,
5747
+ /* @__PURE__ */ jsxs23(Box22, { height: viewportHeight, children: [
5748
+ /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", flexGrow: 1, children: [
5749
+ hasMoreAbove ? /* @__PURE__ */ jsxs23(Text22, { color: "gray", dimColor: true, children: [
5697
5750
  " ",
5698
5751
  "\u25B2",
5699
5752
  " ",
5700
5753
  aboveCount,
5701
5754
  " more above"
5702
5755
  ] }) : null,
5703
- visibleRows.map((row) => /* @__PURE__ */ jsx22(
5756
+ visibleRows.map((row) => /* @__PURE__ */ jsx23(
5704
5757
  RowRenderer,
5705
5758
  {
5706
5759
  row,
@@ -5710,7 +5763,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
5710
5763
  },
5711
5764
  row.key
5712
5765
  )),
5713
- hasMoreBelow ? /* @__PURE__ */ jsxs22(Text21, { color: "gray", dimColor: true, children: [
5766
+ hasMoreBelow ? /* @__PURE__ */ jsxs23(Text22, { color: "gray", dimColor: true, children: [
5714
5767
  " ",
5715
5768
  "\u25BC",
5716
5769
  " ",
@@ -5718,7 +5771,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
5718
5771
  " more below"
5719
5772
  ] }) : null
5720
5773
  ] }),
5721
- showDetailPanel ? /* @__PURE__ */ jsx22(Box21, { marginLeft: 1, width: detailPanelWidth, children: /* @__PURE__ */ jsx22(
5774
+ showDetailPanel ? /* @__PURE__ */ jsx23(Box22, { marginLeft: 1, width: detailPanelWidth, children: /* @__PURE__ */ jsx23(
5722
5775
  DetailPanel,
5723
5776
  {
5724
5777
  issue: selectedItem.issue,
@@ -5731,9 +5784,9 @@ function Dashboard({ config: config2, options, activeProfile }) {
5731
5784
  ) }) : null
5732
5785
  ] })
5733
5786
  ] }) : null,
5734
- /* @__PURE__ */ jsx22(ToastContainer, { toasts }),
5735
- logVisible ? /* @__PURE__ */ jsx22(ActionLog, { entries: logEntries }) : null,
5736
- /* @__PURE__ */ jsx22(
5787
+ /* @__PURE__ */ jsx23(ToastContainer, { toasts }),
5788
+ logVisible ? /* @__PURE__ */ jsx23(ActionLog, { entries: logEntries }) : null,
5789
+ /* @__PURE__ */ jsx23(
5737
5790
  HintBar,
5738
5791
  {
5739
5792
  uiMode: ui.state.mode,
@@ -5745,7 +5798,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
5745
5798
  )
5746
5799
  ] });
5747
5800
  }
5748
- var PRIORITY_RANK, CHROME_ROWS;
5801
+ var PRIORITY_RANK, CHROME_ROWS_REPO, CHROME_ROWS_OTHER;
5749
5802
  var init_dashboard = __esm({
5750
5803
  "src/board/components/dashboard.tsx"() {
5751
5804
  "use strict";
@@ -5765,6 +5818,7 @@ var init_dashboard = __esm({
5765
5818
  init_hint_bar();
5766
5819
  init_overlay_renderer();
5767
5820
  init_row_renderer();
5821
+ init_status_tab_bar();
5768
5822
  init_tab_bar();
5769
5823
  init_toast_container();
5770
5824
  PRIORITY_RANK = {
@@ -5773,7 +5827,8 @@ var init_dashboard = __esm({
5773
5827
  "priority:medium": 2,
5774
5828
  "priority:low": 3
5775
5829
  };
5776
- CHROME_ROWS = 6;
5830
+ CHROME_ROWS_REPO = 6;
5831
+ CHROME_ROWS_OTHER = 5;
5777
5832
  }
5778
5833
  });
5779
5834
 
@@ -5783,10 +5838,10 @@ __export(live_exports, {
5783
5838
  runLiveDashboard: () => runLiveDashboard
5784
5839
  });
5785
5840
  import { render } from "ink";
5786
- import { jsx as jsx23 } from "react/jsx-runtime";
5841
+ import { jsx as jsx24 } from "react/jsx-runtime";
5787
5842
  async function runLiveDashboard(config2, options, activeProfile) {
5788
5843
  const instance = render(
5789
- /* @__PURE__ */ jsx23(Dashboard, { config: config2, options, activeProfile: activeProfile ?? null })
5844
+ /* @__PURE__ */ jsx24(Dashboard, { config: config2, options, activeProfile: activeProfile ?? null })
5790
5845
  );
5791
5846
  setInkInstance(instance);
5792
5847
  await instance.waitUntilExit();
@@ -6949,7 +7004,7 @@ function resolveProjectId(projectId) {
6949
7004
  process.exit(1);
6950
7005
  }
6951
7006
  var program = new Command();
6952
- program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.9.3").option("--json", "Force JSON output").option("--human", "Force human-readable output").hook("preAction", (thisCommand) => {
7007
+ program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.10.0").option("--json", "Force JSON output").option("--human", "Force human-readable output").hook("preAction", (thisCommand) => {
6953
7008
  const opts = thisCommand.opts();
6954
7009
  if (opts.json) setFormat("json");
6955
7010
  if (opts.human) setFormat("human");