112 lines
3.5 KiB
TypeScript
112 lines
3.5 KiB
TypeScript
import React, { ReactNode, CSSProperties } from 'react';
|
|
import { Surface } from './Surface';
|
|
|
|
export interface TableProps {
|
|
children: ReactNode;
|
|
className?: string;
|
|
}
|
|
|
|
export const Table = ({ children, className }: TableProps) => {
|
|
return (
|
|
<Surface rounded="lg" shadow="sm" style={{ overflow: 'auto', border: '1px solid var(--ui-color-border-default)' }} className={className}>
|
|
<table className="w-full border-collapse text-left">
|
|
{children}
|
|
</table>
|
|
</Surface>
|
|
);
|
|
};
|
|
|
|
export interface TableHeaderProps {
|
|
children: ReactNode;
|
|
className?: string;
|
|
textAlign?: 'left' | 'center' | 'right';
|
|
w?: string;
|
|
}
|
|
|
|
export const TableHeader = ({ children, className, textAlign, w }: TableHeaderProps) => {
|
|
return (
|
|
<thead className={`bg-[var(--ui-color-bg-base)] border-b border-[var(--ui-color-border-default)] ${className || ''}`}>
|
|
<tr>
|
|
{React.Children.map(children, child => {
|
|
if (React.isValidElement(child)) {
|
|
return React.cloneElement(child as any, { textAlign: textAlign || (child.props as any).textAlign, w: w || (child.props as any).w });
|
|
}
|
|
return child;
|
|
})}
|
|
</tr>
|
|
</thead>
|
|
);
|
|
};
|
|
|
|
export const TableHead = TableHeader;
|
|
|
|
export const TableBody = ({ children, className }: { children: ReactNode, className?: string }) => {
|
|
return (
|
|
<tbody className={`divide-y divide-[var(--ui-color-border-muted)] ${className || ''}`}>
|
|
{children}
|
|
</tbody>
|
|
);
|
|
};
|
|
|
|
export const TableRow = ({ children, onClick, className, variant, clickable, bg, ...props }: { children: ReactNode, onClick?: () => void, className?: string, variant?: string, clickable?: boolean, bg?: string, [key: string]: any }) => {
|
|
const isClickable = clickable || !!onClick;
|
|
return (
|
|
<tr
|
|
className={`${isClickable ? 'cursor-pointer hover:bg-white/5 transition-colors' : ''} ${variant === 'highlight' ? 'bg-white/5' : ''} ${className || ''}`}
|
|
onClick={onClick}
|
|
style={bg ? { backgroundColor: bg.startsWith('bg-') ? undefined : bg } : undefined}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</tr>
|
|
);
|
|
};
|
|
|
|
export interface TableHeaderCellProps {
|
|
children: ReactNode;
|
|
textAlign?: 'left' | 'center' | 'right';
|
|
w?: string;
|
|
className?: string;
|
|
}
|
|
|
|
export const TableHeaderCell = ({ children, textAlign, w, className }: TableHeaderCellProps) => {
|
|
const alignClass = textAlign === 'center' ? 'text-center' : (textAlign === 'right' ? 'text-right' : 'text-left');
|
|
return (
|
|
<th
|
|
className={`px-4 py-3 text-xs font-bold uppercase tracking-wider text-[var(--ui-color-text-low)] ${alignClass} ${className || ''}`}
|
|
style={w ? { width: w } : undefined}
|
|
>
|
|
{children}
|
|
</th>
|
|
);
|
|
};
|
|
|
|
export interface TableCellProps {
|
|
children: ReactNode;
|
|
textAlign?: 'left' | 'center' | 'right';
|
|
className?: string;
|
|
py?: number;
|
|
colSpan?: number;
|
|
w?: string;
|
|
position?: string;
|
|
[key: string]: any;
|
|
}
|
|
|
|
export const TableCell = ({ children, textAlign, className, py, colSpan, w, position, ...props }: TableCellProps) => {
|
|
const alignClass = textAlign === 'center' ? 'text-center' : (textAlign === 'right' ? 'text-right' : 'text-left');
|
|
return (
|
|
<td
|
|
className={`px-4 py-3 text-sm text-[var(--ui-color-text-high)] ${alignClass} ${className || ''}`}
|
|
colSpan={colSpan}
|
|
style={{
|
|
...(py !== undefined ? { paddingTop: `${py * 0.25}rem`, paddingBottom: `${py * 0.25}rem` } : {}),
|
|
...(w ? { width: w } : {}),
|
|
...(position ? { position: position as any } : {}),
|
|
}}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</td>
|
|
);
|
|
};
|