import { useMemo, useEffect, useState } from 'react'; import { useCanvasStore } from '@/lib/store'; import { getElementListRange } from '@/lib/utils/element'; import type { PPTElement } from '@/lib/types/slides'; import type { ViewportStyles } from './hooks/useViewportSize'; interface RulerProps { viewportStyles: ViewportStyles; elementList: PPTElement[]; } export function Ruler({ viewportStyles, elementList }: RulerProps) { const canvasScale = useCanvasStore.use.canvasScale(); const activeElementIdList = useCanvasStore.use.activeElementIdList(); const viewportRatio = useCanvasStore.use.viewportRatio(); const viewportSize = useCanvasStore.use.viewportSize(); const [elementListRange, setElementListRange] = useState | null>(null); useEffect(() => { const els = elementList.filter((el) => activeElementIdList.includes(el.id)); if (!els.length) { // eslint-disable-next-line react-hooks/set-state-in-effect -- DOM measurement requires effect setElementListRange(null); } else { setElementListRange(getElementListRange(els)); } }, [elementList, activeElementIdList]); const markerSize = useMemo(() => { return (viewportStyles.width * canvasScale) / (viewportSize / 100); }, [viewportStyles.width, canvasScale, viewportSize]); const markers = Array.from({ length: 20 }, (_, i) => i + 1); return (
{/* Ruler corner */}
{/* Horizontal ruler */}
{markers.map((marker) => (
span]:hidden' : '' } ${markerSize < 72 ? 'before:hidden' : ''}`} style={{ width: markerSize + 'px' }} > {marker * 100 <= viewportSize && {marker * 100}} {/* Major tick mark */}
{/* Minor tick mark (50) */}
))} {elementListRange && (
)}
{/* Vertical ruler */}
{markers.map((marker) => (
span]:hidden' : '' } ${markerSize < 72 ? 'before:hidden' : ''}`} style={{ height: markerSize + 'px' }} > {marker * 100 <= viewportSize * viewportRatio && {marker * 100}} {/* Major tick mark */}
{/* Minor tick mark (50) */}
))} {elementListRange && (
)}
); }