Skip to content

Instantly share code, notes, and snippets.

@adam-zethraeus
Created December 2, 2020 22:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adam-zethraeus/1fafa2f4b8aead44eaffbc8c6634ce8e to your computer and use it in GitHub Desktop.
Save adam-zethraeus/1fafa2f4b8aead44eaffbc8c6634ce8e to your computer and use it in GitHub Desktop.
useViewportSpace.ts
import { useState, useEffect, MutableRefObject } from 'react';
type Location = { x: number; y: number };
type Size = { width: number; height: number };
type Space = { location: Location; size: Size };
// The viewport information for the passed Div.
const useViewportSpace = (
scrollArea: MutableRefObject<HTMLDivElement | undefined>,
): { content?: Space; viewport?: Space } => {
const [space, setSpace] = useState<{ content?: Space; viewport?: Space }>({
content: undefined,
viewport: undefined,
});
// Called only on the client, and only once due to empty dependency list.
useEffect((): (() => void) => {
const element = scrollArea.current;
let content: () => Space | undefined;
let viewport: () => Space | undefined;
if (!element) {
content = () => undefined;
viewport = () => undefined;
} else {
content = () => ({
// The location of the content is always at (0,0) relative to its viewport.
location: {
x: 0,
y: 0,
},
size: {
width: element.scrollWidth,
height: element.scrollHeight,
},
});
viewport = () => ({
location: {
x: element.scrollLeft,
y: element.scrollTop,
},
size: {
width: element.clientWidth,
height: element.clientHeight,
},
});
}
const updateViewport = () => {
setSpace({
content: content(),
viewport: viewport(),
});
};
// Set values for initial return.
updateViewport();
// Set up listeners for changes.
element.addEventListener('resize', updateViewport);
element.addEventListener('scroll', updateViewport);
return () => {
// Tear down listeners when we're disposed.
element.removeEventListener('resize', updateViewport);
element.removeEventListener('scroll', updateViewport);
};
}, [scrollArea.current]);
return space;
};
export default useViewportSpace;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment