import { capitalizeFirstLetter } from '~/lib/util' import classNames from '~/lib/classNames' import LoadingSpinner from '~/components/LoadingSpinner' import React, { RefObject, useState } from 'react' export type StyledTableProps = { loading?: boolean tableProps?: React.HTMLAttributes tableRowStyle?: React.CSSProperties tableBodyClassName?: string tableBodyStyle?: React.CSSProperties data?: T[] noDataText?: string onRowClick?: (record: T) => void columns?: { accessor: keyof T title?: React.ReactNode render?: (record: T, index: number) => React.ReactNode className?: string }[] className?: string rowLines?: boolean ref?: RefObject containerProps?: React.HTMLAttributes compact?: boolean expandable?: { expandedRowRender: (record: T, index: number) => React.ReactNode defaultExpandedRowKeys?: (string | number)[] onExpandedRowsChange?: (expandedKeys: (string | number)[]) => void expandIconColumnIndex?: number } } function StyledTable({ loading = false, tableProps = {}, tableRowStyle = {}, tableBodyClassName = '', tableBodyStyle = {}, data = [], noDataText = 'No records found', onRowClick, columns = [], className = '', ref, containerProps = {}, rowLines = true, compact = false, expandable, }: StyledTableProps) { const { className: tableClassName, ...restTableProps } = tableProps const [expandedRowKeys, setExpandedRowKeys] = useState<(string | number)[]>( expandable?.defaultExpandedRowKeys || [] ) const leftPadding = compact ? 'pl-2' : 'pl-4 sm:pl-6' const isRowExpanded = (record: T, index: number) => { const key = record.id ?? index return expandedRowKeys.includes(key) } const toggleRowExpansion = (record: T, index: number, event: React.MouseEvent) => { event.stopPropagation() const key = record.id ?? index const newExpandedKeys = expandedRowKeys.includes(key) ? expandedRowKeys.filter((k) => k !== key) : [...expandedRowKeys, key] setExpandedRowKeys(newExpandedKeys) expandable?.onExpandedRowsChange?.(newExpandedKeys) } return (
{expandable && ( ))} {!loading && data.length !== 0 && data.map((record, recordIdx) => { const isExpanded = expandable && isRowExpanded(record, recordIdx) return ( onRowClick?.(record)} style={{ ...tableRowStyle, height: 'height' in record ? record.height : 'auto', transform: 'translateY' in record ? 'translateY(' + record.transformY + 'px)' : undefined, }} className={classNames( rowLines ? 'border-b border-border-subtle' : '', onRowClick ? `cursor-pointer hover:bg-surface-secondary ` : '' )} > {expandable && ( )} {columns.map((column, index) => ( ))} {expandable && isExpanded && ( )} ) })} {!loading && data.length === 0 && ( )} {loading && ( )}
)} {columns.map((column, index) => ( {column.title ?? capitalizeFirstLetter(column.accessor.toString())}
toggleRowExpansion(record, recordIdx, e)} > {column.render ? column.render(record, index) : (record[column.accessor] as React.ReactNode)}
{expandable.expandedRowRender(record, recordIdx)}
{noDataText}
) } export default StyledTable