Skip to content

Instantly share code, notes, and snippets.

@createdbymahmood
Created December 3, 2020 11:01
Show Gist options
  • Select an option

  • Save createdbymahmood/1231cc0d6752b5c80f2e1d3961290455 to your computer and use it in GitHub Desktop.

Select an option

Save createdbymahmood/1231cc0d6752b5c80f2e1d3961290455 to your computer and use it in GitHub Desktop.
import { useState, RefObject, useLayoutEffect } from "react";
import useWindowSize from "./useWindowSize";
export function useOverflow(
ref: RefObject<HTMLElement>
): {
refXOverflowing: boolean;
refYOverflowing: boolean;
refXScrollBegin: boolean;
refXScrollEnd: boolean;
refYScrollBegin: boolean;
refYScrollEnd: boolean;
} {
const [refXOverflowing, setRefXOverflowing] = useState(false);
const [refYOverflowing, setRefYOverflowing] = useState(false);
const [refXScrollBegin, setRefXScrollBegin] = useState(true);
const [refXScrollEnd, setRefXScrollEnd] = useState(false);
const [refYScrollBegin, setRefYScrollBegin] = useState(true);
const [refYScrollEnd, setRefYScrollEnd] = useState(false);
const size = useWindowSize();
useLayoutEffect((): any => {
if (!ref?.current) {
return;
}
const isXOverflowing =
ref.current.scrollWidth > ref.current.clientWidth;
const isYOverflowing =
ref.current.scrollHeight > ref.current.clientHeight;
if (refXOverflowing !== isXOverflowing) {
setRefXOverflowing(isXOverflowing);
}
if (refYOverflowing !== isYOverflowing) {
setRefYOverflowing(isYOverflowing);
}
const handleScroll = (): void => {
// Handle X Overflow
const offsetRight =
ref?.current?.scrollWidth! - ref?.current?.clientWidth!;
if (
ref?.current?.scrollLeft! >= offsetRight &&
refXScrollEnd === false
) {
setRefXScrollEnd(true);
} else {
setRefXScrollEnd(false);
}
if (ref?.current?.scrollLeft === 0) {
setRefXScrollBegin(true);
} else {
setRefXScrollBegin(false);
}
// Handle Y Overflow
const offsetBottom =
ref?.current?.scrollHeight! - ref?.current?.clientHeight!;
if (
ref?.current?.scrollTop! >= offsetBottom &&
refYScrollEnd === false
) {
setRefYScrollEnd(true);
} else {
setRefYScrollEnd(false);
}
if (ref?.current?.scrollTop === 0) {
setRefYScrollBegin(true);
} else {
setRefYScrollBegin(false);
}
};
ref.current.addEventListener("scroll", handleScroll);
return (): void =>
ref.current?.removeEventListener("scroll", handleScroll);
}, [ref, size.width]); // Empty array ensures that effect is only run on mount and unmount
return {
refXOverflowing,
refYOverflowing,
refXScrollBegin,
refXScrollEnd,
refYScrollBegin,
refYScrollEnd,
};
}
// Borrowed from https://usehooks.com ♥️
import { useState, useEffect, useLayoutEffect } from "react";
function useWindowSize(): {
height: number | undefined;
width: number | undefined;
} {
const isClient = typeof window === "object";
function getSize(): {
height: number | undefined;
width: number | undefined;
} {
return {
width: isClient ? window.innerWidth : undefined,
height: isClient ? window.innerHeight : undefined,
};
}
const [windowSize, setWindowSize] = useState(getSize);
useLayoutEffect((): any => {
if (!isClient) {
return false;
}
function handleResize(): void {
setWindowSize(getSize());
}
window.addEventListener("resize", handleResize);
return (): void => window.removeEventListener("resize", handleResize);
}, []); // Empty array ensures that effect is only run on mount and unmount
return windowSize;
}
export default useWindowSize;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment