Files
2026-07-13 13:39:12 +08:00

51 lines
1.4 KiB
React

import React, { useState } from "react";
import { Box, Text, useInput } from "ink";
import { theme } from "./theme.jsx";
function formatCell(v, col) {
if (v == null) return "-";
if (col.formatter) return col.formatter(v);
return String(v);
}
export function DataTable({ rows = [], schema = [], selectable = false, onSelect }) {
const [selectedIdx, setSelectedIdx] = useState(0);
useInput((input, key) => {
if (!selectable || rows.length === 0) return;
if (key.upArrow) setSelectedIdx((i) => Math.max(0, i - 1));
if (key.downArrow) setSelectedIdx((i) => Math.min(rows.length - 1, i + 1));
if (key.return && onSelect) onSelect(rows[selectedIdx]);
});
if (rows.length === 0) {
return <Text dimColor>No data.</Text>;
}
return (
<Box flexDirection="column">
<Box>
{schema.map((col) => (
<Box key={col.key} width={col.width ?? 16} marginRight={1}>
<Text bold color={theme.header}>
{col.header}
</Text>
</Box>
))}
</Box>
{rows.map((row, idx) => (
<Box
key={idx}
backgroundColor={selectable && idx === selectedIdx ? theme.selected : undefined}
>
{schema.map((col) => (
<Box key={col.key} width={col.width ?? 16} marginRight={1}>
<Text>{formatCell(row[col.key], col)}</Text>
</Box>
))}
</Box>
))}
</Box>
);
}