import React, { useEffect, useCallback } from 'react'; import { createPortal } from 'react-dom'; import { Close } from '@lunit/design-system-icons'; import { DialogAction } from './components/DialogAction'; import { StyledBackdrop, StyledDialog, StyledDialogContent, StyledDialogTitle, StyledDialogTitleIconWrapper, } from './Dialog.styled'; import Button from '../Button'; import Typography from '../Typography'; import type { SxProps } from '@mui/material/styles'; import type { TypographyProps } from '@mui/material'; export interface DialogBaseProps { isOpen: boolean; onClose(): void; type?: 'passive' | 'action'; // default passive nonModal?: boolean; // default false title: string; titleIcon?: React.ReactNode; titleVariant?: TypographyProps['variant']; children: React.ReactNode; actions?: React.ReactNode; enableBackdropClose?: boolean; size?: 'small' | 'medium'; // default "small" sx?: SxProps; style?: React.CSSProperties; className?: string; } export interface PassiveDialogType extends DialogBaseProps { type: 'passive'; actions?: undefined; enableBackdropClose?: true; } export interface ActionDialogType extends DialogBaseProps { type: 'action'; actions: React.ReactNode; enableBackdropClose?: boolean; } export interface PassiveModalProps extends PassiveDialogType { nonModal?: false; } export interface ActionModalProps extends ActionDialogType { nonModal?: false; } export type ModalProps = PassiveModalProps | ActionModalProps; export interface PassiveNonModalProps extends PassiveDialogType { nonModal?: true; } export interface ActionNonModalProps extends ActionDialogType { nonModal?: true; enableBackdropClose?: false; } export type NonModalProps = PassiveNonModalProps | ActionNonModalProps; export type DialogProps = ModalProps | NonModalProps; function Dialog(props: DialogProps) { const { isOpen, type, nonModal = false, onClose } = props; const isActionModal = type === 'action' && !nonModal; const isPassiveModal = type === 'passive' && !nonModal; const handleBackdropClose = useCallback( (e: React.MouseEvent) => { const isClosable = isPassiveModal || (isActionModal && props.enableBackdropClose); if (!isClosable) return; if (e.target !== e.currentTarget) return; onClose(); }, [isPassiveModal, isActionModal, props.enableBackdropClose, onClose], ); useEffect(() => { const isClosable = isOpen && isPassiveModal; if (!isClosable) return; function handleEscClose(event: KeyboardEvent) { if (event.key === 'Escape') onClose(); } document.addEventListener('keydown', handleEscClose); return () => { document.removeEventListener('keydown', handleEscClose); }; }, [isOpen, isPassiveModal, onClose]); if (!isOpen) return null; return createPortal( nonModal ? ( ) : ( ), document.body, ); } function DialogBase({ dialogProps }: { dialogProps: DialogBaseProps }) { const { nonModal = false, onClose, title, titleIcon, titleVariant = 'headline5', children, actions, type, size = 'small', sx, style, className, } = dialogProps; return ( {titleIcon && ( {titleIcon} )} {title} {type === 'passive' && (