99} from 'react'
1010
1111import { CloseIcon } from '@mx-space/kami-design/components/Icons/layout'
12+ import { RootPortalProvider } from '@mx-space/kami-design/components/Portal/provider'
1213
14+ import { useIsMountedState } from '~/hooks/use-is-mounted'
1315import { useStore } from '~/store'
1416
1517import { BottomUpTransitionView } from '../Transition/bottom-up'
@@ -18,17 +20,18 @@ import { ScaleModalTransition } from './scale-transition'
1820
1921export interface ModalProps {
2022 title ?: string
21- // TODO action
2223 closeable ?: boolean
2324 onClose ?: ( ) => any
2425 modalClassName ?: string
2526 contentClassName ?: string
2627 noBlur ?: boolean
2728 fixedWidth ?: boolean
29+ useRootPortal ?: boolean
2830}
2931
3032export type ModalRefObject = {
3133 dismiss : ( ) => Promise < void >
34+ getElement : ( ) => HTMLElement
3235}
3336export const Modal = observer (
3437 forwardRef <
@@ -50,8 +53,13 @@ export const Modal = observer(
5053 } )
5154 } , [ props . disposer ] )
5255
56+ const $wrapper = useRef < HTMLDivElement > ( null )
57+
5358 useImperativeHandle ( ref , ( ) => ( {
5459 dismiss,
60+ getElement : ( ) => {
61+ return $wrapper . current as HTMLElement
62+ } ,
5563 } ) )
5664
5765 const {
@@ -60,10 +68,27 @@ export const Modal = observer(
6068 } ,
6169 } = useStore ( )
6270
63- const { title, closeable } = props
71+ const { title, closeable, modalId , useRootPortal } = props
6472 const useDrawerStyle = mobile && props . useBottomDrawerInMobile
73+
74+ const isMounted = useIsMountedState ( )
75+
76+ const Content = (
77+ < div
78+ className = { clsx (
79+ styles [ 'content' ] ,
80+ title && styles [ 'has-title' ] ,
81+ props . contentClassName ,
82+ ) }
83+ >
84+ { props . children }
85+ </ div >
86+ )
87+
6588 const Children = (
6689 < div
90+ id = { modalId }
91+ ref = { $wrapper }
6792 className = { clsx (
6893 styles [ 'modal' ] ,
6994 props . fixedWidth && styles [ 'fixed-width' ] ,
@@ -86,15 +111,15 @@ export const Modal = observer(
86111 < CloseIcon />
87112 </ div >
88113 ) }
89- < div
90- className = { clsx (
91- styles [ 'content' ] ,
92- title && styles [ 'has-title' ] ,
93- props . contentClassName ,
94- ) }
95- >
96- { props . children }
97- </ div >
114+ { useRootPortal ? (
115+ isMounted ? (
116+ < RootPortalProvider value = { { to : $wrapper . current as HTMLElement } } >
117+ { Content }
118+ </ RootPortalProvider >
119+ ) : null
120+ ) : (
121+ Content
122+ ) }
98123 </ div >
99124 )
100125
0 commit comments