license import React from 'react' ; import { FlexStyle , StyleSheet , View , ViewProps , ViewStyle , Dimensions , } from 'react-native' ; import { Frame , MeasureElement , MeasuringElement , Point , } from '../../devsupport' ; import { ModalPresentingConfig , ModalService , } from '../../theme' ; export interface ModalProps extends ViewProps , ModalPresentingConfig { visible ? : boolean ; children ? : React . ReactNode ; } export type ModalElement = React . ReactElement < ModalProps > ; interface State { contentFrame : Frame ; forceMeasure : boolean ; } extends React . Component method method property property property property property overview-example overview-example export class Modal extends React . PureComponent < ModalProps , State > { public state : State = { contentFrame : Frame . zero ( ) , forceMeasure : false , } ; private modalId : string ; private contentPosition : Point = Point . outscreen ( ) ; private get contentFlexPosition ( ) : FlexStyle { const derivedStyle = StyleSheet . flatten ( this . props . style || { } ) ; const { x : centerX , y : centerY } = this . contentPosition ; return { left : derivedStyle . left || centerX , top : derivedStyle . top || centerY } ; } private get backdropConfig ( ) : ModalPresentingConfig { const { onBackdropPress , backdropStyle } = this . props ; return { onBackdropPress , backdropStyle } ; } public show = ( ) : void => { this . modalId = ModalService . show ( this . renderMeasuringContentElement ( ) , this . backdropConfig ) ; } ; public hide = ( ) : void => { this . modalId = ModalService . hide ( this . modalId ) ; } ; public componentDidMount ( ) { Dimensions . addEventListener ( 'change' , this . onDimensionChange ) ; if ( ! this . modalId && this . props . visible ) { this . show ( ) ; return ; } } public componentDidUpdate ( prevProps ) { if ( ! this . modalId && this . props . visible && ! this . state . forceMeasure ) { this . setState ( { forceMeasure : true } ) ; return ; } if ( ! this . modalId && this . props . visible ) { this . show ( ) ; return ; } if ( this . modalId && ! this . props . visible ) { this . hide ( ) ; } if ( this . modalId && this . props . visible ) { ModalService . update ( this . modalId , this . renderContentElement ( ) ) ; } } public componentWillUnmount ( ) { Dimensions . removeEventListener ( 'change' , this . onDimensionChange ) ; this . hide ( ) ; } private onDimensionChange = ( ) : void => { if ( this . props . visible ) { ModalService . update ( this . modalId , this . renderMeasuringContentElement ( ) ) ; } } ; private onContentMeasure = ( contentFrame ) : void => { this . state . contentFrame = contentFrame ; const displayFrame = this . state . contentFrame . centerOf ( Frame . window ( ) ) ; this . contentPosition = displayFrame . origin ; ModalService . update ( this . modalId , this . renderContentElement ( ) ) ; } ; private renderContentElement = ( ) : React . ReactElement < ViewProps > => { return ( < View { ... this . props } style = { [ this . props . style , styles . modalView , this . contentFlexPosition ] } / > ) ; } ; private renderMeasuringContentElement = ( ) : MeasuringElement => { return ( < MeasureElement shouldUseTopInsets = { ModalService . getShouldUseTopInsets } onMeasure = { this . onContentMeasure } > { this . renderContentElement ( ) } < /MeasureElement>); } ; public render ( ) { return null ; } } const styles = StyleSheet . create ( { modalView : { position : 'absolute' , } , } ) ;