| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | import { Fragment, useCallback } from 'react' | 
					
						
							|  |  |  | import type { ElementType, ReactNode } from 'react' | 
					
						
							| 
									
										
										
										
											2025-03-21 17:41:03 +08:00
										 |  |  | import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from '@headlessui/react' | 
					
						
							| 
									
										
										
										
											2024-07-09 15:05:40 +08:00
										 |  |  | import classNames from '@/utils/classnames' | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // https://headlessui.com/react/dialog
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type DialogProps = { | 
					
						
							|  |  |  |   className?: string | 
					
						
							|  |  |  |   titleClassName?: string | 
					
						
							|  |  |  |   bodyClassName?: string | 
					
						
							|  |  |  |   footerClassName?: string | 
					
						
							|  |  |  |   titleAs?: ElementType | 
					
						
							|  |  |  |   title?: ReactNode | 
					
						
							|  |  |  |   children: ReactNode | 
					
						
							|  |  |  |   footer?: ReactNode | 
					
						
							|  |  |  |   show: boolean | 
					
						
							|  |  |  |   onClose?: () => void | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const CustomDialog = ({ | 
					
						
							|  |  |  |   className, | 
					
						
							|  |  |  |   titleClassName, | 
					
						
							|  |  |  |   bodyClassName, | 
					
						
							|  |  |  |   footerClassName, | 
					
						
							|  |  |  |   titleAs, | 
					
						
							|  |  |  |   title, | 
					
						
							|  |  |  |   children, | 
					
						
							|  |  |  |   footer, | 
					
						
							|  |  |  |   show, | 
					
						
							|  |  |  |   onClose, | 
					
						
							|  |  |  | }: DialogProps) => { | 
					
						
							|  |  |  |   const close = useCallback(() => onClose?.(), [onClose]) | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <Transition appear show={show} as={Fragment}> | 
					
						
							| 
									
										
										
										
											2023-05-20 21:55:47 +08:00
										 |  |  |       <Dialog as="div" className="relative z-40" onClose={close}> | 
					
						
							| 
									
										
										
										
											2025-03-21 17:41:03 +08:00
										 |  |  |         <TransitionChild> | 
					
						
							|  |  |  |           <div className={classNames( | 
					
						
							|  |  |  |             'fixed inset-0 bg-background-overlay-backdrop backdrop-blur-[6px]', | 
					
						
							|  |  |  |             'duration-300 ease-in data-[closed]:opacity-0', | 
					
						
							|  |  |  |             'data-[enter]:opacity-100', | 
					
						
							|  |  |  |             'data-[leave]:opacity-0', | 
					
						
							|  |  |  |           )} /> | 
					
						
							|  |  |  |         </TransitionChild> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         <div className="fixed inset-0 overflow-y-auto"> | 
					
						
							| 
									
										
										
										
											2025-03-21 17:41:03 +08:00
										 |  |  |           <div className="flex min-h-full items-center justify-center"> | 
					
						
							|  |  |  |             <TransitionChild> | 
					
						
							|  |  |  |               <DialogPanel className={classNames( | 
					
						
							|  |  |  |                 'w-full max-w-[800px] p-6 overflow-hidden transition-all transform bg-components-panel-bg border-[0.5px] border-components-panel-border shadow-xl rounded-2xl', | 
					
						
							|  |  |  |                 'duration-100 ease-in data-[closed]:opacity-0 data-[closed]:scale-95', | 
					
						
							|  |  |  |                 'data-[enter]:opacity-100 data-[enter]:scale-100', | 
					
						
							|  |  |  |                 'data-[leave]:opacity-0 data-[enter]:scale-95', | 
					
						
							|  |  |  |                 className, | 
					
						
							|  |  |  |               )}> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |                 {Boolean(title) && ( | 
					
						
							| 
									
										
										
										
											2025-03-21 17:41:03 +08:00
										 |  |  |                   <DialogTitle | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |                     as={titleAs || 'h3'} | 
					
						
							| 
									
										
										
										
											2024-12-30 13:39:26 +08:00
										 |  |  |                     className={classNames('pr-8 pb-3 title-2xl-semi-bold text-text-primary', titleClassName)} | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |                   > | 
					
						
							|  |  |  |                     {title} | 
					
						
							| 
									
										
										
										
											2025-03-21 17:41:03 +08:00
										 |  |  |                   </DialogTitle> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |                 )} | 
					
						
							| 
									
										
										
										
											2024-12-30 13:39:26 +08:00
										 |  |  |                 <div className={classNames(bodyClassName)}> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |                   {children} | 
					
						
							|  |  |  |                 </div> | 
					
						
							|  |  |  |                 {Boolean(footer) && ( | 
					
						
							| 
									
										
										
										
											2024-12-30 13:39:26 +08:00
										 |  |  |                   <div className={classNames('flex items-center justify-end gap-2 px-6 pb-6 pt-3', footerClassName)}> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |                     {footer} | 
					
						
							|  |  |  |                   </div> | 
					
						
							|  |  |  |                 )} | 
					
						
							| 
									
										
										
										
											2025-03-21 17:41:03 +08:00
										 |  |  |               </DialogPanel> | 
					
						
							|  |  |  |             </TransitionChild> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |           </div> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       </Dialog> | 
					
						
							|  |  |  |     </Transition > | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default CustomDialog |