UNPKG

@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.

106 lines (105 loc) 5.81 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { ObjectUtils } from "../../utils/objectUtils"; import { useTheme } from "../../styles/theme-provider"; import { TableBody as StyledTableBody, TableRow, TableCell as StyledTableCell, } from "../../styles/styled-components"; import { CellRenderer } from "../Cells/CellRenderer"; import { RowActions } from "../Editing/RowActions"; import { EditableCell } from "../Editing/EditableCell"; export const TableBody = ({ data, columns, onRowClick, onCellClick, onNavigateToSubTable, enableNavigation, showRowNumbers, customRenderers = {}, // Editing props editState, setEditState, onDeleteRow, onAddRow, onUpdateField, onDeleteField, onAddField, validateField, options, }) => { const { theme } = useTheme(); const isEditingEnabled = options?.enableEditing || false; const isRowDeletionEnabled = options?.enableRowDeletion || false; const isFieldEditingEnabled = options?.enableFieldEditing || false; const isInlineEditingEnabled = options?.enableInlineEditing || false; const handleRowSelect = (rowIndex, selected) => { if (!setEditState) return; setEditState((prev) => { const newSelectedRows = new Set(prev.selectedRows); if (selected) { newSelectedRows.add(rowIndex); } else { newSelectedRows.delete(rowIndex); } return { ...prev, selectedRows: newSelectedRows }; }); }; const handleStartEdit = (rowIndex, field) => { if (!setEditState) return; setEditState((prev) => ({ ...prev, isEditing: true, editingRow: rowIndex, editingField: field, })); }; // Removed handleRowDoubleClick - editing should only be triggered by cell double-click const handleSaveEdit = (rowIndex, field, value) => { if (!onUpdateField) return; onUpdateField(rowIndex, field, value); if (setEditState) { setEditState((prev) => ({ ...prev, isEditing: false, editingRow: null, editingField: null, })); } }; const handleCancelEdit = () => { if (!setEditState) return; setEditState((prev) => ({ ...prev, isEditing: false, editingRow: null, editingField: null, })); }; const handleDeleteRow = (rowIndex) => { if (!onDeleteRow) return; onDeleteRow(rowIndex); }; return (_jsx(StyledTableBody, { children: data.map((row, index) => { const isRowSelected = editState?.selectedRows.has(index) || false; const isRowEditing = editState?.isEditing && editState.editingRow === index; const isFieldEditing = isRowEditing && editState?.editingField; return (_jsxs(TableRow, { hoverable: !!onRowClick, onClick: () => onRowClick?.(row, index), className: isEditingEnabled ? "group" : "", style: { backgroundColor: isRowSelected ? "#e3f2fd" : undefined, }, children: [isEditingEnabled && (_jsx(StyledTableCell, { style: { width: "120px", minWidth: "120px", textAlign: "center", }, children: _jsx(RowActions, { rowIndex: index, row: row, isSelected: isRowSelected, onDelete: () => handleDeleteRow(index), onSelect: (selected) => handleRowSelect(index, selected), enableDeletion: isRowDeletionEnabled || false }) })), showRowNumbers && (_jsx(StyledTableCell, { style: { width: "50px", minWidth: "50px", maxWidth: "50px", textAlign: "center", color: theme.colors.text.muted, fontSize: theme.typography.fontSize.sm, fontWeight: theme.typography.fontWeight.medium, boxSizing: "border-box", }, children: index + 1 })), columns.map((column) => { const value = ObjectUtils.getNestedValue(row, column.cleanKey); const isFieldBeingEdited = isFieldEditing && editState?.editingField === column.cleanKey; const validationError = validateField ? validateField(column.cleanKey, value, row).error : null; // Show EditableCell only if a specific field is being edited if (isInlineEditingEnabled && isFieldBeingEdited) { return (_jsx(StyledTableCell, { children: _jsx(EditableCell, { value: value, column: column, rowIndex: index, isEditing: true, onStartEdit: () => handleStartEdit(index, column.cleanKey), onSaveEdit: (newValue) => handleSaveEdit(index, column.cleanKey, newValue), onCancelEdit: handleCancelEdit, validationError: validationError || undefined }) }, column.key)); } return (_jsx(CellRenderer, { column: column, row: row, value: value, onNavigateToSubTable: (path, value, title) => onNavigateToSubTable(path, value, title, index), onCellClick: onCellClick, onCellDoubleClick: (value, column, row) => { if (isInlineEditingEnabled) { handleStartEdit(index, column.cleanKey); } }, enableNavigation: enableNavigation, customRenderers: customRenderers, rowIndex: index }, column.key)); })] }, index)); }) })); };