7 changed files with 175 additions and 183 deletions
@ -0,0 +1,80 @@ |
|||||||
|
import { createContext, useContext, useEffect, 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 [lastScrollTop, setLastScrollTop] = useState(0) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (!active) return |
||||||
|
|
||||||
|
const handleScroll = () => { |
||||||
|
const atBottom = !scrollAreaRef |
||||||
|
? window.innerHeight + window.scrollY >= document.body.offsetHeight - 20 |
||||||
|
: scrollAreaRef.current |
||||||
|
? scrollAreaRef.current?.clientHeight + scrollAreaRef.current?.scrollTop >= |
||||||
|
scrollAreaRef.current?.scrollHeight - 20 |
||||||
|
: false |
||||||
|
if (atBottom) { |
||||||
|
setDeepBrowsing(false) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
const scrollTop = (!scrollAreaRef ? window.scrollY : scrollAreaRef.current?.scrollTop) || 0 |
||||||
|
const diff = scrollTop - lastScrollTop |
||||||
|
if (scrollTop <= 800) { |
||||||
|
setDeepBrowsing(false) |
||||||
|
setLastScrollTop(scrollTop) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if (diff > 20) { |
||||||
|
setDeepBrowsing(true) |
||||||
|
setLastScrollTop(scrollTop) |
||||||
|
} else if (diff < -20) { |
||||||
|
setDeepBrowsing(false) |
||||||
|
setLastScrollTop(scrollTop) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (!scrollAreaRef) { |
||||||
|
window.addEventListener('scroll', handleScroll) |
||||||
|
return () => { |
||||||
|
window.removeEventListener('scroll', handleScroll) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
scrollAreaRef.current?.addEventListener('scroll', handleScroll) |
||||||
|
return () => { |
||||||
|
scrollAreaRef.current?.removeEventListener('scroll', handleScroll) |
||||||
|
} |
||||||
|
}, [lastScrollTop, active]) |
||||||
|
|
||||||
|
return ( |
||||||
|
<DeepBrowsingContext.Provider value={{ deepBrowsing, lastScrollTop }}> |
||||||
|
{children} |
||||||
|
</DeepBrowsingContext.Provider> |
||||||
|
) |
||||||
|
} |
||||||
Loading…
Reference in new issue