import React, { useEffect, useRef } from "react"; import { CellWrapper } from "./CellWrapper"; import { stickyColumnContext } from "../context/StickyColumnContext"; import { viewportSizeContext } from "../context/ViewportContext"; type IProps = { x: number; y: number; hasError: boolean; children: React.ReactNode; numHeaders: number; isSelectable: boolean; isReadonly: boolean; borderRightColor?: string; }; /** * Sticky cells are stuck to the left edge of the table even when scrolling. * We need to manually track the widths of the sticky cells to make sure they * stack beside each other properly, since the cells can grow horizontally if * there aren't many columns. */ export const StickyCell = ({ x, y, hasError, numHeaders, children, isSelectable, isReadonly, borderRightColor, }: IProps) => { const resizeObserverRef = useRef(null); const stickyCellWidths = stickyColumnContext.useState(); const setStickyCellWidths = stickyColumnContext.useSetter(); const wrapperRef = useRef(null); const viewportSize = viewportSizeContext.useState(); useEffect(() => { if (!wrapperRef.current) { return; } if (y % viewportSize === 0) { const updateStickyWidths = () => setStickyCellWidths((widths) => { if (!wrapperRef.current) { return widths; } const newWidths = [...widths]; newWidths[x] = wrapperRef.current.offsetWidth; return newWidths; }); resizeObserverRef.current = new ResizeObserver(updateStickyWidths); resizeObserverRef.current.observe(wrapperRef.current); updateStickyWidths(); return () => resizeObserverRef.current?.disconnect(); } return; }, [y % viewportSize]); const yPosition = (y % viewportSize) + 1 + numHeaders; const left = stickyCellWidths.slice(0, x).reduce((acc, v) => acc + v, 0); return ( {children} ); };