import { Children, cloneElement, ReactNode, useEffect, useRef, useState } from 'react'; import classnames from 'classnames'; import { useTableContext } from './contexts/TableContext'; import styles from './Table.css'; type Props = { /** * Must be instances of Table.Cell, Table.HeaderCell, or Table.SortableHeaderCell components. See the [Subcomponent section](https://gestalt.pinterest.systems/web/table#Subcomponents) to learn more. */ children: ReactNode; /** * Sets the background color on hover over the row. See the [selected and hovered state variant](https://gestalt.pinterest.systems/web/table#Selected-and-hovered-state) to learn more. */ hoverStyle?: 'gray' | 'none'; /** * Indicates if Table.Row is currently selected or unselected. See the [selected and hovered state variant](https://gestalt.pinterest.systems/web/table#Selected-and-hovered-state) to learn more. */ selected?: 'selected' | 'unselected'; }; /** * Use [Table.Row](https://gestalt.pinterest.systems/web/table#Table.Row) to define a row in Table. */ export default function TableRow({ children, hoverStyle = 'none', selected }: Props) { const { stickyColumns } = useTableContext(); const rowRef = useRef(); const [columnWidths, setColumnWidths] = useState>([]); useEffect(() => { if (rowRef?.current && stickyColumns) { // @ts-expect-error - TS2488 - Type 'HTMLCollection' must have a '[Symbol.iterator]()' method that returns an iterator. const colWidths = [...rowRef.current.children].map((item) => item.clientWidth); setColumnWidths(colWidths); } }, [stickyColumns]); const renderCellWithIndex = (child: ReactNode, index: number) => { const shouldBeSticky = stickyColumns ? stickyColumns >= 0 && index < stickyColumns : false; const shouldHaveShadow = stickyColumns ? stickyColumns - 1 === index : false; const previousWidths = columnWidths.slice(0, index); const previousTotalWidth = previousWidths.length > 0 ? previousWidths.reduce((a, b) => a + b) : 0; // @ts-expect-error - TS2769 - No overload matches this call. return cloneElement(child, { shouldBeSticky, previousTotalWidth, shouldHaveShadow, }); }; const rowStyle = classnames({ [styles.hoverShadeGray]: hoverStyle === 'gray' && selected !== 'selected', [styles.selected]: selected === 'selected', [styles.unselected]: selected === 'unselected', }); return ( // @ts-expect-error - TS2322 - Type 'MutableRefObject' is not assignable to type 'LegacyRef | undefined'. {Number(stickyColumns) > 0 ? Children.map(children, renderCellWithIndex) : children} ); } TableRow.displayName = 'Table.Row';