import classNames from 'classnames'; import * as React from 'react'; import type { ITableLayoutProps } from './Table'; import type { ITableCellLayoutProps } from './TableCell'; import type { ITableRowLayoutProps } from './TableRow'; import './standardGridTableLayout.less'; export interface ITableColumnSize { size: number; unit: 'fr' | '%' | 'px' | 'em' | 'rem' | 'vh' | 'vw' | 'vmin' | 'vmax'; } export type ITableColumnSizes = Readonly>; // If the table rows are expandable, we'll need a column on the right // for the expand/collapse indicators const EXPAND_COLLAPSE_COLUMN_SIZE = '48px'; const GUTTER_SIZE_PX = 16; const INDENT_SIZE_PX = 20; const throwSizingError = (invalidSizing: any) => { throw new Error( `Invalid table sizing configuration. Expected either a sizing object with 'size' and 'unit' fields or an array of two sizing objects. Actual value was ${JSON.stringify(invalidSizing)}`, ); }; export const getGridColumnsStyle = (sizes: ITableColumnSizes, expandable: boolean, isMobile: boolean) => { if (isMobile) { return undefined; } const gridColumns = sizes.map((sizing) => { if (typeof sizing === 'number') { return `${sizing}fr`; } else if (Array.isArray(sizing) && sizing.length === 2) { const [min, max] = sizing; return `minmax(${min.size + min.unit}, ${max.size + max.unit})`; } else if (!Array.isArray(sizing) && sizing.size && sizing.unit) { return `${sizing.size}${sizing.unit}`; } else { return throwSizingError(sizing); } }); if (expandable) { gridColumns.push(EXPAND_COLLAPSE_COLUMN_SIZE); } return gridColumns.join(' '); }; const TableLayout = ({ columns, expandable, expandAll, isMobile, children, sizes, }: ITableLayoutProps & { sizes: ITableColumnSizes }) => { const gridTemplateColumns = getGridColumnsStyle(sizes, expandable, isMobile); return (
{!isMobile && (
{columns.map(({ name, sortDirection, onSort }) => (
{name} {sortDirection ? : null}
))} {expandable && (
)}
)} {children}
); }; const TableRowLayout = ({ tableExpandable, rowExpandable, expanded, setExpanded, isMobile, sizes, children, renderExpandedContent, }: ITableRowLayoutProps & { sizes: ITableColumnSizes }) => { const gridTemplateColumns = getGridColumnsStyle(sizes, tableExpandable, isMobile); return (
setExpanded(!expanded) : null} > {children} {tableExpandable && !isMobile && (
{rowExpandable && ( )}
)}
{rowExpandable && expanded &&
{renderExpandedContent()}
}
); }; const TableCellLayout = ({ children, indent, index, columns, isMobile }: ITableCellLayoutProps) => { const columnName = columns[index].name; const indentPx = !!indent && isMobile ? `${GUTTER_SIZE_PX + indent * INDENT_SIZE_PX}px` : undefined; return (
{isMobile &&
{columnName}
}
{children}
); }; export const standardGridTableLayout = (sizes: ITableColumnSizes) => ({ TableLayout: (props: ITableLayoutProps) => , TableRowLayout: (props: ITableRowLayoutProps) => , TableCellLayout: (props: ITableCellLayoutProps) => , });