From f12523d3f0ab42864cee5f645e01f3118e1a610e Mon Sep 17 00:00:00 2001 From: n4ze3m Date: Thu, 30 May 2024 23:49:28 +0530 Subject: [PATCH] feat: Add useScrollAnchor hook for scrolling functionality --- src/hooks/useScrollAnchor.tsx | 87 +++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/hooks/useScrollAnchor.tsx diff --git a/src/hooks/useScrollAnchor.tsx b/src/hooks/useScrollAnchor.tsx new file mode 100644 index 0000000..a8ec2ad --- /dev/null +++ b/src/hooks/useScrollAnchor.tsx @@ -0,0 +1,87 @@ +import { useCallback, useEffect, useRef, useState } from "react" + +export const useScrollAnchor = () => { + const messagesRef = useRef(null) + const scrollRef = useRef(null) + const visibilityRef = useRef(null) + + const [isAtBottom, setIsAtBottom] = useState(true) + const [isVisible, setIsVisible] = useState(false) + + const scrollToBottom = useCallback(() => { + if (messagesRef.current) { + messagesRef.current.scrollIntoView({ + block: "end", + behavior: "smooth" + }) + } + }, []) + + useEffect(() => { + if (messagesRef.current) { + if (isAtBottom && !isVisible) { + messagesRef.current.scrollIntoView({ + block: "end" + }) + } + } + }, [isAtBottom, isVisible]) + + useEffect(() => { + const { current } = scrollRef + + if (current) { + const handleScroll = (event: Event) => { + const target = event.target as HTMLDivElement + const offset = 25 + const isAtBottom = + target.scrollTop + target.clientHeight >= target.scrollHeight - offset + console.log(target.scrollTop, target.clientHeight, target.scrollHeight) + setIsAtBottom(isAtBottom) + } + + current.addEventListener("scroll", handleScroll, { + passive: true + }) + + return () => { + current.removeEventListener("scroll", handleScroll) + } + } + }, []) + + useEffect(() => { + if (visibilityRef.current) { + let observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + console.log(entry.isIntersecting) + if (entry.isIntersecting) { + setIsVisible(true) + } else { + setIsVisible(false) + } + }) + }, + { + rootMargin: "0px 0px -100px 0px" + } + ) + + observer.observe(visibilityRef.current) + + return () => { + observer.disconnect() + } + } + }) + + return { + messagesRef, + scrollRef, + visibilityRef, + scrollToBottom, + isAtBottom, + isVisible + } +}