import { MouseEvent, useEffect, useRef, useState, useCallback } from 'react'; import { useTheme } from '@cleartrip/ct-design-theme'; import { Container } from '@cleartrip/ct-design-container'; import Conditional from '@cleartrip/ct-design-conditional-wrap'; import { ITooltipProps, TooltipStyles, TooltipArrowStyles } from './type'; import { overlayBorderRadius, positions } from './constants'; import { staticTooltipStyles } from './style'; import TooltipContainer from './TooltipContainer'; import TooltipArrow from './TooltipArrow'; import { Transition } from '@cleartrip/ct-design-transition'; import { TooltipChevronDown } from '@cleartrip/ct-design-icons'; import { useStyles, useWebMergeStyles } from '@cleartrip/ct-design-style-manager'; import { isEmpty } from '@cleartrip/ct-design-common-utils'; import { getTooltipStyles, getTooltipArrowStyles } from './webStyle'; const Tooltip: React.FC = ({ children, position = positions.RIGHT, labelContainer, tooltipWidth = 150, tooltipBorderRadius = overlayBorderRadius.MD, styleConfig, enableTooltipContainerHovering = false, open = false, animate = true, svgPathProps, anchorRef, }) => { const theme = useTheme(); const { root: customRootStyles = [], labelContainerStyles: customLabelContainerStyles = [], overlayStyles: customOverlayStyles = [], arrowStyles: customArrowStyles = [], } = styleConfig || {}; const [styles, setStyles] = useState<{ tooltipStyles: TooltipStyles; tooltipArrowStyles: TooltipArrowStyles }>({ tooltipStyles: {}, tooltipArrowStyles: {}, }); const labelRef = useRef(null); const tooltipRef = useRef(null); const setTooltipStyles = useCallback(() => { const tooltipStyle = getTooltipStyles({ borderSize: tooltipBorderRadius, position, labelRef, tooltipRef, anchorRef: anchorRef as React.RefObject, theme, }); const tooltipArrowStyle = getTooltipArrowStyles({ position, labelRef, tooltipRef, anchorRef: anchorRef as React.RefObject, theme, }); setStyles({ tooltipStyles: tooltipStyle, tooltipArrowStyles: tooltipArrowStyle }); }, [tooltipBorderRadius, position, labelRef, tooltipRef, anchorRef, theme]); useEffect(() => { if (open) { setTooltipStyles(); } else { setStyles({ tooltipStyles: {}, tooltipArrowStyles: {} }); } }, [open, setTooltipStyles]); const canCloseTooltipContainer = (event: MouseEvent) => { const defaultDimesstions = { right: 0, left: 0, bottom: 0, top: 0 }; const tooltipDimesntions = tooltipRef.current?.getBoundingClientRect() ?? defaultDimesstions; const labelDimensions = labelRef.current?.getBoundingClientRect() ?? defaultDimesstions; const { r, l, b, t } = { r: Math.floor(Math.max(tooltipDimesntions.right, labelDimensions.left)), l: Math.floor(Math.min(tooltipDimesntions.left, labelDimensions.right)), b: Math.floor(Math.max(tooltipDimesntions.bottom, labelDimensions.top)), t: Math.floor(Math.min(tooltipDimesntions.top, labelDimensions.bottom)), }; const currentX = event.clientX + 1; const currentY = event.clientY + 1; return r >= currentX && l <= currentX && t <= currentY && b >= currentY; }; const handleMouseEnter = () => { setTooltipStyles(); }; const handleMouseLeave = (event: MouseEvent) => { if (enableTooltipContainerHovering && canCloseTooltipContainer(event)) return; setStyles({ tooltipStyles: {}, tooltipArrowStyles: {} }); }; const labelStyles = useWebMergeStyles([...customLabelContainerStyles], [customLabelContainerStyles]); const dynamicTooltipStyles = useStyles(() => { return { tooltip: styles.tooltipStyles, tooltipArrow: styles.tooltipArrowStyles, }; }, [styles.tooltipStyles, open]); return (
{labelContainer}
{!!children && ( {child}}> <> {children} )}
); }; export default Tooltip;