import { createContext, Dispatch, ReactNode, SetStateAction, useCallback, useContext, useRef, useState, } from "react"; /** * */ interface ScrollHandlerContextType { categoryRefs: React.RefObject<{ [key: number]: HTMLDivElement | null }>; showScrollTop: boolean; setShowScrollTop: Dispatch>; isCategoriesSticky: boolean; setIsCategoriesSticky: Dispatch>; categoriesContainerRef: React.RefObject; scrollToCategory: (categoryId: number) => void; activeCategory: number | null; setActiveCategory: Dispatch>; } const ScrollHandlerContext = createContext< ScrollHandlerContextType | undefined >(undefined); export function ScrollHandlerProvider({ children }: { children: ReactNode }) { const categoryRefs = useRef<{ [key: number]: HTMLDivElement | null }>({}); const [showScrollTop, setShowScrollTop] = useState(false); // Handle scroll to show/hide scroll-to-top button and sticky categories const [isCategoriesSticky, setIsCategoriesSticky] = useState(false); const categoriesContainerRef = useRef(null); // Active category state const [activeCategory, setActiveCategory] = useState(null); // Function to scroll to a specific category const scrollToCategory = useCallback((categoryId: number) => { const categoryRef = categoryRefs.current?.[categoryId]; // Use a more stable approach to find the scroll container const findScrollContainer = () => { const antApp = document.querySelector('.ant-app') as HTMLElement; if (antApp && antApp.scrollHeight > antApp.clientHeight) { return antApp; } const appContainer = document.querySelector('[class*="App"]') as HTMLElement; if (appContainer && appContainer.scrollHeight > appContainer.clientHeight) { return appContainer; } return document.documentElement; }; const scrollContainer = findScrollContainer(); if (categoryRef && scrollContainer) { // Get the position of the category relative to the scroll container const categoryRect = categoryRef.getBoundingClientRect(); const containerRect = scrollContainer.getBoundingClientRect(); // Calculate the target scroll position const targetScrollTop = scrollContainer.scrollTop + categoryRect.top - containerRect.top; // Smooth scroll to the target position scrollContainer.scrollTo({ top: targetScrollTop, behavior: "smooth" }); } }, []); return ( {children} ); } // eslint-disable-next-line react-refresh/only-export-components export function useScrollHandler() { const context = useContext(ScrollHandlerContext); if (context === undefined) { throw new Error( "useScrollHandler must be used within a ScrollHandlerProvider" ); } return context; }