diff --git a/apps/playground/src/stories/hooks/useOverflow.stories.tsx b/apps/playground/src/stories/hooks/useOverflow.stories.tsx new file mode 100644 index 0000000..6f214a9 --- /dev/null +++ b/apps/playground/src/stories/hooks/useOverflow.stories.tsx @@ -0,0 +1,61 @@ +import React, { + forwardRef, + PropsWithChildren, + ReactNode, + Ref, + useRef, +} from "react"; +import { ComponentMeta } from "@storybook/react"; +import { useOverflow } from "@nanlabs/react-hooks"; + +interface BoxProps { + background?: string; + children?: ReactNode; +} + +const Box = forwardRef((props: BoxProps, ref: Ref) => { + const style = { + display: "flex", + justifyContent: "center", + alignItems: "center", + overflow: "scroll", + background: "#108ee9", + textDirection: "center", + }; + + return ( +
+ {props.children} +
+ ); +}); + +Box.displayName = "Box"; + +export const Example: React.FC = () => { + const ref = useRef(null); + const { overflowActive } = useOverflow({ + elementRef: ref, + }); + + return ( + +
+ {overflowActive ? "Element in Overflow" : "No overflow"} +
+
+ ); +}; + +export default { + title: "React Hooks/useOverflow", + component: Example, +} as ComponentMeta; diff --git a/packages/react-hooks/index.ts b/packages/react-hooks/index.ts index a91d97c..66a5698 100644 --- a/packages/react-hooks/index.ts +++ b/packages/react-hooks/index.ts @@ -14,4 +14,5 @@ export * from "./use-append-task"; export * from "./use-copy-to-clipboard"; export * from "./use-previous"; export * from "./use-hover"; +export * from "./use-overflow"; export * from "./use-scroll"; diff --git a/packages/react-hooks/use-overflow/index.ts b/packages/react-hooks/use-overflow/index.ts new file mode 100644 index 0000000..60762d6 --- /dev/null +++ b/packages/react-hooks/use-overflow/index.ts @@ -0,0 +1 @@ +export { default as useOverflow } from "./useOverflow"; diff --git a/packages/react-hooks/use-overflow/useOverflow.ts b/packages/react-hooks/use-overflow/useOverflow.ts new file mode 100644 index 0000000..720f133 --- /dev/null +++ b/packages/react-hooks/use-overflow/useOverflow.ts @@ -0,0 +1,40 @@ +import { useCallback, useEffect, useState } from "react"; + +export type UseOverflowParams = { + elementRef: React.RefObject; +}; + +const checkOverflow = (element: HTMLElement) => { + if (element) + return ( + element.offsetHeight < element.scrollHeight || + element.offsetWidth < element.scrollWidth + ); + return false; +}; + +const useOverflow = ({ elementRef }: UseOverflowParams) => { + const [overflowActive, setOverflowActive] = useState(false); + + const onResize = useCallback(() => { + if (!elementRef.current) return; + if (checkOverflow(elementRef.current)) { + setOverflowActive(true); + return; + } + setOverflowActive(false); + }, [elementRef]); + + useEffect(() => { + onResize(); + window.addEventListener("resize", onResize); + + return () => window.removeEventListener("resize", onResize); + }, [onResize]); + + return { + overflowActive, + }; +}; + +export default useOverflow;