139 lines
3.9 KiB
TypeScript
139 lines
3.9 KiB
TypeScript
import React, { memo, useMemo } from 'react';
|
|
import classNames from 'classnames';
|
|
import ClearIcon from '@material-ui/icons/Clear';
|
|
import ButtonBase from '@material-ui/core/ButtonBase';
|
|
import Dialog from '@material-ui/core/Dialog';
|
|
import Button from '@material-ui/core/Button';
|
|
import Loading from '@Components/Base/Loading';
|
|
import Styles from './index.module.css';
|
|
import { ModalProps } from './types';
|
|
|
|
function Modal(props: ModalProps): React.ReactElement {
|
|
/* Global & Local States */
|
|
const {
|
|
open,
|
|
onClose,
|
|
onConfirm,
|
|
typeSize,
|
|
typeIsLoading,
|
|
disableEscapeKeyDown,
|
|
disableBackdropClick,
|
|
disableCancelButton,
|
|
disableConfirmButton,
|
|
confirmButtonText,
|
|
cancelButtonText,
|
|
tipsText,
|
|
children,
|
|
className,
|
|
mainName,
|
|
titleClassName,
|
|
actionClassName,
|
|
title,
|
|
closeIcon = true,
|
|
disabledConfirm,
|
|
} = props;
|
|
/* Views */
|
|
const RenderSize = useMemo(() => {
|
|
switch (typeSize) {
|
|
case 'xs':
|
|
return 'xs';
|
|
case 'sm':
|
|
return 'sm';
|
|
case 'md':
|
|
return 'md';
|
|
case 'lg':
|
|
return 'lg';
|
|
case 'xl':
|
|
return 'xl';
|
|
default:
|
|
return 'sm';
|
|
}
|
|
}, [typeSize]);
|
|
const RenderCloseIcon = useMemo<React.ReactElement>(() => {
|
|
if (closeIcon) {
|
|
return (
|
|
<ButtonBase className={classNames(Styles.modalContainerRemoveIcon)} onClick={onClose}>
|
|
<ClearIcon className={classNames(Styles.modalContainerRemoveIconStyle)} fontSize="small" />
|
|
</ButtonBase>
|
|
);
|
|
}
|
|
return <></>;
|
|
}, [open, closeIcon, onClose]);
|
|
const RenderTitle = useMemo<React.ReactElement>(() => {
|
|
if (title) {
|
|
return <div className={classNames(Styles.modalContainerTitle, titleClassName)}>{title}</div>;
|
|
}
|
|
return <></>;
|
|
}, [title]);
|
|
const RenderIsLoading = useMemo<React.ReactElement>(
|
|
() => <Loading typePosition="relative" typeZIndex={10003} typeIcon="line:relative" isLoading={typeIsLoading} />,
|
|
[typeIsLoading],
|
|
);
|
|
const RenderCancelButton = useMemo<React.ReactElement>(() => {
|
|
if (!disableCancelButton) {
|
|
return (
|
|
<Button className={classNames(Styles.modalContainerActionStyle)} color="default" onClick={onClose}>
|
|
{!cancelButtonText ? '取消' : cancelButtonText}
|
|
</Button>
|
|
);
|
|
}
|
|
return <></>;
|
|
}, [disableCancelButton, cancelButtonText, onClose]);
|
|
const RenderConfirmButton = useMemo<React.ReactElement>(() => {
|
|
if (!disableConfirmButton) {
|
|
return (
|
|
<Button
|
|
className={classNames(Styles.modalContainerActionStyle)}
|
|
color="primary"
|
|
variant="contained"
|
|
onClick={onConfirm}
|
|
disabled={disabledConfirm}
|
|
>
|
|
{!confirmButtonText ? '確定' : confirmButtonText}
|
|
</Button>
|
|
);
|
|
}
|
|
return <></>;
|
|
}, [disableConfirmButton, confirmButtonText, onConfirm]);
|
|
const RenderTipsText = useMemo(() => {
|
|
if (tipsText) {
|
|
return tipsText;
|
|
}
|
|
return <></>;
|
|
}, [tipsText]);
|
|
/* Main */
|
|
return (
|
|
<Dialog
|
|
className={classNames(Styles.modalContainer, mainName)}
|
|
open={open}
|
|
onClose={onClose}
|
|
fullWidth
|
|
maxWidth={RenderSize}
|
|
disableEnforceFocus
|
|
disableEscapeKeyDown={disableEscapeKeyDown}
|
|
disableBackdropClick={disableBackdropClick}
|
|
>
|
|
<div className={classNames(className)}>
|
|
{RenderCloseIcon}
|
|
{RenderTitle}
|
|
<div className={classNames(Styles.modalContainerContent)} style={{ marginTop: title ? '18px' : '0px' }}>
|
|
{children}
|
|
</div>
|
|
<div
|
|
className={classNames(
|
|
(!disableCancelButton || !disableConfirmButton) && Styles.modalContainerAction,
|
|
actionClassName,
|
|
)}
|
|
>
|
|
{RenderTipsText}
|
|
{RenderCancelButton}
|
|
{RenderConfirmButton}
|
|
</div>
|
|
{RenderIsLoading}
|
|
</div>
|
|
</Dialog>
|
|
);
|
|
}
|
|
|
|
export default memo(Modal);
|