2022-06-12 19:07:52 +00:00
|
|
|
import React from 'react';
|
|
|
|
import { Dialog as HDialog } from '@headlessui/react';
|
2022-06-05 18:56:42 +00:00
|
|
|
import { Button } from '@/components/elements/button/index';
|
|
|
|
import { XIcon } from '@heroicons/react/solid';
|
2022-06-12 19:07:52 +00:00
|
|
|
import DialogIcon from '@/components/elements/dialog/DialogIcon';
|
|
|
|
import { AnimatePresence, motion } from 'framer-motion';
|
2022-06-05 18:56:42 +00:00
|
|
|
import classNames from 'classnames';
|
2022-06-20 15:17:33 +00:00
|
|
|
import ConfirmationDialog from '@/components/elements/dialog/ConfirmationDialog';
|
2022-06-05 18:56:42 +00:00
|
|
|
|
2022-06-20 15:17:33 +00:00
|
|
|
export interface DialogProps {
|
2022-06-12 19:07:52 +00:00
|
|
|
open: boolean;
|
|
|
|
onClose: () => void;
|
|
|
|
hideCloseIcon?: boolean;
|
2022-06-05 18:56:42 +00:00
|
|
|
title?: string;
|
2022-06-20 15:17:33 +00:00
|
|
|
description?: string | undefined;
|
2022-06-05 18:56:42 +00:00
|
|
|
children?: React.ReactNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
const DialogButtons = ({ children }: { children: React.ReactNode }) => (
|
|
|
|
<>{children}</>
|
|
|
|
);
|
|
|
|
|
2022-06-20 15:17:33 +00:00
|
|
|
const Dialog = ({ open, title, description, onClose, hideCloseIcon, children }: DialogProps) => {
|
2022-06-05 18:56:42 +00:00
|
|
|
const items = React.Children.toArray(children || []);
|
|
|
|
const [ buttons, icon, content ] = [
|
|
|
|
// @ts-expect-error
|
|
|
|
items.find(child => child.type === DialogButtons),
|
|
|
|
// @ts-expect-error
|
|
|
|
items.find(child => child.type === DialogIcon),
|
|
|
|
// @ts-expect-error
|
|
|
|
items.filter(child => ![ DialogIcon, DialogButtons ].includes(child.type)),
|
|
|
|
];
|
|
|
|
|
|
|
|
return (
|
2022-06-12 19:07:52 +00:00
|
|
|
<AnimatePresence>
|
|
|
|
{open && (
|
|
|
|
<HDialog
|
|
|
|
static
|
|
|
|
as={motion.div}
|
|
|
|
initial={{ opacity: 0 }}
|
|
|
|
animate={{ opacity: 1 }}
|
|
|
|
exit={{ opacity: 0 }}
|
|
|
|
transition={{ duration: 0.15 }}
|
|
|
|
open={open}
|
|
|
|
onClose={onClose}
|
|
|
|
>
|
2022-06-20 18:16:42 +00:00
|
|
|
<div className={'fixed inset-0 bg-gray-900/50 z-40'}/>
|
|
|
|
<div className={'fixed inset-0 overflow-y-auto z-50'}>
|
2022-06-12 19:07:52 +00:00
|
|
|
<div className={'flex min-h-full items-center justify-center p-4 text-center'}>
|
|
|
|
<HDialog.Panel
|
|
|
|
as={motion.div}
|
|
|
|
initial={{ opacity: 0, scale: 0.85 }}
|
|
|
|
animate={{ opacity: 1, scale: 1 }}
|
|
|
|
exit={{ opacity: 0 }}
|
|
|
|
transition={{ type: 'spring', damping: 15, stiffness: 300, duration: 0.15 }}
|
|
|
|
className={classNames([
|
|
|
|
'relative bg-gray-600 rounded max-w-xl w-full mx-auto shadow-lg text-left',
|
|
|
|
'ring-4 ring-gray-800 ring-opacity-80',
|
|
|
|
])}
|
|
|
|
>
|
2022-06-20 18:16:42 +00:00
|
|
|
<div className={'flex p-6 overflow-y-auto'}>
|
2022-06-12 19:07:52 +00:00
|
|
|
{icon && <div className={'mr-4'}>{icon}</div>}
|
2022-06-20 15:17:33 +00:00
|
|
|
<div className={'flex-1 max-h-[70vh]'}>
|
2022-06-12 19:07:52 +00:00
|
|
|
{title &&
|
2022-06-20 15:17:33 +00:00
|
|
|
<HDialog.Title className={'font-header text-xl font-medium mb-2 text-gray-50 pr-4'}>
|
2022-06-12 19:07:52 +00:00
|
|
|
{title}
|
|
|
|
</HDialog.Title>
|
|
|
|
}
|
|
|
|
{description && <HDialog.Description>{description}</HDialog.Description>}
|
2022-06-05 18:56:42 +00:00
|
|
|
{content}
|
2022-06-12 19:07:52 +00:00
|
|
|
</div>
|
2022-06-05 18:56:42 +00:00
|
|
|
</div>
|
2022-06-12 19:07:52 +00:00
|
|
|
{buttons &&
|
|
|
|
<div className={'px-6 py-3 bg-gray-700 flex items-center justify-end space-x-3 rounded-b'}>
|
|
|
|
{buttons}
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
{/* Keep this below the other buttons so that it isn't the default focus if they're present. */}
|
|
|
|
{!hideCloseIcon &&
|
|
|
|
<div className={'absolute right-0 top-0 m-4'}>
|
2022-06-20 16:38:23 +00:00
|
|
|
<Button.Text
|
|
|
|
size={Button.Sizes.Small}
|
|
|
|
shape={Button.Shapes.IconSquare}
|
|
|
|
onClick={onClose}
|
|
|
|
className={'hover:rotate-90'}
|
|
|
|
>
|
2022-06-12 19:07:52 +00:00
|
|
|
<XIcon className={'w-5 h-5'}/>
|
|
|
|
</Button.Text>
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
</HDialog.Panel>
|
2022-06-05 18:56:42 +00:00
|
|
|
</div>
|
2022-06-12 19:07:52 +00:00
|
|
|
</div>
|
|
|
|
</HDialog>
|
|
|
|
)}
|
|
|
|
</AnimatePresence>
|
2022-06-05 18:56:42 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2022-06-20 15:17:33 +00:00
|
|
|
const _Dialog = Object.assign(Dialog, {
|
|
|
|
Confirm: ConfirmationDialog,
|
|
|
|
Buttons: DialogButtons,
|
|
|
|
Icon: DialogIcon,
|
|
|
|
});
|
2022-06-05 18:56:42 +00:00
|
|
|
|
|
|
|
export default _Dialog;
|