React AutoScroll

Date: 2024-02-09

Component that prevents the parent from growing, applying scrollbars.

export interface IRect {
    width: number,
    height: number;
}

export function ParentSize(props: { children?: ReactNode; sizeChanged: (size: IRect) => any; minHeight?: number | string }) {
    const { sizeChanged, minHeight } = props;
    const ref = useRef<HTMLDivElement>(null);
    useEffect(() => {
        const element = ref.current;
        if (!element)
            return;
        const onSizeChanged = () => {
            if (element) {
                const rect = element.getBoundingClientRect();
                sizeChanged(rect);
            }
        };

        const observer = new (window as any).ResizeObserver(onSizeChanged);
        observer.observe(element);
        return () => observer.unobserve(element);
    }, [sizeChanged, ref]);

    const parentStyle: CSSProperties = {
        position: "relative",
        display: "block",
        overflow: "hidden",
        width: "100%",
        height: "100%",
        minHeight: minHeight
    };

    const childStyle: CSSProperties = {
        position: "absolute",
        overflow: "hidden",
        width: "100%",
        height: "100%"
    };

    return <div style={parentStyle} ref={ref}>
        <div style={childStyle} >
            {props.children}
        </div>
    </div>;
}


export function AutoScroll(props: { children: any; onSizeChange?: (size: IRect) => any }) {
    const { onSizeChange } = props;
    const [size, setSize] = useState<IRect>({ width: 0, height: 0 });

    function sizeChanged(s: IRect) {
        setSize(s);
        if (onSizeChange)
            onSizeChange(s);
    }

    return (<ParentSize sizeChanged={sizeChanged}>
        <div style={{ display: "grid", height: size.height, width: size.width, overflow: "auto" }}>
            {props.children}
        </div>
    </ParentSize>);
}

82580cookie-checkReact AutoScroll