import React, { MutableRefObject, useEffect, useMemo, useRef, useState } from 'react' import { createPortal } from 'react-dom' import useTheme from '../styles/use-theme' import usePortal from '../utils/use-portal' import useResize from '../utils/use-resize' import CSSTransition from '../shared/css-transition' import useClickAnyWhere from '../utils/use-click-anywhere' import { getColors } from './styles' import { getPosition, TooltipPosition, defaultTooltipPosition } from './placement' import TooltipIcon from './tooltip-icon' import { Placement, SnippetTypes } from '../utils/prop-types' interface Props { parent?: MutableRefObject | undefined placement: Placement type: SnippetTypes visible: boolean hideArrow: boolean offset: number className?: string } interface ReactiveDomReact { top: number bottom: number left: number right: number width: number height: number } const defaultRect: ReactiveDomReact = { top: -1000, left: -1000, right: -1000, bottom: -1000, width: 0, height: 0, } const getRect = (ref: MutableRefObject): ReactiveDomReact => { if (!ref || !ref.current) return defaultRect const rect = ref.current.getBoundingClientRect() return { ...rect, width: rect.width || rect.right - rect.left, height: rect.height || rect.bottom - rect.top, top: rect.top + document.documentElement.scrollTop, bottom: rect.bottom + document.documentElement.scrollTop, left: rect.left + document.documentElement.scrollLeft, right: rect.right + document.documentElement.scrollLeft, } } const TooltipContent: React.FC> = ({ children, parent, visible, offset, placement, type, className, hideArrow, }) => { const theme = useTheme() const el = usePortal('tooltip') const selfRef = useRef(null) const [rect, setRect] = useState(defaultTooltipPosition) const colors = useMemo(() => getColors(type, theme.palette), [type, theme.palette]) const hasShadow = type === 'default' if (!parent) return null const updateRect = () => { const position = getPosition(placement, getRect(parent), offset) setRect(position) } useResize(updateRect) useClickAnyWhere(() => updateRect()) useEffect(() => { updateRect() }, [visible]) const preventHandler = (event: React.MouseEvent) => { event.stopPropagation() event.nativeEvent.stopImmediatePropagation() } if (!el) return null return createPortal(
{!hideArrow && ( )} {children}
, el, ) } export default TooltipContent