@@ -29,6 +29,9 @@ type PopoverWithMeasuredContentProps = Omit<PopoverProps, 'anchorPosition'> & {
2929
3030 /** Whether we should should use top side for the anchor positioning */
3131 shouldMeasureAnchorPositionFromTop ?: boolean ;
32+
33+ /** Whether to skip re-measurement when becoming visible (for components with static dimensions) */
34+ shouldSkipRemeasurement ?: boolean ;
3235} ;
3336
3437/**
@@ -66,6 +69,7 @@ function PopoverWithMeasuredContent({
6669 shouldHandleNavigationBack = false ,
6770 shouldEnableNewFocusManagement,
6871 shouldMeasureAnchorPositionFromTop = false ,
72+ shouldSkipRemeasurement = false ,
6973 ...props
7074} : PopoverWithMeasuredContentProps ) {
7175 const actionSheetAwareScrollViewContext = useContext ( ActionSheetAwareScrollView . ActionSheetAwareScrollViewContext ) ;
@@ -75,15 +79,28 @@ function PopoverWithMeasuredContent({
7579 const [ popoverHeight , setPopoverHeight ] = useState ( popoverDimensions . height ) ;
7680 const [ isContentMeasured , setIsContentMeasured ] = useState ( popoverWidth > 0 && popoverHeight > 0 ) ;
7781 const prevIsVisible = usePrevious ( isVisible ) ;
82+ const prevAnchorPosition = usePrevious ( anchorPosition ) ;
83+ const prevWindowDimensions = usePrevious ( { windowWidth, windowHeight} ) ;
7884
7985 const modalId = useMemo ( ( ) => ComposerFocusManager . getId ( ) , [ ] ) ;
8086
8187 if ( ! prevIsVisible && isVisible && shouldEnableNewFocusManagement ) {
8288 ComposerFocusManager . saveFocusState ( modalId ) ;
8389 }
8490
85- if ( ! prevIsVisible && isVisible && isContentMeasured ) {
86- setIsContentMeasured ( false ) ;
91+ if ( ! prevIsVisible && isVisible && isContentMeasured && ! shouldSkipRemeasurement ) {
92+ // Check if anything significant changed that would require re-measurement
93+ const hasAnchorPositionChanged = ! isEqual ( prevAnchorPosition , anchorPosition ) ;
94+ const hasWindowSizeChanged = ! isEqual ( prevWindowDimensions , { windowWidth, windowHeight} ) ;
95+ const hasStaticDimensions = popoverDimensions . width > 0 && popoverDimensions . height > 0 ;
96+
97+ // Only reset if:
98+ // 1. We don't have static dimensions, OR
99+ // 2. The anchor position changed significantly, OR
100+ // 3. The window size changed significantly
101+ if ( ! hasStaticDimensions || hasAnchorPositionChanged || hasWindowSizeChanged ) {
102+ setIsContentMeasured ( false ) ;
103+ }
87104 }
88105
89106 /**
@@ -144,28 +161,39 @@ function PopoverWithMeasuredContent({
144161 } ;
145162 } , [ anchorPosition , anchorAlignment , popoverWidth , popoverHeight ] ) ;
146163
147- const horizontalShift = PopoverWithMeasuredContentUtils . computeHorizontalShift ( adjustedAnchorPosition . left , popoverWidth , windowWidth ) ;
148- const verticalShift = PopoverWithMeasuredContentUtils . computeVerticalShift (
149- adjustedAnchorPosition . top ,
150- popoverHeight ,
151- windowHeight ,
152- anchorDimensions . height ,
153- shouldSwitchPositionIfOverflow ,
154- ) ;
155- const shiftedAnchorPosition : PopoverAnchorPosition = {
156- left : adjustedAnchorPosition . left + horizontalShift ,
157- ...( shouldMeasureAnchorPositionFromTop ? { top : adjustedAnchorPosition . top + verticalShift } : { } ) ,
158- } ;
164+ const positionCalculations = useMemo ( ( ) => {
165+ const horizontalShift = PopoverWithMeasuredContentUtils . computeHorizontalShift ( adjustedAnchorPosition . left , popoverWidth , windowWidth ) ;
166+ const verticalShift = PopoverWithMeasuredContentUtils . computeVerticalShift (
167+ adjustedAnchorPosition . top ,
168+ popoverHeight ,
169+ windowHeight ,
170+ anchorDimensions . height ,
171+ shouldSwitchPositionIfOverflow ,
172+ ) ;
173+ return { horizontalShift, verticalShift} ;
174+ } , [ adjustedAnchorPosition . left , adjustedAnchorPosition . top , popoverWidth , popoverHeight , windowWidth , windowHeight , anchorDimensions . height , shouldSwitchPositionIfOverflow ] ) ;
175+
176+ const shiftedAnchorPosition : PopoverAnchorPosition = useMemo ( ( ) => {
177+ const result : PopoverAnchorPosition = {
178+ left : adjustedAnchorPosition . left + positionCalculations . horizontalShift ,
179+ } ;
159180
160- if ( anchorAlignment . vertical === CONST . MODAL . ANCHOR_ORIGIN_VERTICAL . TOP ) {
161- const top = adjustedAnchorPosition . top + verticalShift ;
162- const maxTop = windowHeight - popoverHeight - verticalShift ;
163- shiftedAnchorPosition . top = Math . min ( Math . max ( verticalShift , top ) , maxTop ) ;
164- }
181+ if ( shouldMeasureAnchorPositionFromTop ) {
182+ result . top = adjustedAnchorPosition . top + positionCalculations . verticalShift ;
183+ }
165184
166- if ( anchorAlignment . vertical === CONST . MODAL . ANCHOR_ORIGIN_VERTICAL . BOTTOM ) {
167- shiftedAnchorPosition . bottom = windowHeight - ( adjustedAnchorPosition . top + popoverHeight ) - verticalShift ;
168- }
185+ if ( anchorAlignment . vertical === CONST . MODAL . ANCHOR_ORIGIN_VERTICAL . TOP ) {
186+ const top = adjustedAnchorPosition . top + positionCalculations . verticalShift ;
187+ const maxTop = windowHeight - popoverHeight - positionCalculations . verticalShift ;
188+ result . top = Math . min ( Math . max ( positionCalculations . verticalShift , top ) , maxTop ) ;
189+ }
190+
191+ if ( anchorAlignment . vertical === CONST . MODAL . ANCHOR_ORIGIN_VERTICAL . BOTTOM ) {
192+ result . bottom = windowHeight - ( adjustedAnchorPosition . top + popoverHeight ) - positionCalculations . verticalShift ;
193+ }
194+
195+ return result ;
196+ } , [ adjustedAnchorPosition , positionCalculations , anchorAlignment . vertical , windowHeight , popoverHeight , shouldMeasureAnchorPositionFromTop ] ) ;
169197
170198 return isContentMeasured ? (
171199 < Popover
0 commit comments