import { Children, cloneElement, Fragment, ReactNode, useEffect, useRef, useState } from 'react'; import classnames from 'classnames'; import Box from './Box'; import { useTableContext } from './contexts/TableContext'; import styles from './Table.css'; import getChildrenCount from './Table/getChildrenCount'; type Props = { /** * Must be instances of Table.Cell. See the [Subcomponent section](https://gestalt.pinterest.systems/web/table#Subcomponents) to learn more. */ children: ReactNode; /** * The contents within the drawer. See the [Table.RowDrawer implementation](https://gestalt.pinterest.systems/web/table#Table.RowDrawer-implementation) to learn more. */ drawerContents: 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'; /** * Unique id for Table.RowDrawer. */ id: string; /** * Indicates if Table.RowDrawer 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.RowDrawer](https://gestalt.pinterest.systems/web/table#Table.RowDrawer) to define a row drawer to display additional content. */ export default function TableRowDrawer({ children, drawerContents, hoverStyle = 'none', id, 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 renderCellWithAdjustedIndex = (child: ReactNode, index: number) => { // Account for initial expandable column const adjustedIndex = index + 1; const shouldBeSticky = stickyColumns ? stickyColumns >= 0 && adjustedIndex < stickyColumns : false; const shouldHaveShadow = stickyColumns ? stickyColumns - 1 === adjustedIndex : false; const previousWidths = columnWidths.slice(0, adjustedIndex); 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'. */} {/* This needs to be fixed for children wrapped in React.Fragment when sticky columns are present */} {Number(stickyColumns) > 0 ? Children.map(children, renderCellWithAdjustedIndex) : children} {drawerContents ? ( {drawerContents} ) : null} ); } TableRowDrawer.displayName = 'Table.RowDrawer';