'use client'; import { cn } from '@/lib/utils'; import type { IntervalListState } from '@/lib/visualizations/types'; import { IntervalBar } from '../primitives/interval-bar'; import { AnimatePresence } from 'framer-motion'; interface IntervalViewProps { intervalList: IntervalListState; className?: string; } const PIXELS_PER_UNIT = 20; const BAR_HEIGHT = 28; const ROW_GAP = 8; export function IntervalView({ intervalList, className, }: IntervalViewProps) { // Calculate timeline range const minValue = intervalList.minValue ?? 0; const maxValue = intervalList.maxValue ?? Math.max( ...intervalList.intervals.map((i) => i.end), 20 ); const timelineWidth = (maxValue - minValue) * PIXELS_PER_UNIT; // Generate tick marks for the number line const tickStep = maxValue <= 10 ? 1 : maxValue <= 20 ? 2 : 5; const ticks: number[] = []; for (let i = minValue; i <= maxValue; i += tickStep) { ticks.push(i); } // Calculate row assignments to prevent overlapping intervals const rows: IntervalListState['intervals'][] = []; for (const interval of intervalList.intervals) { let placed = false; for (const row of rows) { const overlaps = row.some( (existing) => !(interval.end <= existing.start || interval.start >= existing.end) ); if (!overlaps) { row.push(interval); placed = true; break; } } if (!placed) { rows.push([interval]); } } const intervalsHeight = rows.length * (BAR_HEIGHT + ROW_GAP) - ROW_GAP; return (