Path: blob/1.0-develop/resources/scripts/components/elements/dialog/Dialog.tsx
10260 views
import React, { useRef, useState } from 'react';1import { Dialog as HDialog } from '@headlessui/react';2import { Button } from '@/components/elements/button/index';3import { XIcon } from '@heroicons/react/solid';4import { AnimatePresence, motion } from 'framer-motion';5import { DialogContext, IconPosition, RenderDialogProps, styles } from './';67const variants = {8open: {9scale: 1,10opacity: 1,11transition: {12type: 'spring',13damping: 15,14stiffness: 300,15duration: 0.15,16},17},18closed: {19scale: 0.75,20opacity: 0,21transition: {22type: 'easeIn',23duration: 0.15,24},25},26bounce: {27scale: 0.95,28opacity: 1,29transition: { type: 'linear', duration: 0.075 },30},31};3233export default ({34open,35title,36description,37onClose,38hideCloseIcon,39preventExternalClose,40children,41}: RenderDialogProps) => {42const container = useRef<HTMLDivElement>(null);43const [icon, setIcon] = useState<React.ReactNode>();44const [footer, setFooter] = useState<React.ReactNode>();45const [iconPosition, setIconPosition] = useState<IconPosition>('title');46const [down, setDown] = useState(false);4748const onContainerClick = (down: boolean, e: React.MouseEvent<HTMLDivElement>): void => {49if (e.target instanceof HTMLElement && container.current?.isSameNode(e.target)) {50setDown(down);51}52};5354const onDialogClose = (): void => {55if (!preventExternalClose) {56return onClose();57}58};5960return (61<AnimatePresence>62{open && (63<DialogContext.Provider value={{ setIcon, setFooter, setIconPosition }}>64<HDialog65static66as={motion.div}67initial={{ opacity: 0 }}68animate={{ opacity: 1 }}69exit={{ opacity: 0 }}70transition={{ duration: 0.15 }}71open={open}72onClose={onDialogClose}73>74<div className={'fixed inset-0 bg-gray-900/50 z-40'} />75<div className={'fixed inset-0 overflow-y-auto z-50'}>76<div77ref={container}78className={styles.container}79onMouseDown={onContainerClick.bind(this, true)}80onMouseUp={onContainerClick.bind(this, false)}81>82<HDialog.Panel83as={motion.div}84initial={'closed'}85animate={down ? 'bounce' : 'open'}86exit={'closed'}87variants={variants}88className={styles.panel}89>90<div className={'flex p-6 pb-0 overflow-y-auto'}>91{iconPosition === 'container' && icon}92<div className={'flex-1 max-h-[70vh] min-w-0'}>93<div className={'flex items-center'}>94{iconPosition !== 'container' && icon}95<div>96{title && (97<HDialog.Title className={styles.title}>{title}</HDialog.Title>98)}99{description && (100<HDialog.Description>{description}</HDialog.Description>101)}102</div>103</div>104{children}105<div className={'invisible h-6'} />106</div>107</div>108{footer}109{/* Keep this below the other buttons so that it isn't the default focus if they're present. */}110{!hideCloseIcon && (111<div className={'absolute right-0 top-0 m-4'}>112<Button.Text113size={Button.Sizes.Small}114shape={Button.Shapes.IconSquare}115onClick={onClose}116className={'group'}117>118<XIcon className={styles.close_icon} />119</Button.Text>120</div>121)}122</HDialog.Panel>123</div>124</div>125</HDialog>126</DialogContext.Provider>127)}128</AnimatePresence>129);130};131132133