jsx import { CSSObject , jsx } from '@emotion/core' ; import React , { CSSProperties } from 'react' ; import Color from 'color' ; import { CloseIcon } from '../Icon' ; import type { SVGIconProps } from '../Icon/SVGIcon' ; import { COLOR } from '../Identity' ; import type { Theme } from '../Layout' ; import { QueryKeys , media } from '../mediaQueries' ; import { filterProps , noop } from '../util' ; import { OverlayBackgroundProps , OverlayWrapper , overlayBackgroundStyle } from './Overlay' ; export interface ModalBodyProps < T = HTMLDivElement > extends React . HTMLProps < T > { fullscreen ? : boolean ; } const modalBodyStyle = ( theme , { fullscreen = false } ) => ( { alignItems : 'center' , backgroundColor : COLOR . tint ( theme . general . backgroundColor , 0.16 ) , borderRadius : fullscreen ? 0 : '8px' , bottom : fullscreen ? 0 : undefined , boxShadow : fullscreen ? 'none' : '0 16px 64px 0 rgba(0, 0, 0, 0.16)' , display : 'flex' , flexDirection : 'column' , justifyContent : fullscreen ? 'center' : 'space-between' , left : fullscreen ? 0 : undefined , margin : 'auto' , position : fullscreen ? 'fixed' : 'relative' , right : fullscreen ? 0 : undefined , top : fullscreen ? 0 : undefined , transform : 'translate3d(0, 0, 0)' , zIndex : 9999 , [ media [ QueryKeys . TABLET_DOWN ] ] : { width : fullscreen ? 'initial' : '100%' , } , } ) ; const filterModalBodyProps = ( props ) => filterProps ( props , [ 'fullscreen' ] ) ; const ModalBody = ( props ) => ( < div css = { theme => modalBodyStyle ( theme , props ) } { ... filterModalBodyProps ( props ) } />); const ModalClose = ( props ) => ( < CloseIcon width = { 16 } height = { 16 } css = { { alignItems : 'center' , cursor : 'pointer' , display : 'flex' , justifyContent : 'center' , position : 'absolute' , right : 16 , top : 16 , } } { ... props } />); const ModalContent = props => ( < div css = { { maxWidth : '100%' , overflowY : 'auto' , padding : '40px' , } } { ... props } />); const modalBackgroundStyle = props => ( { ... overlayBackgroundStyle ( props ) , backgroundColor : 'rgba(50, 54, 57, 0.4)' , } ) ; const ModalBackground = ( props ) => < div css = { modalBackgroundStyle ( props ) } { ... props } />; export interface ModalActionItem { bold ? : boolean ; dataUieName ? : string ; onClick : ( event : React . MouseEvent < HTMLElement > ) => void ; title : string ; } interface ModalActions { actions ? : ModalActionItem [ ] ; } const modalActionsWrapperStyles = ( ) => ( { borderTop : `1px solid ${ COLOR . GRAY_LIGHTEN_72 }` , bottom : 0 , display : 'flex' , div : { '&:hover' : { backgroundColor : COLOR . opaque ( COLOR . GRAY_DARKEN_72 , 0.04 ) , } , '&:active' : { backgroundColor : COLOR . opaque ( COLOR . GRAY_DARKEN_72 , 0.08 ) , } , borderRight : `1px solid ${ COLOR . GRAY_LIGHTEN_72 }` , } , 'div:first-child' : { borderBottomLeftRadius : 8 , } , 'div:last-child' : { borderBottomRightRadius : 8 , borderRight : 0 , } , position : 'absolute' , width : '100%' , } ) ; const modalActionStyles = ( { bold } ) => ( { '&:hover' : { color : Color ( COLOR . BLUE ) . mix ( Color ( COLOR . BLACK ) , 0.16 ) . toString ( ) , } , color : COLOR . BLUE , cursor : 'pointer' , display : 'flex' , flex : 1 , fontWeight : bold ? 'bold' : 'normal' , justifyContent : 'center' , padding : '8px 0' , } ) ; const ModalActions = ( { actions } ) => ( < div css = { modalActionsWrapperStyles ( ) } > { actions . map ( action => ( < div key = { action . title } onClick = { action . onClick } css = { modalActionStyles ( { bold : action . bold } ) } data - uie - name = { action . dataUieName } > { action . title } < /div>))} < /div>); interface ModalProps { actions ? : ModalActionItem [ ] ; bodyStyle ? : CSSProperties ; fullscreen ? : boolean ; onBackgroundClick ? : ( ) => void ; onClose ? : ( ) => void ; } export const Modal = ( { actions = [ ] , children , bodyStyle , fullscreen , onClose , onBackgroundClick , ... props } ) => ( < OverlayWrapper { ... props } data - uie - name = "modal" > < ModalBody fullscreen = { fullscreen } style = { bodyStyle } > < ModalContent > { children } < /ModalContent> { onClose !== noop && < ModalClose onClick = { onClose } data - uie - name = "do-close" / > } { actions . length > 0 && < ModalActions actions = { actions } data - uie - name = "modal-actions" / > } < /ModalBody> { ! fullscreen && ( < ModalBackground onClick = { onBackgroundClick === noop ? onClose : onBackgroundClick } data - uie - name = "modal-background" / > ) } < /OverlayWrapper>); Modal . defaultProps = { actions : [ ] , fullscreen : false , onBackgroundClick : noop , onClose : noop , } ;