Files
smesh/src/providers/DeepBrowsingProvider.tsx
2025-02-11 16:33:31 +08:00

73 lines
1.9 KiB
TypeScript

import { createContext, useContext, useEffect, useRef, useState } from 'react'
type TDeepBrowsingContext = {
deepBrowsing: boolean
lastScrollTop: number
}
const DeepBrowsingContext = createContext<TDeepBrowsingContext | undefined>(undefined)
export const useDeepBrowsing = () => {
const context = useContext(DeepBrowsingContext)
if (!context) {
throw new Error('useDeepBrowsing must be used within a DeepBrowsingProvider')
}
return context
}
export function DeepBrowsingProvider({
children,
active,
scrollAreaRef
}: {
children: React.ReactNode
active: boolean
scrollAreaRef?: React.RefObject<HTMLDivElement>
}) {
const [deepBrowsing, setDeepBrowsing] = useState(false)
const lastScrollTopRef = useRef(
(!scrollAreaRef ? window.scrollY : scrollAreaRef.current?.scrollTop) || 0
)
const [lastScrollTop, setLastScrollTop] = useState(lastScrollTopRef.current)
useEffect(() => {
setDeepBrowsing(false)
if (!active) return
const handleScroll = () => {
const scrollTop = (!scrollAreaRef ? window.scrollY : scrollAreaRef.current?.scrollTop) || 0
const diff = scrollTop - lastScrollTopRef.current
lastScrollTopRef.current = scrollTop
setLastScrollTop(scrollTop)
if (scrollTop <= 800) {
setDeepBrowsing(false)
return
}
if (diff > 20) {
setDeepBrowsing(true)
} else if (diff < -20) {
setDeepBrowsing(false)
}
}
if (!scrollAreaRef) {
window.addEventListener('scroll', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
}
}
scrollAreaRef.current?.addEventListener('scroll', handleScroll)
return () => {
scrollAreaRef.current?.removeEventListener('scroll', handleScroll)
}
}, [active])
return (
<DeepBrowsingContext.Provider value={{ deepBrowsing, lastScrollTop }}>
{children}
</DeepBrowsingContext.Provider>
)
}