From 42be1f3c42e55de0be9a4d548c57b1ebdd65314d Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Tue, 14 Jul 2026 16:14:45 +0000 Subject: [PATCH 1/3] fix(tsc): use local variable with type guards for tabs --- src/components/ui/tabs/Tabs.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/ui/tabs/Tabs.tsx b/src/components/ui/tabs/Tabs.tsx index 0581e623e..afb363f5e 100644 --- a/src/components/ui/tabs/Tabs.tsx +++ b/src/components/ui/tabs/Tabs.tsx @@ -40,21 +40,24 @@ export const Tabs: React.FC = ({ const currentIndex = tabs.findIndex((t) => t.key === effectiveActiveKey); if (key.leftArrow || input === "h") { for (let i = currentIndex - 1; i >= 0; i--) { - if (!tabs[i].disabled) { - onChange(tabs[i].key); + const tab = tabs[i]; + if (tab && !tab.disabled) { + onChange(tab.key); break; } } } else if (key.rightArrow || input === "l") { for (let i = currentIndex + 1; i < tabs.length; i++) { - if (!tabs[i].disabled) { - onChange(tabs[i].key); + const tab = tabs[i]; + if (tab && !tab.disabled) { + onChange(tab.key); break; } } } else if (input >= "1" && input <= "9") { const idx = parseInt(input, 10) - 1; - if (idx < tabs.length && !tabs[idx].disabled) onChange(tabs[idx].key); + const tab = tabs[idx]; + if (idx < tabs.length && tab && !tab.disabled) onChange(tab.key); } }, { isActive: focus }, From d4600265d56241cfeacca4a09a5b2a4c8059cd12 Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Tue, 14 Jul 2026 16:48:06 +0000 Subject: [PATCH 2/3] fix(tui): zip column width into column data structure to avoid undefined assertions --- src/components/ui/data-table/DataTable.tsx | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/components/ui/data-table/DataTable.tsx b/src/components/ui/data-table/DataTable.tsx index 812e3f53f..0d6a94521 100644 --- a/src/components/ui/data-table/DataTable.tsx +++ b/src/components/ui/data-table/DataTable.tsx @@ -154,14 +154,14 @@ export function DataTable>({ { isActive: focus }, ); - // Column widths - const colWidths = columns.map((col) => { - if (col.width) return col.width; + // default the width of each column + const columnsWithWidths = columns.map((col) => { + if (col.width !== undefined) return { ...col, width: col.width }; const maxData = pageData.reduce((max, row) => { const val = col.render ? col.render(row[col.key], row) : String(row[col.key] ?? ""); return Math.max(max, val.length); }, 0); - return Math.max(col.header.length + 2, maxData + 2, 6); + return { ...col, width: Math.max(col.header.length + 2, maxData + 2, 6) }; }); const pad = (s: string, w: number, align: "left" | "center" | "right" = "left") => { @@ -214,12 +214,12 @@ export function DataTable>({ {/* Header */} {selectable && {" "}} - {columns.map((col, i) => { + {columnsWithWidths.map((col) => { const sortArrow = sortColumn === col.key ? (sortDirection === "asc" ? " ▲" : " ▼") : ""; return ( - + - {pad(col.header + sortArrow, colWidths[i], col.align)} + {pad(col.header + sortArrow, col.width, col.align)} ); @@ -230,7 +230,9 @@ export function DataTable>({ {showDivider - ? "─".repeat(colWidths.reduce((a, b) => a + b, 0) + (selectable ? 2 : 0)) + ? "─".repeat( + columnsWithWidths.reduce((acc, col) => acc + col.width, 0) + (selectable ? 2 : 0), + ) : " "} @@ -250,17 +252,17 @@ export function DataTable>({ {isSelected ? "❯ " : " "} )} - {columns.map((col, ci) => { + {columnsWithWidths.map((col) => { const val = col.render ? col.render(row[col.key], row) : String(row[col.key] ?? ""); return ( - + - {pad(val, colWidths[ci], col.align)} + {pad(val, col.width, col.align)} ); From 2d2e914de635561bae413583a8aa5bcf25e92815 Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Tue, 14 Jul 2026 17:03:14 +0000 Subject: [PATCH 3/3] fix(tui): add safe assertions for typechecker --- src/components/ui/markdown/Markdown.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/ui/markdown/Markdown.tsx b/src/components/ui/markdown/Markdown.tsx index c131b8b21..773733ecf 100644 --- a/src/components/ui/markdown/Markdown.tsx +++ b/src/components/ui/markdown/Markdown.tsx @@ -144,15 +144,17 @@ export const Markdown: React.FC = ({ content, theme = darkTheme } let i = 0; while (i < lines.length) { - const line = lines[i]; + // Note: assertion is safe based on bound above. + const line = lines[i]!; // Fenced code block if (line.startsWith("```")) { const lang = line.slice(3).trim(); const codeLines: string[] = []; i++; - while (i < lines.length && !lines[i].startsWith("```")) { - codeLines.push(lines[i]); + // Note: assertions on lines[i] are safe based on first term in the while condition. + while (i < lines.length && !lines[i]!.startsWith("```")) { + codeLines.push(lines[i]!); i++; } elements.push( @@ -253,10 +255,11 @@ export const Markdown: React.FC = ({ content, theme = darkTheme } // Ordered list const olMatch = line.match(/^(\d+)\.\s(.*)/); if (olMatch) { + // note: if the regex matched, there must be number at olMatch[1], so assertion is safe. elements.push( - {` ${olMatch[1]}. `} - {renderInline(parseInline(olMatch[2]), theme)} + {` ${olMatch[1]!}. `} + {renderInline(parseInline(olMatch[2] ?? ""), theme)} , ); i++;