import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react" export type BaseTabType = { label: string value: string } type EventData = { storageValue: string } type TabProps = { tabs: T[] group?: string } function useTabs({ tabs, group }: TabProps) { const [selectedTab, setSelectedTab] = useState(null) const storageKey = useMemo(() => `tab_${group}`, [group]) const eventKey = useMemo(() => `tab_${group}_changed`, [group]) const scrollPosition = useRef(0) const changeSelectedTab = (tab: T) => { scrollPosition.current = window.scrollY setSelectedTab(tab) localStorage.setItem(storageKey, tab.value) window.dispatchEvent( new CustomEvent(eventKey, { detail: { storageValue: tab.value, }, }) ) } const findTabItem = useCallback( (val: string) => { const lowerVal = val.toLowerCase() return tabs.find((t) => t.value.toLowerCase() === lowerVal) }, [tabs] ) const handleStorageChange = useCallback( (e: CustomEvent) => { if (e.detail.storageValue !== selectedTab?.value) { // check if tab exists const tab = findTabItem(e.detail.storageValue) if (tab) { setSelectedTab(tab) } } }, [selectedTab, findTabItem] ) as EventListener useEffect(() => { if (!selectedTab) { const storedSelectedTabValue = localStorage.getItem(storageKey) setSelectedTab( storedSelectedTabValue ? findTabItem(storedSelectedTabValue) || tabs[0] : tabs[0] ) } }, [selectedTab, storageKey, tabs, findTabItem]) useEffect(() => { window.addEventListener(eventKey, handleStorageChange) return () => { window.removeEventListener(eventKey, handleStorageChange) } }, [handleStorageChange, eventKey]) useLayoutEffect(() => { if (scrollPosition.current && window.scrollY !== scrollPosition.current) { window.scrollTo(0, scrollPosition.current) } }, [selectedTab]) return { selectedTab, changeSelectedTab } } export default useTabs