UNPKG

@redocly/theme

Version:

Shared UI components lib

74 lines (58 loc) 2.21 kB
import { useLayoutEffect, useRef, useState } from 'react'; import type { RefObject } from 'react'; import type { TooltipPlacement, TooltipProps } from '@redocly/theme/core/types'; type TooltipFallbackPlacementParams = { isOpened: boolean; placement: TooltipPlacement; arrowPosition: TooltipProps['arrowPosition']; fallbackPlacements: TooltipPlacement[] | undefined; tooltipBodyRef: RefObject<HTMLElement | null>; }; type TooltipFallbackPlacementResult = { activePlacement: TooltipPlacement; activeArrowPosition: TooltipProps['arrowPosition']; }; export function useTooltipFallbackPlacement({ isOpened, placement, arrowPosition, fallbackPlacements, tooltipBodyRef, }: TooltipFallbackPlacementParams): TooltipFallbackPlacementResult { const [activePlacement, setActivePlacement] = useState<TooltipPlacement>(placement); const wasOpenRef = useRef(false); const candidateIndexRef = useRef(0); useLayoutEffect(() => { if (!isOpened) { wasOpenRef.current = false; candidateIndexRef.current = 0; return; } if (!wasOpenRef.current) { wasOpenRef.current = true; candidateIndexRef.current = 0; if (activePlacement !== placement) { setActivePlacement(placement); return; } } if (!tooltipBodyRef.current || !fallbackPlacements?.length) return; const candidates: TooltipPlacement[] = [placement, ...fallbackPlacements]; if (candidateIndexRef.current >= candidates.length) return; const rect = tooltipBodyRef.current.getBoundingClientRect(); const overflows = rect.left < 0 || rect.top < 0 || rect.right > window.innerWidth || rect.bottom > window.innerHeight; if (!overflows) return; candidateIndexRef.current++; if (candidateIndexRef.current < candidates.length) { setActivePlacement(candidates[candidateIndexRef.current]); } else if (activePlacement !== placement) { setActivePlacement(placement); } }, [isOpened, activePlacement, placement, fallbackPlacements, tooltipBodyRef]); const activeArrowPosition = activePlacement === placement ? arrowPosition : 'center'; return { activePlacement, activeArrowPosition }; }