11import {
22 forwardRef ,
33 useCallback ,
4+ useLayoutEffect ,
45 useMemo ,
6+ useRef ,
57 type ComponentRef ,
68 type ReactElement ,
79 type ReactNode ,
810 type Ref ,
911} from 'react' ;
10- import type { ScrollViewProps } from 'react-native' ;
12+ import type { LayoutChangeEvent , ScrollViewProps } from 'react-native' ;
1113import Animated , {
1214 type AnimatedProps ,
1315 type AnimatedRef ,
@@ -74,18 +76,18 @@ export function createHeaderMotionScrollable<
7476 ) } )`,
7577 } = options || { } ;
7678
77- const AnimatedScrollable = ( isComponentAnimated
78- ? ScrollableComponent
79- : Animated . createAnimatedComponent (
80- ScrollableComponent as never
81- ) ) as unknown as ScrollableImplementationComponent ;
79+ const AnimatedScrollable = (
80+ isComponentAnimated
81+ ? ScrollableComponent
82+ : Animated . createAnimatedComponent ( ScrollableComponent )
83+ ) as ScrollableImplementationComponent ;
8284
8385 function HeaderMotionScrollable ( props : ScrollableRuntimeProps ) {
8486 const {
8587 scrollId,
8688 animatedRef,
8789 headerOffsetStrategy,
88- ensureScrollableContentMinHeight = true ,
90+ ensureScrollableContentMinHeight = false ,
8991 contentContainerStyle,
9092 refreshControl,
9193 refreshing,
@@ -114,31 +116,39 @@ export function createHeaderMotionScrollable<
114116 onMomentumScrollBegin,
115117 onMomentumScrollEnd,
116118 animatedRef,
119+ ensureScrollableContentMinHeight,
117120 }
118121 ) ;
119122
120123 const {
121124 onScroll : managedOnScroll ,
125+ onLayout : managedOnLayout ,
122126 refreshControl : managedRefreshControl ,
123127 ref,
124128 ...scrollViewProps
125129 } = scrollableProps ;
126- const { originalHeaderHeight, minHeightContentContainerStyle } =
130+ const { originalHeaderHeight, contentContainerMinHeight } =
127131 headerMotionContext ;
128132
133+ const userOnLayoutRef = useRef < UserOnLayout > ( rest . onLayout as UserOnLayout ) ;
134+ useLayoutEffect ( ( ) => {
135+ userOnLayoutRef . current = rest . onLayout as UserOnLayout ;
136+ } ) ;
137+
129138 const managedContentContainerStyle = useMemo (
130139 ( ) => [
131- ensureScrollableContentMinHeight
132- ? minHeightContentContainerStyle
140+ ensureScrollableContentMinHeight &&
141+ contentContainerMinHeight !== undefined
142+ ? { minHeight : contentContainerMinHeight }
133143 : undefined ,
134144 resolveHeaderOffsetStyle ( originalHeaderHeight , headerOffsetStrategy ) ,
135145 contentContainerStyle ,
136146 ] ,
137147 [
138148 contentContainerStyle ,
149+ contentContainerMinHeight ,
139150 ensureScrollableContentMinHeight ,
140151 headerOffsetStrategy ,
141- minHeightContentContainerStyle ,
142152 originalHeaderHeight ,
143153 ]
144154 ) ;
@@ -147,6 +157,14 @@ export function createHeaderMotionScrollable<
147157 refreshControl : managedRefreshControl ,
148158 } ;
149159
160+ const handleLayout = useCallback (
161+ ( e : LayoutChangeEvent ) => {
162+ managedOnLayout ?.( e ) ;
163+ userOnLayoutRef . current ?.( e ) ;
164+ } ,
165+ [ managedOnLayout ]
166+ ) ;
167+
150168 const contentContainerProps = useContentContainerProps ( {
151169 children : rest . children ,
152170 mode : contentContainerMode ,
@@ -160,6 +178,7 @@ export function createHeaderMotionScrollable<
160178 { ...refreshControlProps }
161179 { ...contentContainerProps }
162180 ref = { ref }
181+ onLayout = { handleLayout }
163182 onScroll = { managedOnScroll }
164183 />
165184 ) ;
@@ -222,6 +241,8 @@ function getDisplayName(ScrollableComponent: {
222241 ) ;
223242}
224243
244+ type UserOnLayout = ScrollViewProps [ 'onLayout' ] | undefined ;
245+
225246// TODO: From here below Codex did some absolute TypeScript magic but it seems to work
226247// Having limited time, I can't spend more on adjusting this to make it less convoluted
227248// But what matters is that it seems that for the user the types work very well
0 commit comments