Skip to content

Instantly share code, notes, and snippets.

@ErikGMatos
Created August 26, 2021 02:20
Show Gist options
  • Save ErikGMatos/69a2b63ac81b59f443c45d00abb50546 to your computer and use it in GitHub Desktop.
Save ErikGMatos/69a2b63ac81b59f443c45d00abb50546 to your computer and use it in GitHub Desktop.
import React, { useEffect, useState, useRef } from 'react';
import { createPortal } from 'react-dom';
import PropTypes from 'prop-types';
import usePortal from '~/components/Portal';
import {
ModalCrm,
Overlay,
ButtonClose,
ModalWrap,
ModalWrapDad,
Header,
Title,
} from './styles';
export default function Modal({
id,
children,
handleClose,
closeOverlay,
hasCloseButton,
title,
icon: IconHeader,
maxHeight,
open,
successCallback,
errorCallback,
closeCallbackType,
setCloseCallbackType,
...rest
}) {
const containerId = id || 'AppModal';
const target = usePortal(containerId);
const [animation, setAnimation] = useState(false);
const [isOpenModal, setIsOpenModal] = useState(false);
const [shouldRender, setShouldRender] = useState(false);
const [close, setClose] = useState(false);
const modalRef = useRef(null);
useEffect(() => {
if (!closeCallbackType) return;
setClose(true);
setCloseCallbackType(false);
setTimeout(
() =>
({
error: errorCallback,
success: successCallback,
close: handleClose,
}[closeCallbackType]()),
200
);
}, [
setCloseCallbackType,
closeCallbackType,
errorCallback,
successCallback,
handleClose,
]);
useEffect(() => {
if (close) {
setAnimation(false);
setIsOpenModal(false);
document.body.style.overflow = '';
return;
}
document.body.style.overflow = 'hidden';
setTimeout(() => {
if (!modalRef.current) return;
setShouldRender(true);
setIsOpenModal(true);
setAnimation(true);
}, 50);
}, [close]);
function closeModal() {
setClose(true);
setCloseCallbackType(false);
setTimeout(() => {
handleClose();
}, 200);
}
return createPortal(
<>
<ModalWrapDad isOpen={isOpenModal}>
<ModalWrap isOpen={isOpenModal}>
<Overlay
isOpen={isOpenModal}
animation={animation}
onClick={closeOverlay ? closeModal : null}
/>
<ModalCrm
ref={modalRef}
isOpen={isOpenModal}
animation={animation}
maxHeight={maxHeight}
{...rest}
>
{hasCloseButton && <ButtonClose onClick={closeModal} />}
{title || IconHeader ? (
<Header>
{IconHeader && (
<IconHeader
style={{ width: '64px', margin: '0 auto 16px' }}
/>
)}
{title && <Title>{title}</Title>}
</Header>
) : null}
{shouldRender && children}
</ModalCrm>
</ModalWrap>
</ModalWrapDad>
</>,
target
);
}
Modal.propTypes = {
children: PropTypes.oneOfType([PropTypes.element, PropTypes.array]),
handleClose: PropTypes.func,
closeOverlay: PropTypes.bool,
hasCloseButton: PropTypes.bool,
title: PropTypes.string,
icon: PropTypes.oneOfType([
PropTypes.func,
PropTypes.object,
PropTypes.string,
]),
maxHeight: PropTypes.string,
closeCallbackType: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
setCloseCallbackType: PropTypes.func,
};
Modal.defaultProps = {
children: null,
handleClose: () => null,
closeOverlay: true,
hasCloseButton: true,
title: '',
icon: null,
maxHeight: '98%',
closeCallbackType: false,
setCloseCallbackType: () => null,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment