@blocktion/json-to-table
Version:
A powerful, modular React component for converting JSON data to navigable tables with advanced features like automatic column detection, theming, and sub-table navigation. Part of the Blocktion SaaS project ecosystem.
88 lines (87 loc) • 3.99 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { NavigableCell } from "./NavigableCell";
import { useTheme } from "../../styles/theme-provider";
import { TableCell } from "../../styles/styled-components";
export const CellRenderer = ({ column, row, value, onNavigateToSubTable, onCellClick, onCellDoubleClick, enableNavigation, customRenderers = {}, rowIndex, }) => {
const { theme } = useTheme();
const handleCellClick = () => {
onCellClick?.(value, column, row);
};
const handleCellDoubleClick = () => {
onCellDoubleClick?.(value, column, row);
};
const handleNavigate = () => {
const valueIsArray = Array.isArray(value);
const valueIsObject = !!value && typeof value === "object" && !Array.isArray(value);
let isNavigable = valueIsArray || valueIsObject;
if (!isNavigable && column.columnType.isNavigable) {
isNavigable = valueIsArray || valueIsObject;
}
if (!enableNavigation || !isNavigable)
return;
let title;
if (valueIsArray || column.columnType.isArray) {
title = `${column.displayName} (Array)`;
}
else if (valueIsObject || column.columnType.isObject) {
title = `${column.displayName} (Object)`;
}
else {
title = `${column.displayName} (Value)`;
}
onNavigateToSubTable(column.cleanKey, value, title, rowIndex);
};
const formatValue = (val) => {
if (val === null || val === undefined)
return "";
if (typeof val === "string") {
return val.length > 30 ? val.substring(0, 27) + "..." : val;
}
if (typeof val === "object" && val !== null) {
const jsonStr = JSON.stringify(val);
return jsonStr.length > 30 ? jsonStr.substring(0, 27) + "..." : jsonStr;
}
return String(val);
};
// Custom renderer from column definition
if (column.renderer) {
return (_jsx(TableCell, { onClick: handleCellClick, onDoubleClick: handleCellDoubleClick, children: column.renderer(value, row) }));
}
// Custom renderer from props
if (customRenderers[column.cleanKey]) {
return (_jsx(TableCell, { onClick: handleCellClick, onDoubleClick: handleCellDoubleClick, children: customRenderers[column.cleanKey](value, row) }));
}
// Navigable cell
const valueIsArray = Array.isArray(value);
const valueIsObject = !!value && typeof value === "object" && !Array.isArray(value);
let isNavigableNow = enableNavigation && (valueIsArray || valueIsObject);
if (!isNavigableNow && column.columnType.isNavigable) {
isNavigableNow = enableNavigation && (valueIsArray || valueIsObject);
}
if (isNavigableNow && value) {
let displayText;
let type;
if (valueIsArray || column.columnType.isArray) {
displayText = `${value.length} items`;
type = "array";
}
else if (valueIsObject || column.columnType.isObject) {
// Show object key count for better context
const obj = value;
const keyCount = Object.keys(obj).length;
displayText = keyCount === 1 ? "1 property" : `${keyCount} properties`;
type = "object";
}
else {
displayText = formatValue(value);
type = "object";
}
return (_jsx(TableCell, { onClick: handleCellClick, onDoubleClick: handleCellDoubleClick, children: _jsx(NavigableCell, { value: value, displayText: displayText, onNavigate: handleNavigate, type: type }) }));
}
// Regular cell
return (_jsx(TableCell, { onClick: handleCellClick, onDoubleClick: handleCellDoubleClick, children: _jsx("span", { style: {
color: value === null || value === undefined
? theme.colors.text.muted
: theme.colors.text.primary,
}, children: formatValue(value) }) }));
};