eventx-design-system
Version:
Design System do EventX
195 lines (184 loc) • 7.92 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import styled from 'styled-components';
import { colors, typography, spacing, borderRadius, shadows } from '../../tokens/design-tokens';
const TableContainer = styled.div `
width: 100%;
overflow-x: auto;
border-radius: ${borderRadius.lg};
box-shadow: ${shadows.base};
background-color: ${colors.neutral[50]};
`;
const StyledTable = styled.table `
width: 100%;
border-collapse: separate;
border-spacing: 0;
font-family: ${typography.fontFamily.primary};
${({ variant }) => {
if (variant === 'bordered') {
return `
border: 1px solid ${colors.neutral[300]};
border-radius: ${borderRadius.lg};
`;
}
return '';
}}
`;
const TableHeader = styled.thead `
background-color: ${colors.neutral[100]};
`;
const TableHeaderCell = styled.th `
padding: ${spacing[4]};
text-align: ${({ align }) => align || 'left'};
font-family: ${typography.fontFamily.primary};
font-size: ${typography.fontSize.sm};
font-weight: ${typography.fontWeight.semibold};
color: ${colors.neutral[700]};
border-bottom: 1px solid ${colors.neutral[300]};
cursor: ${({ sortable }) => sortable ? 'pointer' : 'default'};
user-select: none;
position: relative;
width: ${({ width }) => width || 'auto'};
min-width: ${({ width }) => width || 'auto'};
${({ sortable }) => sortable && `
&:hover {
background-color: ${colors.neutral[200]};
}
`}
${({ sorted }) => sorted && `
color: ${colors.brand.primary[600]};
&::after {
content: '${sorted === 'asc' ? '↑' : '↓'}';
position: absolute;
right: ${spacing[2]};
color: ${colors.brand.primary[500]};
}
`}
&:first-child {
border-top-left-radius: ${borderRadius.lg};
}
&:last-child {
border-top-right-radius: ${borderRadius.lg};
}
`;
const TableBody = styled.tbody `
${({ variant }) => {
if (variant === 'striped') {
return `
tr:nth-child(even) {
background-color: ${colors.neutral[50]};
}
tr:nth-child(odd) {
background-color: ${colors.neutral[100]};
}
`;
}
return '';
}}
`;
const TableRow = styled.tr `
transition: all 0.2s ease-in-out;
border-bottom: 1px solid ${colors.neutral[200]};
${({ hoverable }) => hoverable && `
&:hover {
background-color: ${colors.brand.primary[50]} !important;
transform: translateY(-1px);
box-shadow: ${shadows.md};
}
`}
${({ selected }) => selected && `
background-color: ${colors.brand.primary[100]} !important;
border-left: 3px solid ${colors.brand.primary[500]};
`}
&:last-child {
border-bottom: none;
}
`;
const TableCell = styled.td `
padding: ${spacing[4]};
text-align: ${({ align }) => align || 'left'};
font-family: ${typography.fontFamily.primary};
font-size: ${typography.fontSize.sm};
color: ${colors.neutral[700]};
border-bottom: 1px solid ${colors.neutral[200]};
width: ${({ width }) => width || 'auto'};
min-width: ${({ width }) => width || 'auto'};
vertical-align: middle;
&:last-child {
border-right: none;
}
`;
const EmptyState = styled.div `
padding: ${spacing[12]};
text-align: center;
color: ${colors.neutral[500]};
font-family: ${typography.fontFamily.primary};
font-size: ${typography.fontSize.base};
`;
const LoadingState = styled.div `
padding: ${spacing[12]};
text-align: center;
color: ${colors.neutral[500]};
font-family: ${typography.fontFamily.primary};
font-size: ${typography.fontSize.base};
`;
const SortIcon = styled.span `
margin-left: ${spacing[1]};
color: ${colors.neutral[400]};
font-size: ${typography.fontSize.xs};
`;
export const Table = ({ columns, dataSource, loading = false, variant = 'default', hoverable = true, selectable = false, selectedRowKeys = [], onRowSelect, onRowClick, sortConfig, onSort, rowKey = 'id', emptyText = 'Nenhum dado encontrado', className, }) => {
const getRowKey = (record, index) => {
if (typeof rowKey === 'function') {
return rowKey(record);
}
return record[rowKey] || index.toString();
};
const handleSort = (column) => {
if (!column.sortable || !onSort)
return;
const currentDirection = sortConfig?.key === column.key ? sortConfig.direction : null;
const newDirection = currentDirection === 'asc' ? 'desc' : 'asc';
onSort(column.key, newDirection);
};
const handleRowClick = (record, index) => {
onRowClick?.(record, index);
};
const handleRowSelect = (record, checked) => {
if (!selectable || !onRowSelect)
return;
const key = getRowKey(record, 0);
const newSelectedKeys = checked
? [...selectedRowKeys, key]
: selectedRowKeys.filter(k => k !== key);
const newSelectedRows = dataSource.filter(item => newSelectedKeys.includes(getRowKey(item, 0)));
onRowSelect(newSelectedKeys, newSelectedRows);
};
const renderCell = (column, record, index) => {
if (column.render) {
return column.render(record[column.dataIndex], record, index);
}
const value = column.dataIndex ? record[column.dataIndex] : record[column.key];
return value;
};
if (loading) {
return (_jsx(TableContainer, { variant: variant, className: className, children: _jsx(LoadingState, { children: "Carregando..." }) }));
}
if (!dataSource || dataSource.length === 0) {
return (_jsx(TableContainer, { variant: variant, className: className, children: _jsx(EmptyState, { children: emptyText }) }));
}
return (_jsx(TableContainer, { variant: variant, className: className, children: _jsxs(StyledTable, { variant: variant, children: [_jsx(TableHeader, { children: _jsxs("tr", { children: [selectable && (_jsx(TableHeaderCell, { width: "40px", children: _jsx("input", { type: "checkbox", checked: selectedRowKeys.length === dataSource.length, onChange: (e) => {
if (e.target.checked) {
const allKeys = dataSource.map((record, index) => getRowKey(record, index));
onRowSelect?.(allKeys, dataSource);
}
else {
onRowSelect?.([], []);
}
} }) })), columns.map((column) => (_jsxs(TableHeaderCell, { sortable: column.sortable, sorted: sortConfig?.key === column.key ? sortConfig.direction : null, align: column.align, width: column.width, onClick: () => handleSort(column), children: [column.title, column.sortable && (_jsx(SortIcon, { direction: sortConfig?.key === column.key ? sortConfig.direction : null, children: sortConfig?.key === column.key
? (sortConfig.direction === 'asc' ? '↑' : '↓')
: '↕' }))] }, column.key)))] }) }), _jsx(TableBody, { variant: variant, children: dataSource.map((record, index) => {
const key = getRowKey(record, index);
const isSelected = selectedRowKeys.includes(key);
return (_jsxs(TableRow, { variant: variant, hoverable: hoverable, selected: isSelected, onClick: () => handleRowClick(record, index), children: [selectable && (_jsx(TableCell, { width: "40px", children: _jsx("input", { type: "checkbox", checked: isSelected, onChange: (e) => handleRowSelect(record, e.target.checked), onClick: (e) => e.stopPropagation() }) })), columns.map((column) => (_jsx(TableCell, { align: column.align, width: column.width, children: renderCell(column, record, index) }, column.key)))] }, key));
}) })] }) }));
};