import React, { useEffect, useMemo } from 'react' import { createPortal } from 'react-dom' import usePortal from '../utils/use-portal' import ModalTitle from './modal-title' import ModalSubtitle from './modal-subtitle' import ModalWrapper from './modal-wrapper' import ModalContent from './modal-content' import ModalAction from './modal-action' import ModalActions from './modal-actions' import Backdrop from '../shared/backdrop' import { ModalConfig, ModalContext } from './modal-context' import { pickChild } from '../utils/collections' import useBodyScroll from '../utils/use-body-scroll' import useCurrentState from '../utils/use-current-state' interface Props { disableBackdropClick?: boolean onClose?: () => void onOpen?: () => void open?: boolean width?: string wrapClassName?: string } const defaultProps = { width: '26rem', wrapClassName: '', disableBackdropClick: false } type NativeAttrs = Omit, keyof Props> export type ModalProps = Props & typeof defaultProps & NativeAttrs const Modal: React.FC> = ({ children, disableBackdropClick, onClose, onOpen, open, width: wrapperWidth, wrapClassName }) => { const portal = usePortal( 'modal', () => document.body.querySelector('#hui-modal-root') || document.body ) const [, setBodyHidden] = useBodyScroll(null, { scrollLayer: true }) const [visible, setVisible, visibleRef] = useCurrentState(false) const [withoutActionsChildren, ActionsChildren] = pickChild(children, ModalAction) const hasActions = ActionsChildren && React.Children.count(ActionsChildren) > 0 const closeModal = () => { onClose && onClose() setVisible(false) setBodyHidden(false) } useEffect(() => { if (open === undefined) return if (open) { onOpen && onOpen() } if (!open && visibleRef.current) { onClose && onClose() } setVisible(open) setBodyHidden(open) }, [open]) const closeFromBackdrop = () => { if (disableBackdropClick && hasActions) return closeModal() } const modalConfig: ModalConfig = useMemo( () => ({ close: closeModal }), [] ) if (!portal) return null return createPortal( {withoutActionsChildren} {hasActions && {ActionsChildren}} , portal ) } type ModalComponent

= React.FC

& { Title: typeof ModalTitle Subtitle: typeof ModalSubtitle Content: typeof ModalContent Action: typeof ModalAction } type ComponentProps = Partial & Omit & NativeAttrs Modal.defaultProps = defaultProps export default Modal as ModalComponent