| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 | import { Popover, Transition } from '@headlessui/react'import { Fragment, cloneElement, useRef } from 'react'import cn from 'classnames'import s from './style.module.css'export type HtmlContentProps = {  onClose?: () => void  onClick?: () => void}type IPopover = {  className?: string  htmlContent: React.ReactElement<HtmlContentProps>  popupClassName?: string  trigger?: 'click' | 'hover'  position?: 'bottom' | 'br' | 'bl'  btnElement?: string | React.ReactNode  btnClassName?: string | ((open: boolean) => string)  manualClose?: boolean}const timeoutDuration = 100export default function CustomPopover({  trigger = 'hover',  position = 'bottom',  htmlContent,  popupClassName,  btnElement,  className,  btnClassName,  manualClose,}: IPopover) {  const buttonRef = useRef<HTMLButtonElement>(null)  const timeOutRef = useRef<NodeJS.Timeout | null>(null)  const onMouseEnter = (isOpen: boolean) => {    timeOutRef.current && clearTimeout(timeOutRef.current)    !isOpen && buttonRef.current?.click()  }  const onMouseLeave = (isOpen: boolean) => {    timeOutRef.current = setTimeout(() => {      isOpen && buttonRef.current?.click()    }, timeoutDuration)  }  return (    <Popover className="relative">      {({ open }: { open: boolean }) => {        return (          <>            <div              {...(trigger !== 'hover'                ? {}                : {                  onMouseLeave: () => onMouseLeave(open),                  onMouseEnter: () => onMouseEnter(open),                })}            >              <Popover.Button                ref={buttonRef}                className={`group ${s.popupBtn} ${open ? '' : 'bg-gray-100'} ${!btnClassName                  ? ''                  : typeof btnClassName === 'string'                    ? btnClassName                    : btnClassName?.(open)                }`}              >                {btnElement}              </Popover.Button>              <Transition as={Fragment}>                <Popover.Panel                  className={cn(                    s.popupPanel,                    position === 'bottom' && '-translate-x-1/2 left-1/2',                    position === 'bl' && 'left-0',                    position === 'br' && 'right-0',                    className,                  )}                  {...(trigger !== 'hover'                    ? {}                    : {                      onMouseLeave: () => onMouseLeave(open),                      onMouseEnter: () => onMouseEnter(open),                    })                  }                >                  {({ close }) => (                    <div                      className={cn(s.panelContainer, popupClassName)}                      {...(trigger !== 'hover'                        ? {}                        : {                          onMouseLeave: () => onMouseLeave(open),                          onMouseEnter: () => onMouseEnter(open),                        })                      }                    >                      {cloneElement(htmlContent as React.ReactElement<HtmlContentProps>, {                        onClose: () => onMouseLeave(open),                        ...(manualClose                          ? {                            onClick: close,                          }                          : {}),                      })}                    </div>                  )}                </Popover.Panel>              </Transition>            </div>          </>        )      }}    </Popover>  )}
 |