import ZoomInIcon from '@mui/icons-material/Add'; import ZoomOutIcon from '@mui/icons-material/Remove'; import ReplayIcon from '@mui/icons-material/Replay'; import { RectClipPath } from '@visx/clip-path'; import { type ForwardedRef, forwardRef, type MutableRefObject, useEffect, useRef, useState } from 'react'; import { IconButton } from '../Button'; import { minimapScale, radius } from './constants'; import Minimap from './Minimap'; import type { Dimension, MinimapPosition, ZoomChildren, ZoomInterface } from './models'; import { useZoom } from './useZoom'; import { useZoomStyles } from './Zoom.styles'; export interface Props extends Dimension, ZoomInterface, ZoomChildren { id?: number | string; minimapPosition: MinimapPosition; showMinimap?: boolean; } const ZoomContent = forwardRef( ( { zoom, width, height, children, showMinimap, minimapPosition, id }: Props, ref?: ForwardedRef ): JSX.Element => { const { classes } = useZoomStyles(); const fallbackRef = useRef(null); const contentRef = (ref || fallbackRef) as MutableRefObject; const minimapSvgRef = useRef(null); const minimapContentRef = useRef(null); const [contentClientRect, setContentClientRect] = useState(null); const resizeObserver = new ResizeObserver(() => { const contentBoundingClientRect = ( contentRef.current as SVGGElement ).getBoundingClientRect(); setContentClientRect({ height: contentBoundingClientRect.height, width: contentBoundingClientRect.width }); }); useEffect(() => { if (contentRef.current) { resizeObserver.disconnect(); resizeObserver.observe(contentRef.current); } return () => { resizeObserver.disconnect(); }; }, [contentRef.current, resizeObserver.disconnect, resizeObserver.observe]); const { move, dragEnd, dragStart, isDragging } = useZoom(); const diffBetweenContentAndSvg = minimapSvgRef.current && minimapContentRef.current && { left: minimapContentRef.current.getBoundingClientRect().left - minimapSvgRef.current.getBoundingClientRect().left, top: minimapContentRef.current.getBoundingClientRect().top - minimapSvgRef.current.getBoundingClientRect().top }; return (
{children({ contentClientRect, height, transformMatrix: zoom.transformMatrix, width, zoom })}
{showMinimap && contentClientRect && ( {children({ contentClientRect, height, transformMatrix: zoom.transformMatrix, width, zoom })} )}
} onClick={() => zoom.scale({ scaleX: 1.2, scaleY: 1.2 })} size="small" /> } onClick={() => zoom.scale({ scaleX: 0.8, scaleY: 0.8 })} size="small" /> } onClick={zoom.reset} size="small" />
); } ); export default ZoomContent;