@@ -16,7 +16,11 @@ const useLayoutEffect =
1616type ScrollerProps = {
1717 onStepChange : ( stepIndex : number ) => void
1818 children : React . ReactNode
19- getRootMargin ?: ( vh : number ) => string
19+ getRootMargin ?: (
20+ vh : number ,
21+ triggerPosition ?: TriggerPosition
22+ ) => string
23+ triggerPosition ?: TriggerPosition
2024 debug ?: boolean
2125}
2226
@@ -28,30 +32,31 @@ function Scroller({
2832 onStepChange,
2933 children,
3034 getRootMargin = defaultRootMargin ,
35+ triggerPosition,
3136 debug = false ,
3237} : ScrollerProps ) {
33- const [
34- observer ,
35- setObserver ,
36- ] = React . useState < IntersectionObserver > ( )
38+ const [ observer , setObserver ] =
39+ React . useState < IntersectionObserver > ( )
3740 const vh = useWindowHeight ( )
3841
3942 useLayoutEffect ( ( ) => {
4043 const windowHeight = vh || 0
41- const handleIntersect : IntersectionObserverCallback = entries => {
42- if ( debug || ( window as any ) . chDebugScroller ) {
43- debugEntries ( entries )
44- }
45- entries . forEach ( entry => {
46- if ( entry . intersectionRatio > 0 ) {
47- const stepElement = ( entry . target as unknown ) as StepElement
48- onStepChange ( + stepElement . stepIndex )
44+ const handleIntersect : IntersectionObserverCallback =
45+ entries => {
46+ if ( debug || ( window as any ) . chDebugScroller ) {
47+ debugEntries ( entries )
4948 }
50- } )
51- }
49+ entries . forEach ( entry => {
50+ if ( entry . intersectionRatio > 0 ) {
51+ const stepElement =
52+ entry . target as unknown as StepElement
53+ onStepChange ( + stepElement . stepIndex )
54+ }
55+ } )
56+ }
5257 const observer = newIntersectionObserver (
5358 handleIntersect ,
54- getRootMargin ( windowHeight )
59+ getRootMargin ( windowHeight , triggerPosition )
5560 )
5661 setObserver ( observer )
5762
@@ -85,7 +90,8 @@ function Step({
8590 } , [ observer ] )
8691
8792 useLayoutEffect ( ( ) => {
88- const stepElement = ( ref . current as unknown ) as StepElement
93+ const stepElement =
94+ ref . current as unknown as StepElement
8995 stepElement . stepIndex = index
9096 } , [ index ] )
9197
@@ -103,6 +109,26 @@ function newIntersectionObserver(
103109 } )
104110}
105111
106- function defaultRootMargin ( vh : number ) {
107- return `-${ vh / 2 - 2 } px 0px`
112+ type TriggerPosition = `${number } px` | `${number } %`
113+
114+ function defaultRootMargin (
115+ vh : number ,
116+ triggerPosition = "50%"
117+ ) {
118+ let y = vh * 0.5
119+
120+ if ( triggerPosition . endsWith ( "%" ) ) {
121+ const percent = parseFloat (
122+ triggerPosition . replace ( "%" , "" )
123+ )
124+ y = vh * ( percent / 100 )
125+ } else if ( triggerPosition . endsWith ( "px" ) ) {
126+ y = parseFloat ( triggerPosition . replace ( "px" , "" ) )
127+ }
128+
129+ if ( y < 0 ) {
130+ y = vh + y
131+ }
132+
133+ return `-${ y - 2 } px 0px -${ vh - y - 2 } px`
108134}
0 commit comments