2023-12-13 14:32:57 +03:00
|
|
|
'use client';
|
|
|
|
|
2023-12-15 17:34:50 +03:00
|
|
|
import clsx from 'clsx';
|
2023-12-25 16:53:27 +03:00
|
|
|
import { motion } from 'framer-motion';
|
2023-07-25 20:27:29 +03:00
|
|
|
import { useRef } from 'react';
|
2023-12-16 19:20:26 +03:00
|
|
|
import { BiX } from 'react-icons/bi';
|
2023-07-25 20:27:29 +03:00
|
|
|
|
2023-12-13 14:32:57 +03:00
|
|
|
import useEscapeKey from '@/hooks/useEscapeKey';
|
2023-12-25 16:53:27 +03:00
|
|
|
import { animateModal } from '@/utils/animations';
|
2023-12-13 14:32:57 +03:00
|
|
|
|
2023-12-18 19:42:27 +03:00
|
|
|
import { CProps } from '../props';
|
2023-07-25 20:27:29 +03:00
|
|
|
import Button from './Button';
|
2023-12-04 14:19:54 +03:00
|
|
|
import MiniButton from './MiniButton';
|
2023-12-05 01:22:44 +03:00
|
|
|
import Overlay from './Overlay';
|
2023-07-22 12:24:14 +03:00
|
|
|
|
2023-12-18 19:42:27 +03:00
|
|
|
export interface ModalProps
|
|
|
|
extends CProps.Styling {
|
|
|
|
header?: string
|
2023-07-22 12:24:14 +03:00
|
|
|
submitText?: string
|
2023-08-23 01:36:17 +03:00
|
|
|
submitInvalidTooltip?: string
|
2023-12-18 19:42:27 +03:00
|
|
|
|
2023-08-08 23:04:21 +03:00
|
|
|
readonly?: boolean
|
2023-07-29 03:31:21 +03:00
|
|
|
canSubmit?: boolean
|
2023-12-18 19:42:27 +03:00
|
|
|
|
2023-07-25 22:29:33 +03:00
|
|
|
hideWindow: () => void
|
2023-08-08 23:04:21 +03:00
|
|
|
onSubmit?: () => void
|
2023-07-22 12:24:14 +03:00
|
|
|
onCancel?: () => void
|
2023-12-18 19:42:27 +03:00
|
|
|
|
2023-07-22 12:24:14 +03:00
|
|
|
children: React.ReactNode
|
|
|
|
}
|
|
|
|
|
2023-08-23 01:36:17 +03:00
|
|
|
function Modal({
|
2023-12-18 19:42:27 +03:00
|
|
|
header, hideWindow, onSubmit,
|
2023-08-23 01:36:17 +03:00
|
|
|
readonly, onCancel, canSubmit,
|
2023-12-07 01:21:27 +03:00
|
|
|
submitInvalidTooltip, className,
|
2023-08-23 01:36:17 +03:00
|
|
|
children,
|
2023-12-18 19:42:27 +03:00
|
|
|
submitText = 'Продолжить',
|
|
|
|
...restProps
|
2023-08-23 01:36:17 +03:00
|
|
|
}: ModalProps) {
|
2023-07-22 12:24:14 +03:00
|
|
|
const ref = useRef(null);
|
2023-07-25 22:29:33 +03:00
|
|
|
useEscapeKey(hideWindow);
|
2023-07-22 12:24:14 +03:00
|
|
|
|
|
|
|
const handleCancel = () => {
|
2023-07-25 22:29:33 +03:00
|
|
|
hideWindow();
|
2023-07-25 20:27:29 +03:00
|
|
|
if (onCancel) onCancel();
|
2023-07-22 12:24:14 +03:00
|
|
|
};
|
|
|
|
|
2023-07-23 15:23:01 +03:00
|
|
|
const handleSubmit = () => {
|
2023-07-25 22:29:33 +03:00
|
|
|
hideWindow();
|
2023-08-08 23:04:21 +03:00
|
|
|
if (onSubmit) onSubmit();
|
2023-07-23 15:23:01 +03:00
|
|
|
};
|
|
|
|
|
2023-12-04 14:19:54 +03:00
|
|
|
return (
|
|
|
|
<>
|
2023-12-15 17:34:50 +03:00
|
|
|
<div className={clsx(
|
|
|
|
'z-navigation',
|
|
|
|
'fixed top-0 left-0',
|
|
|
|
'w-full h-full',
|
|
|
|
'clr-modal-backdrop'
|
|
|
|
)}/>
|
2023-12-25 16:53:27 +03:00
|
|
|
<motion.div ref={ref}
|
2023-12-15 17:34:50 +03:00
|
|
|
className={clsx(
|
|
|
|
'z-modal',
|
|
|
|
'fixed bottom-1/2 left-1/2 -translate-x-1/2 translate-y-1/2',
|
|
|
|
'border shadow-md',
|
|
|
|
'clr-app'
|
|
|
|
)}
|
2023-12-25 16:53:27 +03:00
|
|
|
initial={{...animateModal.initial}}
|
|
|
|
animate={{...animateModal.animate}}
|
|
|
|
exit={{...animateModal.exit}}
|
2023-12-18 19:42:27 +03:00
|
|
|
{...restProps}
|
2023-08-08 23:04:21 +03:00
|
|
|
>
|
2023-12-17 20:19:28 +03:00
|
|
|
<Overlay position='right-[0.3rem] top-2'>
|
2023-12-04 14:19:54 +03:00
|
|
|
<MiniButton
|
2023-12-18 19:42:27 +03:00
|
|
|
title='Закрыть диалоговое окно [ESC]'
|
2023-12-16 19:20:26 +03:00
|
|
|
icon={<BiX size='1.25rem'/>}
|
2023-12-04 14:19:54 +03:00
|
|
|
onClick={handleCancel}
|
|
|
|
/>
|
2023-12-05 01:22:44 +03:00
|
|
|
</Overlay>
|
2023-12-04 14:19:54 +03:00
|
|
|
|
2023-12-18 19:42:27 +03:00
|
|
|
{header ? <h1 className='px-12 py-2 select-none'>{header}</h1> : null}
|
2023-12-04 14:19:54 +03:00
|
|
|
|
2023-12-07 01:21:27 +03:00
|
|
|
<div
|
2023-12-15 17:34:50 +03:00
|
|
|
className={clsx(
|
|
|
|
'overflow-auto',
|
|
|
|
className
|
|
|
|
)}
|
2023-12-07 01:21:27 +03:00
|
|
|
style={{
|
|
|
|
maxHeight: 'calc(100vh - 8rem)',
|
|
|
|
maxWidth: 'calc(100vw - 2rem)',
|
|
|
|
}}
|
|
|
|
>
|
2023-07-22 12:24:14 +03:00
|
|
|
{children}
|
|
|
|
</div>
|
2023-12-04 14:19:54 +03:00
|
|
|
|
2023-12-15 17:34:50 +03:00
|
|
|
<div className={clsx(
|
|
|
|
'z-modal-controls',
|
|
|
|
'px-6 py-3 flex gap-12 justify-center'
|
|
|
|
)}>
|
2023-11-27 11:33:34 +03:00
|
|
|
{!readonly ?
|
|
|
|
<Button autoFocus
|
2023-07-22 12:24:14 +03:00
|
|
|
text={submitText}
|
2023-12-18 19:42:27 +03:00
|
|
|
title={!canSubmit ? submitInvalidTooltip: ''}
|
2023-12-18 12:25:39 +03:00
|
|
|
className='min-w-[8rem] min-h-[2.6rem]'
|
2023-11-05 16:31:49 +03:00
|
|
|
colors='clr-btn-primary'
|
2023-07-22 12:24:14 +03:00
|
|
|
disabled={!canSubmit}
|
2023-07-23 15:23:01 +03:00
|
|
|
onClick={handleSubmit}
|
2023-11-27 11:33:34 +03:00
|
|
|
/> : null}
|
2023-07-25 20:27:29 +03:00
|
|
|
<Button
|
2023-08-08 23:04:21 +03:00
|
|
|
text={readonly ? 'Закрыть' : 'Отмена'}
|
2023-12-18 12:25:39 +03:00
|
|
|
className='min-w-[8rem] min-h-[2.6rem]'
|
2023-07-22 12:24:14 +03:00
|
|
|
onClick={handleCancel}
|
|
|
|
/>
|
|
|
|
</div>
|
2023-12-25 16:53:27 +03:00
|
|
|
</motion.div>
|
2023-12-02 00:15:56 +03:00
|
|
|
</>);
|
2023-07-22 12:24:14 +03:00
|
|
|
}
|
|
|
|
|
2023-12-15 17:34:50 +03:00
|
|
|
export default Modal;
|