@@ -21,31 +21,48 @@ type scrollDir =
2121 | Up ({scrollY : int })
2222 | Down ({scrollY : int })
2323
24+ type action =
25+ | Skip
26+ | EnterTop
27+ | DownToUp
28+ | UpToDown
29+ | KeepDown
30+ | KeepUp
31+
2432/**
2533 This will cause highly frequent events, so use it only once in a root as possible.
2634 And split the children components to prevent heavy ones from being re-rendered unnecessarily. */
27- let useScrollDirection = () => {
28- let (_ , startScrollEventTransition ) = React .useTransition ()
29- let (scrollDir , setScrollDir ) = React .useState (() => Up ({scrollY : %raw (` Infinity ` ) }))
35+ let useScrollDirection = (~topMargin = 80 , ~threshold = 20 ) => {
36+ let (scrollDir , setScrollDir ) = React .useState (() => Up ({
37+ scrollY : 999999 , // pseudo infinity
38+ }))
3039
3140 React .useEffect (() => {
3241 let onScroll = _e => {
33- startScrollEventTransition (() => {
34- setScrollDir (
35- prev => {
36- let Up ({scrollY }) | Down ({scrollY }) = prev
37- if scrollY === 0 || scrollY > Webapi .Window .scrollY {
38- Up ({scrollY : Webapi .Window .scrollY })
39- } else {
40- Down ({scrollY : Webapi .Window .scrollY })
41- }
42- },
43- )
42+ setScrollDir (prev => {
43+ let scrollY = Webapi .Window .scrollY
44+ let enterTopMargin = scrollY <= topMargin
45+
46+ let action = switch prev {
47+ | Up (_ ) if enterTopMargin => Skip
48+ | Down (_ ) if enterTopMargin => EnterTop
49+ | Up ({scrollY : prevScrollY }) if prevScrollY < scrollY => UpToDown
50+ | Up ({scrollY : prevScrollY }) if prevScrollY - threshold >= scrollY => KeepUp
51+ | Down ({scrollY : prevScrollY }) if scrollY < prevScrollY => DownToUp
52+ | Down ({scrollY : prevScrollY }) if scrollY - threshold >= prevScrollY => KeepDown
53+ | _ => Skip
54+ }
55+
56+ switch action {
57+ | Skip => prev
58+ | EnterTop | DownToUp | KeepUp => Up ({scrollY : scrollY })
59+ | UpToDown | KeepDown => Down ({scrollY : scrollY })
60+ }
4461 })
4562 }
4663 Webapi .Window .addEventListener ("scroll" , onScroll )
4764 Some (() => Webapi .Window .removeEventListener ("scroll" , onScroll ))
48- }, [])
65+ }, [topMargin , threshold ])
4966
5067 scrollDir
5168}
0 commit comments