import React from 'react' import styled from 'styled-components' import { shadow } from '@planview/pv-utilities' import { useGridContext, useGridSelector } from '../context/grid-context' const StickyLeft = styled.div<{ $showShadow: boolean }>` width: 36px; pointer-events: none; position: absolute; top: 0; overflow: hidden; z-index: 20; &::before { content: ''; width: 36px; position: absolute; top: 0; bottom: 0; left: -36px; ${shadow.small}; display: ${(props) => (props.$showShadow ? 'block' : 'none')}; } ` const StickyRight = styled.div<{ $showShadow: boolean }>` width: 36px; pointer-events: none; position: absolute; top: 0; overflow: hidden; z-index: 20; &::before { content: ''; width: 36px; position: absolute; top: 0; bottom: 0; left: 36px; ${shadow.small}; display: ${(props) => (props.$showShadow ? 'block' : 'none')}; } ` export type GridStickyOverlayProps = { totalWidth: number totalHeight: number scrollingRef: React.RefObject } type StickyOverlayState = { horizontal: number vertical: number } type StickyScrollState = { fullyLeft: boolean fullyRight: boolean } export const GridStickyOverlay = React.memo(function StickyOverlay({ totalWidth, totalHeight, scrollingRef, }: GridStickyOverlayProps) { const grid = useGridContext() const stickyColumnDetails = useGridSelector( grid.selectors.selectStickyColumnDetails ) const leftWidth = stickyColumnDetails.left.width const rightWidth = stickyColumnDetails.right.width const [scrollbarOffsets, setScrollbarOffsets] = React.useState({ horizontal: 0, vertical: 0 }) const [scrollState, setScrollState] = React.useState({ fullyLeft: true, fullyRight: true, }) const updateScrollbarOffsets = React.useCallback(() => { const scroller = scrollingRef.current if (scroller) { const horizontal = scroller.offsetHeight - scroller.clientHeight const vertical = scroller.offsetWidth - scroller.clientWidth setScrollbarOffsets({ horizontal, vertical }) grid.events.emit('onScrollbarVisibilityChange', { horizontalHeight: horizontal, verticalWidth: vertical, }) } }, [grid.events, scrollingRef]) React.useEffect(() => { const scroller = scrollingRef.current if (scroller) { updateScrollbarOffsets() const observer = new IntersectionObserver( (entries) => { let fullyLeft: boolean let fullyRight: boolean entries.forEach((entry) => { const position = (entry.target as HTMLDivElement) .dataset.pvdsGridSignal if (position === 'left') { fullyLeft = entry.isIntersecting } else if (position === 'right') { fullyRight = entry.isIntersecting } }) setScrollState((s) => ({ fullyLeft: fullyLeft ?? s.fullyLeft, fullyRight: fullyRight ?? s.fullyRight, })) }, { root: scroller } ) const signals = scroller.querySelectorAll( '[data-pvds-grid-signal]' ) signals.forEach((s) => observer.observe(s)) return () => { observer.disconnect() } } else { console.error("Couldn't wire up scroll handlers") } }, [scrollingRef, updateScrollbarOffsets]) React.useEffect(() => { updateScrollbarOffsets() }, [updateScrollbarOffsets, scrollState, totalWidth, totalHeight]) return ( <> {leftWidth > 0 && ( )} {rightWidth > 0 && ( )} ) })