YesPlayMusic/packages/web/hooks/useScroll.ts

70 lines
1.7 KiB
TypeScript
Raw Normal View History

2022-03-13 14:40:38 +08:00
// Inspired by https://github.com/vueuse/vueuse
import { throttle as lodashThrottle } from 'lodash-es'
2022-05-12 02:45:43 +08:00
import { useEffect, useState } from 'react'
2022-03-13 14:40:38 +08:00
interface ArrivedState {
top: boolean
bottom: boolean
left: boolean
right: boolean
}
interface Offset {
top?: number
bottom?: number
left?: number
right?: number
}
const useScroll = (
ref: React.RefObject<HTMLDivElement> | HTMLElement | null,
{ offset, throttle }: { offset?: Offset; throttle?: number } = {}
) => {
const [scroll, setScroll] = useState<{
x: number
y: number
arrivedState: ArrivedState
}>({
x: 0,
y: 0,
arrivedState: {
top: true,
bottom: false,
left: false,
right: false,
},
})
useEffect(() => {
if (!ref) return
2022-03-17 14:45:04 +08:00
const handleScroll = (e: Event) => {
if (!e.target) return
const target = e.target as HTMLElement
2022-03-13 14:40:38 +08:00
const arrivedState: ArrivedState = {
left: target.scrollLeft <= 0 + (offset?.left || 0),
2023-03-26 02:16:01 +08:00
right: target.scrollLeft + target.clientWidth >= target.scrollWidth - (offset?.right || 0),
2022-03-13 14:40:38 +08:00
top: target.scrollTop <= 0 + (offset?.top || 0),
bottom:
2023-03-26 02:16:01 +08:00
target.scrollTop + target.clientHeight >= target.scrollHeight - (offset?.bottom || 0),
2022-03-13 14:40:38 +08:00
}
setScroll({
x: target.scrollLeft,
y: target.scrollTop,
arrivedState,
})
}
2023-03-26 02:16:01 +08:00
const readHandleScroll = throttle ? lodashThrottle(handleScroll, throttle) : handleScroll
2022-03-13 14:40:38 +08:00
const element = 'current' in ref ? ref?.current : ref
element?.addEventListener('scroll', readHandleScroll)
return () => element?.removeEventListener('scroll', readHandleScroll)
}, [offset?.bottom, offset?.left, offset?.right, offset?.top, ref, throttle])
return scroll
}
export default useScroll