diff --git a/apps/playground/src/stories/hooks/useScroll.stories.tsx b/apps/playground/src/stories/hooks/useScroll.stories.tsx new file mode 100644 index 0000000..46fb16c --- /dev/null +++ b/apps/playground/src/stories/hooks/useScroll.stories.tsx @@ -0,0 +1,71 @@ +import React, { + forwardRef, + PropsWithChildren, + ReactNode, + Ref, + useRef, +} from "react"; +import { ComponentMeta } from "@storybook/react"; +import { useScroll } 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", + background: props.background, + minWidth: "200px", + minHeight: "250px", + }; + + return ( +
+ {props.children} +
+ ); +}); + +Box.displayName = "Box"; + +export const Example: React.FC = () => { + const ref = useRef(null); + const { scroll } = useScroll({ + elementRef: ref, + }); + + return ( +
+ +
+ Item 1 + Item 2 + Item 3 +
+ +
+ ); +}; + +export default { + title: "React Hooks/useScroll", + component: Example, +} as ComponentMeta; diff --git a/packages/react-hooks/index.ts b/packages/react-hooks/index.ts index 49f36c1..a91d97c 100644 --- a/packages/react-hooks/index.ts +++ b/packages/react-hooks/index.ts @@ -14,3 +14,4 @@ export * from "./use-append-task"; export * from "./use-copy-to-clipboard"; export * from "./use-previous"; export * from "./use-hover"; +export * from "./use-scroll"; diff --git a/packages/react-hooks/use-scroll/index.ts b/packages/react-hooks/use-scroll/index.ts new file mode 100644 index 0000000..6e49921 --- /dev/null +++ b/packages/react-hooks/use-scroll/index.ts @@ -0,0 +1 @@ +export { default as useScroll } from "./useScroll"; diff --git a/packages/react-hooks/use-scroll/useScroll.ts b/packages/react-hooks/use-scroll/useScroll.ts new file mode 100644 index 0000000..d13a0d3 --- /dev/null +++ b/packages/react-hooks/use-scroll/useScroll.ts @@ -0,0 +1,33 @@ +import { useCallback } from "react"; + +export type UseScrollParams = { + elementRef: React.RefObject; +}; + +export type ScrollDirections = "top" | "bot" | "left" | "right"; + +const useScroll = ({ elementRef }: UseScrollParams) => { + const scroll = useCallback( + (direction: ScrollDirections, spaceToScroll: number) => { + if (!elementRef.current) return; + + const topMovement = direction === "top" ? spaceToScroll : 0; + const botMovement = direction === "bot" ? -spaceToScroll : 0; + const leftMovement = direction === "left" ? -spaceToScroll : 0; + const rightMovement = direction === "right" ? spaceToScroll : 0; + + elementRef.current.scrollBy({ + top: topMovement || botMovement, + left: leftMovement || rightMovement, + behavior: "smooth", + }); + }, + [elementRef] + ); + + return { + scroll, + }; +}; + +export default useScroll;