import React, { forwardRef, TableHTMLAttributes, useMemo } from 'react' import PropTypes from 'prop-types' import classNames from 'classnames' import { CTableHead, CTableHeadProps } from './CTableHead' import { CTableHeaderCell } from './CTableHeaderCell' import { CTableBody } from './CTableBody' import { CTableDataCell } from './CTableDataCell' import { CTableRow } from './CTableRow' import { CTableFoot, CTableFootProps } from './CTableFoot' import { CTableCaption } from './CTableCaption' import { CTableResponsiveWrapper } from './CTableResponsiveWrapper' import { colorPropType } from '../../props' import type { Colors } from '../../types' import { getColumnLabel, getColumnNames } from './utils' import type { Column, FooterItem, Item } from './types' export interface CTableProps extends Omit, 'align'> { /** * Set the vertical aligment. */ align?: 'bottom' | 'middle' | 'top' | string /** * Sets the border color of the component to one of CoreUI’s themed colors. * * @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | string */ borderColor?: Colors /** * Add borders on all sides of the table and cells. */ bordered?: boolean /** * Remove borders on all sides of the table and cells. */ borderless?: boolean /** * Put the caption on the top if you set `caption="top"` of the table or set the text of the table caption. */ caption?: 'top' | string /** * Set the text of the table caption and the caption on the top of the table. * * @since 4.3.0 */ captionTop?: string /** * A string of all className you want applied to the component. */ className?: string /** * Prop for table columns configuration. If prop is not defined, table will display columns based on the first item keys, omitting keys that begins with underscore (e.g. '_props') * * In columns prop each array item represents one column. Item might be specified in two ways: * String: each item define column name equal to item value. * Object: item is object with following keys available as column configuration: * - key (required)(String) - define column name equal to item key. * - label (String) - define visible label of column. If not defined, label will be generated automatically based on column name, by converting kebab-case and snake_case to individual words and capitalization of each word. * - _props (Object) - adds classes to all cels in column, ex. `_props: { scope: 'col', className: 'custom-class' }`, * - _style (Object) - adds styles to the column header (useful for defining widths) * * @since 4.3.0 */ columns?: (string | Column)[] /** * Sets the color context of the component to one of CoreUI’s themed colors. * * @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | string */ color?: Colors /** * Array of objects or strings, where each element represents one cell in the table footer. * * Example items: * `['FooterCell', 'FooterCell', 'FooterCell']` * or * `[{ label: 'FooterCell', _props: { color: 'success' }, ...]` * * @since 4.3.0 */ footer?: (FooterItem | string)[] /** * Enable a hover state on table rows within a ``. */ hover?: boolean /** * Array of objects, where each object represents one item - row in table. Additionally, you can add style classes to each row by passing them by '_props' key and to single cell by '_cellProps'. * * Example item: * `{ name: 'John' , age: 12, _props: { color: 'success' }, _cellProps: { age: { className: 'fw-bold'}}}` * * @since 4.3.0 */ items?: Item[] /** * Make any table responsive across all viewports or pick a maximum breakpoint with which to have a responsive table up to. */ responsive?: boolean | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' /** * Make table more compact by cutting all cell `padding` in half. */ small?: boolean /** * Add zebra-striping to any table row within the ``. */ striped?: boolean /** * Add zebra-striping to any table column. * * @since 4.3.0 */ stripedColumns?: boolean /** * Properties that will be passed to the table footer component. * * @link https://coreui.io/react/docs/components/table/#ctablefoot * @since 4.3.0 */ tableFootProps?: CTableFootProps /** * Properties that will be passed to the table head component. * * @link https://coreui.io/react/docs/components/table/#ctablehead * @since 4.3.0 */ tableHeadProps?: CTableHeadProps } export const CTable = forwardRef( ( { children, align, borderColor, bordered, borderless, caption, captionTop, className, color, columns, footer, hover, items, responsive, small, striped, stripedColumns, tableFootProps, tableHeadProps, ...rest }, ref ) => { const columnNames = useMemo(() => getColumnNames(columns, items), [columns, items]) return ( {((caption && caption !== 'top') || captionTop) && ( {caption || captionTop} )} {columns && ( {columns.map((column: Column, index: number) => ( {getColumnLabel(column)} ))} )} {items && ( {items.map((item: Item, index: number) => ( {columnNames && columnNames.map((colName: string, index: number) => { // eslint-disable-next-line unicorn/no-negated-condition return item[colName] !== undefined ? ( {item[colName]} ) : null })} ))} )} {children} {footer && ( {footer.map((item: FooterItem | string, index: number) => ( {typeof item === 'object' ? item.label : item} ))} )}
) } ) CTable.propTypes = { align: PropTypes.oneOf(['bottom', 'middle', 'top']), borderColor: PropTypes.string, bordered: PropTypes.bool, borderless: PropTypes.bool, caption: PropTypes.oneOfType([PropTypes.string, PropTypes.oneOf(['top'])]), captionTop: PropTypes.string, children: PropTypes.node, className: PropTypes.string, color: colorPropType, columns: PropTypes.array, footer: PropTypes.array, hover: PropTypes.bool, items: PropTypes.array, responsive: PropTypes.oneOfType([ PropTypes.bool, PropTypes.oneOf<'sm' | 'md' | 'lg' | 'xl' | 'xxl'>(['sm', 'md', 'lg', 'xl', 'xxl']), ]), small: PropTypes.bool, striped: PropTypes.bool, stripedColumns: PropTypes.bool, tableFootProps: PropTypes.shape({ ...CTableFoot.propTypes }), tableHeadProps: PropTypes.shape({ ...CTableHead.propTypes }), } CTable.displayName = 'CTable'