83 lines
3.1 KiB
JavaScript
83 lines
3.1 KiB
JavaScript
import { animated, useTransition } from '@react-spring/web';
|
|
import { useEffect, useState } from 'preact/hooks';
|
|
|
|
export default function AnimatedDataTable({
|
|
columns = [],
|
|
rows = [],
|
|
rowKey = (row) => row?.id,
|
|
renderRow,
|
|
loading = false,
|
|
loadingMessage = 'Učitavanje...',
|
|
emptyMessage = 'Nema podataka.',
|
|
tableClassName = 'min-w-full text-sm',
|
|
headClassName = 'bg-canvas-deep text-left text-xs uppercase tracking-wide text-text-muted',
|
|
bodyClassName = 'divide-y divide-border-hairline',
|
|
rowClassName = 'hover:bg-canvas-deep',
|
|
wrapperClassName = 'overflow-x-auto',
|
|
trail = 35,
|
|
}) {
|
|
const [mounted, setMounted] = useState(false);
|
|
useEffect(() => {
|
|
setMounted(true);
|
|
}, []);
|
|
|
|
const transitions = useTransition(rows, {
|
|
keys: (row) => rowKey(row),
|
|
from: { opacity: 0, transform: 'translate3d(0,8px,0)' },
|
|
enter: { opacity: 1, transform: 'translate3d(0,0,0)' },
|
|
leave: { opacity: 0, transform: 'translate3d(0,-8px,0)' },
|
|
trail,
|
|
config: { tension: 230, friction: 26 },
|
|
});
|
|
|
|
const colSpan = Math.max(1, columns.length);
|
|
|
|
return (
|
|
<div className={wrapperClassName}>
|
|
<table className={tableClassName}>
|
|
<thead className={headClassName}>
|
|
<tr>
|
|
{columns.map((column) => (
|
|
<th key={column.key} className={column.className}>
|
|
{column.label}
|
|
</th>
|
|
))}
|
|
</tr>
|
|
</thead>
|
|
<tbody className={bodyClassName}>
|
|
{!mounted && (
|
|
<tr>
|
|
<td colSpan={colSpan} className="px-4 py-6 text-center text-sm text-text-muted">
|
|
{loadingMessage}
|
|
</td>
|
|
</tr>
|
|
)}
|
|
{mounted && loading && (
|
|
<tr>
|
|
<td colSpan={colSpan} className="px-4 py-6 text-center text-sm text-text-muted">
|
|
{loadingMessage}
|
|
</td>
|
|
</tr>
|
|
)}
|
|
{mounted && !loading && rows.length === 0 && (
|
|
<tr>
|
|
<td colSpan={colSpan} className="px-4 py-6 text-center text-sm text-text-muted">
|
|
{emptyMessage}
|
|
</td>
|
|
</tr>
|
|
)}
|
|
{mounted && !loading && transitions((style, row) => (
|
|
<animated.tr
|
|
key={rowKey(row)}
|
|
style={style}
|
|
className={typeof rowClassName === 'function' ? rowClassName(row) : rowClassName}
|
|
>
|
|
{renderRow(row)}
|
|
</animated.tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
}
|