import { isString, omit } from 'lodash'; import React, { ReactNode, useMemo } from 'react'; import { SilkeCheckbox } from '../silke-checkbox'; import { SilkeOverflowMenu } from '../silke-overflow-menu'; import styles from './silke-table.scss'; import { TableColumn, TableRowMenu } from './table-types'; type TableRowProps = { item: T; index: number; columns: TableColumn[]; selected?: boolean; multiselect?: boolean; search?: RegExp; menu?: TableRowMenu[]; onSelect?: (value: T, select: boolean) => void; onHover?: () => void; }; function hasSearchMatch(search: RegExp, values: ReactNode[]): boolean { for (const value of values) { if (isString(value) && search.test(value)) return true; } return false; } const stopPropagation = (e: React.MouseEvent) => e.stopPropagation(); export function TableRow({ item, index, columns, search, menu, multiselect, selected, onSelect, onHover, }: TableRowProps) { // Mapping and transforming the item into column values const values = useMemo(() => { return columns.map((column) => { const value = item[column.attr]; if (column.transform) return column.transform(value, item, index); return value as unknown as React.ReactElement; }); }, [item, columns]); // Checking if one of the values matches the search if (search && !hasSearchMatch(search, values)) return null; const filteredMenu = menu ? menu .filter((m) => m === 'divider' || !m.isVisible || m.isVisible(item)) .map((m) => (typeof m === 'object' ? omit(m, 'isVisible') : m)) : undefined; return ( onSelect(item, true) : undefined} onMouseEnter={onHover} > {multiselect && ( onSelect && onSelect(item, select)} /> )} {values.map((value, i) => ( {value} ))} {filteredMenu && ( {filteredMenu.length > 0 && ( m === 'divider' ? m : { ...m, onClick: () => m.onClick(item) }, )} /> )} )} ); }