11import classNames from 'classnames' ;
22import type { CSSMotionProps } from '@rc-component/motion' ;
33import CSSMotion from '@rc-component/motion' ;
4- import ResizeObserver from '@rc-component/resize-observer' ;
4+ import ResizeObserver , {
5+ type ResizeObserverProps ,
6+ } from '@rc-component/resize-observer' ;
57import useLayoutEffect from '@rc-component/util/lib/hooks/useLayoutEffect' ;
68import { composeRef } from '@rc-component/util/lib/ref' ;
79import * as React from 'react' ;
@@ -10,6 +12,8 @@ import type { AlignType, ArrowPos, ArrowTypeOuter } from '../interface';
1012import Arrow from './Arrow' ;
1113import Mask from './Mask' ;
1214import PopupContent from './PopupContent' ;
15+ import useOffsetStyle from '../hooks/useOffsetStyle' ;
16+ import { useEvent } from '@rc-component/util' ;
1317
1418export interface MobileConfig {
1519 mask ?: boolean ;
@@ -58,6 +62,8 @@ export interface PopupProps {
5862 autoDestroy ?: boolean ;
5963 portal : React . ComponentType < any > ;
6064
65+ children ?: React . ReactElement ;
66+
6167 // Align
6268 ready : boolean ;
6369 offsetX : number ;
@@ -72,6 +78,9 @@ export interface PopupProps {
7278 targetWidth ?: number ;
7379 targetHeight ?: number ;
7480
81+ // Resize
82+ onResize ?: ResizeObserverProps [ 'onResize' ] ;
83+
7584 // Mobile
7685 mobile ?: MobileConfig ;
7786}
@@ -114,6 +123,7 @@ const Popup = React.forwardRef<HTMLDivElement, PopupProps>((props, ref) => {
114123 getPopupContainer,
115124 autoDestroy,
116125 portal : Portal ,
126+ children,
117127
118128 zIndex,
119129
@@ -130,12 +140,15 @@ const Popup = React.forwardRef<HTMLDivElement, PopupProps>((props, ref) => {
130140 onAlign,
131141 onPrepare,
132142
143+ // Resize
144+ onResize,
145+
133146 stretch,
134147 targetWidth,
135148 targetHeight,
136149 } = props ;
137150
138- const childNode = typeof popup === 'function' ? popup ( ) : popup ;
151+ const popupContent = typeof popup === 'function' ? popup ( ) : popup ;
139152
140153 // We can not remove holder only when motion finished.
141154 const isNodeVisible = open || keepDom ;
@@ -172,48 +185,31 @@ const Popup = React.forwardRef<HTMLDivElement, PopupProps>((props, ref) => {
172185 }
173186 } , [ show , getPopupContainerNeedParams , target ] ) ;
174187
188+ // ========================= Resize =========================
189+ const onInternalResize : ResizeObserverProps [ 'onResize' ] = useEvent (
190+ ( size , ele ) => {
191+ onResize ?.( size , ele ) ;
192+ onAlign ( ) ;
193+ } ,
194+ ) ;
195+
196+ // ========================= Styles =========================
197+ const offsetStyle = useOffsetStyle (
198+ isMobile ,
199+ ready ,
200+ open ,
201+ align ,
202+ offsetR ,
203+ offsetB ,
204+ offsetX ,
205+ offsetY ,
206+ ) ;
207+
175208 // ========================= Render =========================
176209 if ( ! show ) {
177210 return null ;
178211 }
179212
180- // >>>>> Offset
181- const AUTO = 'auto' as const ;
182-
183- const offsetStyle : React . CSSProperties = isMobile
184- ? { }
185- : {
186- left : '-1000vw' ,
187- top : '-1000vh' ,
188- right : AUTO ,
189- bottom : AUTO ,
190- } ;
191-
192- // Set align style
193- if ( ! isMobile && ( ready || ! open ) ) {
194- const { points } = align ;
195- const dynamicInset =
196- align . dynamicInset || ( align as any ) . _experimental ?. dynamicInset ;
197- const alignRight = dynamicInset && points [ 0 ] [ 1 ] === 'r' ;
198- const alignBottom = dynamicInset && points [ 0 ] [ 0 ] === 'b' ;
199-
200- if ( alignRight ) {
201- offsetStyle . right = offsetR ;
202- offsetStyle . left = AUTO ;
203- } else {
204- offsetStyle . left = offsetX ;
205- offsetStyle . right = AUTO ;
206- }
207-
208- if ( alignBottom ) {
209- offsetStyle . bottom = offsetB ;
210- offsetStyle . top = AUTO ;
211- } else {
212- offsetStyle . top = offsetY ;
213- offsetStyle . bottom = AUTO ;
214- }
215- }
216-
217213 // >>>>> Misc
218214 const miscStyle : React . CSSProperties = { } ;
219215 if ( stretch ) {
@@ -247,7 +243,7 @@ const Popup = React.forwardRef<HTMLDivElement, PopupProps>((props, ref) => {
247243 motion = { mergedMaskMotion }
248244 mobile = { isMobile }
249245 />
250- < ResizeObserver onResize = { onAlign } disabled = { ! open } >
246+ < ResizeObserver onResize = { onInternalResize } disabled = { ! open } >
251247 { ( resizeObserverRef ) => {
252248 return (
253249 < CSSMotion
@@ -305,7 +301,7 @@ const Popup = React.forwardRef<HTMLDivElement, PopupProps>((props, ref) => {
305301 />
306302 ) }
307303 < PopupContent cache = { ! open && ! fresh } >
308- { childNode }
304+ { popupContent }
309305 </ PopupContent >
310306 </ div >
311307 ) ;
@@ -314,6 +310,7 @@ const Popup = React.forwardRef<HTMLDivElement, PopupProps>((props, ref) => {
314310 ) ;
315311 } }
316312 </ ResizeObserver >
313+ { children }
317314 </ Portal >
318315 ) ;
319316} ) ;
0 commit comments