UNPKG

eventx-design-system

Version:
193 lines (187 loc) 7.44 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useState } from 'react'; import styled, { css } from 'styled-components'; import { colors, typography, spacing, borderRadius, transitions, shadows } from '../tokens/design-tokens'; // Container da tabela const TableContainer = styled.div ` width: 100%; overflow-x: auto; border-radius: ${borderRadius.lg}; box-shadow: ${({ variant }) => variant === 'bordered' ? 'none' : shadows.sm}; border: ${({ variant }) => variant === 'bordered' ? `1px solid ${colors.neutral[200]}` : 'none'}; `; // Tabela const StyledTable = styled.table ` width: 100%; border-collapse: collapse; background-color: ${colors.neutral[50]}; ${({ size }) => { switch (size) { case 'sm': return css ` font-size: ${typography.fontSize.sm}; `; case 'lg': return css ` font-size: ${typography.fontSize.lg}; `; default: return css ` font-size: ${typography.fontSize.base}; `; } }} `; // Cabeçalho da tabela const TableHeader = styled.thead ` background-color: ${colors.neutral[100]}; border-bottom: ${({ variant }) => variant === 'bordered' ? `1px solid ${colors.neutral[200]}` : 'none'}; `; // Célula do cabeçalho const HeaderCell = styled.th ` padding: ${spacing[3]} ${spacing[4]}; text-align: ${({ align }) => align}; font-family: ${typography.fontFamily.primary}; font-weight: ${typography.fontWeight.semibold}; color: ${colors.neutral[700]}; border-bottom: 1px solid ${colors.neutral[200]}; cursor: ${({ sortable }) => sortable ? 'pointer' : 'default'}; user-select: none; transition: all ${transitions.duration[200]} ${transitions.easing.inOut}; width: ${({ width }) => width || 'auto'}; ${({ sortable }) => sortable && css ` &:hover { background-color: ${colors.neutral[200]}; } `} `; // Ícone de ordenação const SortIcon = styled.span ` margin-left: ${spacing[1]}; color: ${({ direction }) => direction ? colors.brand.primary[950] : colors.neutral[400]}; transition: all ${transitions.duration[200]} ${transitions.easing.inOut}; ${({ direction }) => { if (direction === 'asc') { return css ` transform: rotate(180deg); `; } return css ` transform: rotate(0deg); `; }} `; // Corpo da tabela const TableBody = styled.tbody ` ${({ variant, hoverable }) => { if (variant === 'striped') { return css ` tr:nth-child(even) { background-color: ${colors.neutral[50]}; } tr:nth-child(odd) { background-color: ${colors.neutral[100]}; } `; } return css ``; }} ${({ hoverable }) => hoverable && css ` tr:hover { background-color: ${colors.brand.primary[50]} !important; } `} `; // Linha da tabela const TableRow = styled.tr ` border-bottom: ${({ variant }) => variant === 'bordered' ? `1px solid ${colors.neutral[200]}` : 'none'}; transition: all ${transitions.duration[200]} ${transitions.easing.inOut}; ${({ selected }) => selected && css ` background-color: ${colors.brand.primary[50]} !important; `} `; // Célula da tabela const TableCell = styled.td ` padding: ${spacing[3]} ${spacing[4]}; text-align: ${({ align }) => align}; font-family: ${typography.fontFamily.secondary}; color: ${colors.neutral[800]}; border-bottom: 1px solid ${colors.neutral[100]}; `; // Checkbox de seleção const SelectionCheckbox = styled.input ` width: 16px; height: 16px; cursor: pointer; `; // Estado de carregamento const LoadingState = styled.div ` display: flex; align-items: center; justify-content: center; padding: ${spacing[12]}; color: ${colors.neutral[500]}; font-family: ${typography.fontFamily.primary}; `; // Estado vazio const EmptyState = styled.div ` display: flex; align-items: center; justify-content: center; padding: ${spacing[12]}; color: ${colors.neutral[500]}; font-family: ${typography.fontFamily.primary}; text-align: center; `; export function Table({ data, columns, sortable = false, selectable = false, onRowSelect, onSort, loading = false, emptyMessage = 'Nenhum dado encontrado', size = 'md', variant = 'default', hoverable = true, className, ...props }) { const [sortKey, setSortKey] = useState(null); const [sortDirection, setSortDirection] = useState('asc'); const [selectedRows, setSelectedRows] = useState(new Set()); const handleSort = (key) => { if (!sortable) return; const newDirection = sortKey === key && sortDirection === 'asc' ? 'desc' : 'asc'; setSortKey(key); setSortDirection(newDirection); onSort?.(key, newDirection); }; const handleRowSelect = (index, checked) => { const newSelectedRows = new Set(selectedRows); if (checked) { newSelectedRows.add(index); } else { newSelectedRows.delete(index); } setSelectedRows(newSelectedRows); onRowSelect?.(data.filter((_, i) => newSelectedRows.has(i))); }; const handleSelectAll = (checked) => { if (checked) { const allIndices = new Set(data.map((_, index) => index)); setSelectedRows(allIndices); onRowSelect?.(data); } else { setSelectedRows(new Set()); onRowSelect?.([]); } }; const renderCell = (column, row, index) => { if (column.render) { return column.render(row[column.key], row, index); } const value = row[column.key]; return value != null ? String(value) : ''; }; if (loading) { return (_jsx(TableContainer, { variant: variant, className: className, ...props, children: _jsx(LoadingState, { children: "Carregando..." }) })); } if (data.length === 0) { return (_jsx(TableContainer, { variant: variant, className: className, ...props, children: _jsx(EmptyState, { children: emptyMessage }) })); } return (_jsx(TableContainer, { variant: variant, className: className, ...props, children: _jsxs(StyledTable, { variant: variant, size: size, children: [_jsx(TableHeader, { variant: variant, children: _jsxs("tr", { children: [selectable && (_jsx(HeaderCell, { align: "center", sortable: false, children: _jsx(SelectionCheckbox, { type: "checkbox", checked: selectedRows.size === data.length, onChange: (e) => handleSelectAll(e.target.checked) }) })), columns.map((column) => (_jsxs(HeaderCell, { align: column.align || 'left', sortable: column.sortable || false, width: column.width, onClick: () => handleSort(column.key), children: [column.header, (column.sortable || sortable) && (_jsx(SortIcon, { direction: sortKey === column.key ? sortDirection : null, children: "\u25BC" }))] }, column.key)))] }) }), _jsx(TableBody, { variant: variant, hoverable: hoverable, children: data.map((row, index) => (_jsxs(TableRow, { variant: variant, selected: selectedRows.has(index), children: [selectable && (_jsx(TableCell, { align: "center", children: _jsx(SelectionCheckbox, { type: "checkbox", checked: selectedRows.has(index), onChange: (e) => handleRowSelect(index, e.target.checked) }) })), columns.map((column) => (_jsx(TableCell, { align: column.align || 'left', children: renderCell(column, row, index) }, column.key)))] }, index))) })] }) })); }