import React from 'react'; import { Dialog as HDialog } from '@headlessui/react'; import { Button } from '@/components/elements/button/index'; import { XIcon } from '@heroicons/react/solid'; import DialogIcon from '@/components/elements/dialog/DialogIcon'; import { AnimatePresence, motion } from 'framer-motion'; import classNames from 'classnames'; import ConfirmationDialog from '@/components/elements/dialog/ConfirmationDialog'; export interface DialogProps { open: boolean; onClose: () => void; hideCloseIcon?: boolean; title?: string; description?: string | undefined; children?: React.ReactNode; } const DialogButtons = ({ children }: { children: React.ReactNode }) => <>{children}</>; const Dialog = ({ open, title, description, onClose, hideCloseIcon, children }: DialogProps) => { const items = React.Children.toArray(children || []); const [buttons, icon, content] = [ // @ts-expect-error not sure how to get this correct items.find((child) => child.type === DialogButtons), // @ts-expect-error not sure how to get this correct items.find((child) => child.type === DialogIcon), // @ts-expect-error not sure how to get this correct items.filter((child) => ![DialogIcon, DialogButtons].includes(child.type)), ]; return ( <AnimatePresence> {open && ( <HDialog static as={motion.div} initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.15 }} open={open} onClose={onClose} > <div className={'fixed inset-0 bg-gray-900/50 z-40'} /> <div className={'fixed inset-0 overflow-y-auto z-50'}> <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', ])} > <div className={'flex p-6 overflow-y-auto'}> {icon && <div className={'mr-4'}>{icon}</div>} <div className={'flex-1 max-h-[70vh]'}> {title && ( <HDialog.Title className={'font-header text-xl font-medium mb-2 text-gray-50 pr-4'} > {title} </HDialog.Title> )} {description && <HDialog.Description>{description}</HDialog.Description>} {content} </div> </div> {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'}> <Button.Text size={Button.Sizes.Small} shape={Button.Shapes.IconSquare} onClick={onClose} className={'hover:rotate-90'} > <XIcon className={'w-5 h-5'} /> </Button.Text> </div> )} </HDialog.Panel> </div> </div> </HDialog> )} </AnimatePresence> ); }; const _Dialog = Object.assign(Dialog, { Confirm: ConfirmationDialog, Buttons: DialogButtons, Icon: DialogIcon, }); export default _Dialog;