import type { CSSProperties, ElementType, Ref } from 'react'; import type { ArrowRenderProps, Placement } from '~/types'; interface ArrowProps { arrowComponent?: ElementType; arrowRef: Ref; base: number; placement: Placement; position: { x?: number; y?: number } | undefined; size: number; styles: CSSProperties; } function getDimensions(placement: Placement, base: number, size: number) { const [side] = placement.split('-'); switch (side) { case 'top': case 'bottom': return { width: base, height: size }; case 'left': case 'right': return { width: size, height: base }; default: return null; } } function getPoints(placement: Placement, base: number, size: number) { const [side] = placement.split('-'); switch (side) { case 'top': return { points: `0,0 ${base / 2},${size} ${base},0`, ...getDimensions(placement, base, size), }; case 'bottom': return { points: `${base},${size} ${base / 2},0 0,${size}`, ...getDimensions(placement, base, size), }; case 'left': return { points: `0,0 ${size},${base / 2} 0,${base}`, ...getDimensions(placement, base, size), }; case 'right': return { points: `${size},${base} ${size},0 0,${base / 2}`, ...getDimensions(placement, base, size), }; default: return null; } } function getPositionStyle( placement: Placement, position: { x?: number; y?: number } | undefined, size: number, base: number, ): CSSProperties { if (!position) { return {}; } const [side] = placement.split('-'); switch (side) { case 'top': return { bottom: -size, left: position.x ?? 0, ...getDimensions(placement, base, size) }; case 'bottom': return { top: -size, left: position.x ?? 0, ...getDimensions(placement, base, size) }; case 'left': return { right: -size, top: position.y ?? 0, ...getDimensions(placement, base, size) }; case 'right': return { left: -size, top: position.y ?? 0, ...getDimensions(placement, base, size) }; default: return {}; } } export default function Arrow({ arrowComponent, arrowRef, base, placement, position, size, styles, }: ArrowProps) { const ArrowComponent = arrowComponent; let content = null; if (ArrowComponent) { const dimensions = getDimensions(placement, base, size); if (!dimensions) { return null; } content = ( ); } else { const svg = getPoints(placement, base, size); if (!svg) { return null; } content = ( ); } return ( {content} ); }