import { useCallback, useMemo } from 'react'; interface UseTimelineGeometryOptions { mediaDuration: number; constants: { TRACK_HEIGHT: number; TRACK_PADDING: number; TIMELINE_PADDING: number; PIXELS_PER_SECOND: number; }; } export const useTimelineGeometry = ({ mediaDuration, constants, }: UseTimelineGeometryOptions) => { const { TRACK_HEIGHT, TRACK_PADDING, TIMELINE_PADDING, PIXELS_PER_SECOND } = constants; // Calculate timeline dimensions const timelineWidth = useMemo(() => mediaDuration * PIXELS_PER_SECOND, [mediaDuration, PIXELS_PER_SECOND] ); // Convert time to x position const timeToX = useCallback((time: number) => { return TIMELINE_PADDING + (time / mediaDuration) * (timelineWidth - TIMELINE_PADDING * 2); }, [mediaDuration, timelineWidth, TIMELINE_PADDING]); // Convert x position to time const xToTime = useCallback((x: number) => { return ((x - TIMELINE_PADDING) / (timelineWidth - TIMELINE_PADDING * 2)) * mediaDuration; }, [mediaDuration, timelineWidth, TIMELINE_PADDING]); // Convert track to y position const trackToY = useCallback((track: number) => { return TIMELINE_PADDING + track * (TRACK_HEIGHT + TRACK_PADDING); }, [TRACK_HEIGHT, TRACK_PADDING, TIMELINE_PADDING]); // Convert canvas coordinates to time (accounting for scroll) const canvasXToTime = useCallback((canvasX: number) => { return xToTime(canvasX); }, [xToTime]); // Convert client coordinates to canvas coordinates const clientXToCanvasX = useCallback((clientX: number, canvasRef: React.RefObject) => { const canvas = canvasRef.current; if (!canvas) return 0; const rect = canvas.getBoundingClientRect(); return clientX - rect.left; }, []); return { timelineWidth, timeToX, xToTime, trackToY, canvasXToTime, clientXToCanvasX, }; };