@nadle/ink-table
Version:
A table component for Ink.
105 lines • 3.92 kB
JavaScript
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
import { Box, Text } from "ink";
import { sha1 } from "object-hash";
/* Components */
export function Table({ data, columns, padding = 1, cell = Cell, header = Header, skeleton = Skeleton }) {
const allColumns = columns || Array.from(new Set(data.flatMap((row) => Object.keys(row))));
const columnMeta = allColumns.map((key) => {
const maxContentWidth = Math.max(String(key).length, ...data.map((row) => String(row[key] ?? "").length));
return {
column: key,
key: String(key),
width: maxContentWidth + padding * 2
};
});
const headings = Object.fromEntries(allColumns.map((col) => [col, col]));
const RowHeader = row({
padding,
cell: skeleton,
skeleton: {
line: "─",
left: "┌",
right: "┐",
cross: "┬",
component: skeleton
}
});
const RowHeading = row({
padding,
cell: header,
skeleton: {
line: " ",
left: "│",
right: "│",
cross: "│",
component: skeleton
}
});
const RowSeparator = row({
padding,
cell: skeleton,
skeleton: {
line: "─",
left: "├",
right: "┤",
cross: "┼",
component: skeleton
}
});
const RowData = row({
cell,
padding,
skeleton: {
line: " ",
left: "│",
right: "│",
cross: "│",
component: skeleton
}
});
const RowFooter = row({
padding,
cell: skeleton,
skeleton: {
line: "─",
left: "└",
right: "┘",
cross: "┴",
component: skeleton
}
});
return (_jsxs(Box, { flexDirection: "column", children: [RowHeader({ data: {}, key: "header", columns: columnMeta }), RowHeading({ data: headings, key: "heading", columns: columnMeta }), data.map((row, index) => {
const key = `row-${sha1(row)}-${index}`;
return (_jsxs(Box, { flexDirection: "column", children: [RowSeparator({ data: {}, key: `sep-${key}`, columns: columnMeta }), RowData({ data: row, key: `data-${key}`, columns: columnMeta })] }, key));
}), RowFooter({ data: {}, key: "footer", columns: columnMeta })] }));
}
/* Helper components */
export function Header(props) {
return (_jsx(Text, { bold: true, color: "blue", children: props.children }));
}
export function Cell(props) {
return _jsx(Text, { children: props.children });
}
export function Skeleton(props) {
return _jsx(Text, { bold: true, children: props.children });
}
function row(config) {
const skeleton = config.skeleton;
return ({ key, data, columns }) => (_jsxs(Box, { flexDirection: "row", children: [_jsx(skeleton.component, { children: skeleton.left }), ...intersperse((i) => _jsx(skeleton.component, { children: skeleton.cross }, `${key}-sep-${i}`), columns.map((column, i) => {
const value = data[column.column];
const content = value == null ? "" : String(value);
const leftPad = config.padding;
const rightPad = column.width - content.length - leftPad;
return (_jsx(config.cell, { column: i, children: `${skeleton.line.repeat(leftPad)}${content}${skeleton.line.repeat(rightPad)}` }, `${key}-col-${column.key}`));
})), _jsx(skeleton.component, { children: skeleton.right })] }, key));
}
/* Util */
function intersperse(intersperser, elements) {
return elements.reduce((acc, el, idx) => {
if (idx === 0) {
return [el];
}
return [...acc, intersperser(idx), el];
}, []);
}
//# sourceMappingURL=index.js.map