1- import { forwardRef , useRef } from "react" ;
1+ import { forwardRef , useCallback , useRef } from "react" ;
22
33import interpolate from "../interpolate.js" ;
4- import { mergeRefs , useStableLayoutEffect } from "../utils/react-helpers.js" ;
4+ import useAnimationFrame from "../utils/animation-frame.js" ;
5+ import { mergeRefs , type Styles } from "../utils/react-helpers.js" ;
56import { ScrollyElementContext } from "../utils/scrolly-context.js" ;
6- import useScrolly from "../utils/use-scrolly.js" ;
7+ import useScrolly , { ScrollyValues } from "../utils/use-scrolly.js" ;
78
89export interface ScrollyHorizontalElementProps {
910 as ?: React . ElementType ;
@@ -26,6 +27,7 @@ const styles = {
2627 position : "sticky" ,
2728 top : 0 ,
2829 height : "100vh" ,
30+ width : "100vw" ,
2931 display : "inline-block" ,
3032 overflow : "hidden" ,
3133 } ,
@@ -38,7 +40,7 @@ const styles = {
3840 willChange : "transform" ,
3941 pointerEvents : "auto" ,
4042 } ,
41- } satisfies Record < string , React . CSSProperties > ;
43+ } satisfies Styles ;
4244
4345const ScrollyHorizontalElement = (
4446 props : ScrollyHorizontalElementProps ,
@@ -86,48 +88,28 @@ const ScrollyHorizontalElement = (
8688
8789export default forwardRef ( ScrollyHorizontalElement ) ;
8890
89- const CSS_PROPERTY_OVERFLOW_X = "overflow-x" ;
90-
9191function useScrollyHorizontalElementLayout (
9292 containerRef : React . RefObject < HTMLDivElement > ,
9393 contentRef : React . RefObject < HTMLDivElement >
94- ) {
95- const timeRef = useRef ( 0 ) ;
94+ ) : ScrollyValues {
9695 const scrollyValues = useScrolly ( containerRef , {
9796 precision : 3 ,
9897 } ) ;
9998 const { windowWidth, windowHeight, scrollRatio } = scrollyValues ;
10099
101- // Make sure the body doesn't scroll horizontally itself
102- useStableLayoutEffect ( ( ) => {
103- const previousOverflowX = document . body . style . getPropertyValue (
104- CSS_PROPERTY_OVERFLOW_X
105- ) ;
106- document . body . style . setProperty ( CSS_PROPERTY_OVERFLOW_X , "hidden" ) ;
107-
108- return ( ) =>
109- document . body . style . setProperty (
110- CSS_PROPERTY_OVERFLOW_X ,
111- previousOverflowX
112- ) ;
113- } , [ ] ) ;
114-
115- useStableLayoutEffect ( ( ) => {
116- const contentScrollWidth = contentRef . current ?. scrollWidth || 0 ;
117- const scrollDistance = Math . max ( contentScrollWidth - windowWidth , 0 ) ;
118-
119- // Make container taller to accommodate scroll distance
120- const containerHeight = windowHeight + scrollDistance ;
121- containerRef . current ?. style . setProperty ( "height" , `${ containerHeight } px` ) ;
100+ const handleAnimationFrame = useCallback (
101+ ( _ : number , delta : number ) => {
102+ const contentScrollWidth = contentRef . current ?. scrollWidth || 0 ;
103+ const scrollDistance = Math . max ( contentScrollWidth - windowWidth , 0 ) ;
122104
123- const translateValue = interpolate ( scrollRatio , {
124- targetFrom : 0 ,
125- targetTo : scrollDistance ,
126- } ) . toFixed ( 0 ) ;
105+ // Make container taller to accommodate scroll distance
106+ const containerHeight = windowHeight + scrollDistance ;
107+ containerRef . current ?. style . setProperty ( "height" , `${ containerHeight } px` ) ;
127108
128- const frame = window . requestAnimationFrame ( ( time ) => {
129- const delta = time - timeRef . current ;
130- timeRef . current = time ;
109+ const translateValue = interpolate ( scrollRatio , {
110+ targetFrom : 0 ,
111+ targetTo : scrollDistance ,
112+ } ) . toFixed ( 0 ) ;
131113
132114 contentRef . current ?. animate (
133115 { transform : `translateX(-${ translateValue } px)` } ,
@@ -138,10 +120,11 @@ function useScrollyHorizontalElementLayout(
138120 playbackRate : 1 + delta / 100 ,
139121 }
140122 ) ;
141- } ) ;
123+ } ,
124+ [ containerRef , contentRef , scrollRatio , windowHeight , windowWidth ]
125+ ) ;
142126
143- return ( ) => window . cancelAnimationFrame ( frame ) ;
144- } , [ windowHeight , windowWidth , scrollRatio , contentRef , containerRef ] ) ;
127+ useAnimationFrame ( handleAnimationFrame ) ;
145128
146129 return scrollyValues ;
147130}
0 commit comments