@ackplus/react-tanstack-data-table
Version:
A powerful React data table component built with MUI and TanStack Table
120 lines (119 loc) • 7.42 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataTableRow = DataTableRow;
const jsx_runtime_1 = require("react/jsx-runtime");
/**
* DataTableRow Component
*
* Renders individual table rows with support for:
* - Column pinning
* - Row expansion
* - Hover effects
* - Striped styling
*/
const material_1 = require("@mui/material");
const react_table_1 = require("@tanstack/react-table");
const utils_1 = require("../../utils");
const slot_helpers_1 = require("../../utils/slot-helpers");
const data_table_context_1 = require("../../contexts/data-table-context");
/**
* Individual table row component with cell rendering and expansion support
*/
function DataTableRow(props) {
var _a;
const { row, enableHover = true, enableStripes = false, isOdd = false, renderSubComponent, disableStickyHeader = false, onRowClick, selectOnRowClick = false, cellProps, expandedRowProps, expandedCellProps, containerSx, expandedContainerSx, slots, slotProps, ...otherProps } = props;
const { table } = (0, data_table_context_1.useDataTableContext)();
// Extract slot-specific props with enhanced merging
const cellSlotProps = (0, slot_helpers_1.extractSlotProps)(slotProps, 'cell');
const expandedRowSlotProps = (0, slot_helpers_1.extractSlotProps)(slotProps, 'expandedRow');
const rowSlotProps = (0, slot_helpers_1.extractSlotProps)(slotProps, 'row');
const CellSlot = (0, slot_helpers_1.getSlotComponent)(slots, 'cell', material_1.TableCell);
const ExpandedRowSlot = (0, slot_helpers_1.getSlotComponent)(slots, 'expandedRow', material_1.TableRow);
const TableRowSlot = (0, slot_helpers_1.getSlotComponent)(slots, 'row', material_1.TableRow);
// Handle row click
const handleRowClick = (event) => {
// Check if click target is a checkbox, button, or interactive element
const target = event.target;
// Check for various interactive elements
const isCheckboxClick = target.closest('input[type="checkbox"]') !== null;
const isButtonClick = target.closest('button') !== null;
const isLinkClick = target.closest('a') !== null;
// Check for elements with interactive roles (button, checkbox, switch, etc.)
const isInteractiveRole = target.closest('[role="button"]') !== null ||
target.closest('[role="checkbox"]') !== null ||
target.closest('[role="switch"]') !== null ||
target.closest('[role="menuitem"]') !== null;
// Determine if this is an interactive element click
const isInteractiveClick = isCheckboxClick || isButtonClick || isLinkClick || isInteractiveRole;
// If selectOnRowClick is enabled and it's not an interactive element click, toggle selection
if (selectOnRowClick && !isInteractiveClick && (table === null || table === void 0 ? void 0 : table.toggleRowSelected)) {
table.toggleRowSelected(row.id);
}
// Only call onRowClick if it's not an interactive element click
if (onRowClick && !isInteractiveClick) {
onRowClick(event, row);
}
};
// Merge all props for maximum flexibility
const mergedRowProps = (0, slot_helpers_1.mergeSlotProps)({
hover: enableHover,
selected: !!((_a = table === null || table === void 0 ? void 0 : table.getIsRowSelected) === null || _a === void 0 ? void 0 : _a.call(table, row.id)),
onClick: (onRowClick || selectOnRowClick) ? handleRowClick : undefined,
sx: (theme) => ({
// set the row background as a variable
'--row-bg': enableStripes && isOdd
? theme.palette.action.hover
: theme.palette.background.paper,
backgroundColor: 'var(--row-bg)',
// keep the variable in sync for hover/selected
...(enableHover && {
'&:hover': { '--row-bg': theme.palette.action.hover },
}),
[`&.${material_1.tableRowClasses.selected}`]: {
'--row-bg': theme.palette.action.selected,
backgroundColor: 'var(--row-bg)',
},
// Add cursor pointer if row is clickable
...((onRowClick || selectOnRowClick) && {
cursor: 'pointer',
}),
...containerSx,
}),
}, rowSlotProps, otherProps);
const mergedExpandedRowProps = (0, slot_helpers_1.mergeSlotProps)({
sx: expandedContainerSx,
}, expandedRowSlotProps, expandedRowProps || {});
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(TableRowSlot, { ...mergedRowProps, children: row.getVisibleCells().map(cell => {
var _a, _b;
const isPinned = cell.column.getIsPinned();
const pinnedPosition = isPinned ? cell.column.getStart('left') : undefined;
const pinnedRightPosition = isPinned === 'right' ? cell.column.getAfter('right') : undefined;
const alignment = (0, utils_1.getColumnAlignment)(cell.column.columnDef);
// Get minSize and maxSize from column definition
const minSize = (_a = cell.column.columnDef) === null || _a === void 0 ? void 0 : _a.minSize;
const maxSize = cell.column.columnDef.maxSize;
const wrapText = (_b = cell.column.columnDef.wrapText) !== null && _b !== void 0 ? _b : false;
const mergedCellProps = (0, slot_helpers_1.mergeSlotProps)({
align: alignment,
sx: {
...(0, utils_1.getPinnedColumnStyle)({
width: cell.column.getSize() || 'auto',
minWidth: minSize !== undefined ? minSize : undefined,
maxWidth: maxSize !== undefined ? maxSize : undefined,
isPinned,
pinnedPosition,
pinnedRightPosition,
zIndex: isPinned ? 9 : 1,
disableStickyHeader,
isLastLeftPinnedColumn: isPinned === 'left' && cell.column.getIsLastColumn('left'),
isFirstRightPinnedColumn: isPinned === 'right' && cell.column.getIsFirstColumn('right'),
wrapText,
}),
},
}, cellSlotProps, cellProps || {});
return ((0, jsx_runtime_1.jsx)(CellSlot, { ...mergedCellProps, children: (0, react_table_1.flexRender)(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
}) }), row.getIsExpanded() && renderSubComponent ? ((0, jsx_runtime_1.jsx)(ExpandedRowSlot, { ...mergedExpandedRowProps, children: (0, jsx_runtime_1.jsx)(CellSlot, { colSpan: row.getVisibleCells().length, sx: {
py: 0,
...expandedCellProps === null || expandedCellProps === void 0 ? void 0 : expandedCellProps.sx,
}, ...(0, slot_helpers_1.mergeSlotProps)({}, cellSlotProps, expandedCellProps || {}), children: (0, jsx_runtime_1.jsx)(material_1.Collapse, { in: row.getIsExpanded(), timeout: "auto", unmountOnExit: true, children: renderSubComponent(row) }) }) })) : null] }));
}