import React, { useRef } from 'react';
import styled from '@emotion/styled';
import { motion } from 'framer-motion';
import {
ClickOutsideMode,
useListenClickOutside,
} from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
const ModalDiv = styled(motion.div)`
display: flex;
flex-direction: column;
background: ${({ theme }) => theme.background.primary};
border-radius: ${({ theme }) => theme.border.radius.md};
overflow: hidden;
max-height: 90vh;
z-index: 10000; // should be higher than Backdrop's z-index
`;
const StyledHeader = styled.div`
align-items: center;
display: flex;
flex-direction: row;
height: 60px;
overflow: hidden;
padding: ${({ theme }) => theme.spacing(5)};
`;
const StyledContent = styled.div`
display: flex;
flex: 1;
flex-direction: column;
overflow-y: auto;
padding: ${({ theme }) => theme.spacing(10)};
`;
const StyledFooter = styled.div`
align-items: center;
display: flex;
flex-direction: row;
height: 60px;
overflow: hidden;
padding: ${({ theme }) => theme.spacing(5)};
`;
const BackDrop = styled(motion.div)`
align-items: center;
background: ${({ theme }) => theme.background.overlay};
display: flex;
height: 100%;
justify-content: center;
left: 0;
position: fixed;
top: 0;
width: 100%;
z-index: 9999;
`;
/**
* Modal components
*/
type ModalHeaderProps = React.PropsWithChildren & React.ComponentProps<'div'>;
function ModalHeader({ children, ...restProps }: ModalHeaderProps) {
return {children};
}
type ModalContentProps = React.PropsWithChildren & React.ComponentProps<'div'>;
function ModalContent({ children, ...restProps }: ModalContentProps) {
return {children};
}
type ModalFooterProps = React.PropsWithChildren & React.ComponentProps<'div'>;
function ModalFooter({ children, ...restProps }: ModalFooterProps) {
return {children};
}
/**
* Modal
*/
type ModalProps = React.PropsWithChildren &
React.ComponentProps<'div'> & {
isOpen?: boolean;
onOutsideClick?: () => void;
};
const modalVariants = {
hidden: { opacity: 0 },
visible: { opacity: 1 },
exit: { opacity: 0 },
};
export function Modal({
isOpen = false,
children,
onOutsideClick,
...restProps
}: ModalProps) {
const modalRef = useRef(null);
useListenClickOutside({
refs: [modalRef],
callback: () => onOutsideClick?.(),
mode: ClickOutsideMode.absolute,
});
if (!isOpen) {
return null;
}
return (
{children}
);
}
Modal.Header = ModalHeader;
Modal.Content = ModalContent;
Modal.Footer = ModalFooter;