import { cloneElement, isValidElement, useEffect, useId, useRef } from 'react' import PropTypes from 'prop-types' import { useTooltipContext } from '../context/TooltipContext' const mergeHandler = (original, next) => (event) => { next(event) original?.(event) } const Tooltip = ({ children, title, content }) => { const { showTooltip, hideTooltip } = useTooltipContext() const id = useId() const tooltipContent = title ?? content const hoveringRef = useRef(false) useEffect(() => { return () => hideTooltip(id) }, [hideTooltip, id]) useEffect(() => { if (hoveringRef.current) { showTooltip(id, tooltipContent) } }, [id, showTooltip, tooltipContent]) const onMouseEnter = (event) => { hoveringRef.current = true showTooltip(id, tooltipContent, event.clientX, event.clientY) } const onMouseLeave = () => { hoveringRef.current = false hideTooltip(id) } if (isValidElement(children)) { const trigger = cloneElement(children, { onMouseEnter: mergeHandler(children.props.onMouseEnter, onMouseEnter), onMouseLeave: mergeHandler(children.props.onMouseLeave, onMouseLeave) }) if (children.props.disabled) { return ( {trigger} ) } return trigger } return ( {children} ) } Tooltip.propTypes = { children: PropTypes.node.isRequired, title: PropTypes.node, content: PropTypes.node } export default Tooltip