'use client'; import { useCallback, useState } from 'react'; import { KeyframeMarker } from './KeyframeMarker'; import { cn } from '@/lib/utils'; interface Keyframe { id: string; bar: number; } interface KeyframeTrackProps { label: string; icon?: React.ReactNode; keyframes: T[]; durationBars: number; pixelsPerBar: number; selectedId: string | null; onSelect: (id: string | null) => void; onAdd: (bar: number) => void; onDelete: (id: string) => void; markerColor?: string; renderPicker?: (props: { keyframe: T; onClose: () => void; position: { x: number; y: number }; }) => React.ReactNode; className?: string; } export function KeyframeTrack({ label, icon, keyframes, durationBars, pixelsPerBar, selectedId, onSelect, onAdd, onDelete, markerColor = 'bg-primary', renderPicker, className, }: KeyframeTrackProps) { const [pickerPosition, setPickerPosition] = useState<{ x: number; y: number } | null>( null ); const handleTrackClick = useCallback( (e: React.MouseEvent) => { const rect = e.currentTarget.getBoundingClientRect(); const x = e.clientX - rect.left; const bar = Math.floor(x / pixelsPerBar); if (bar >= 0 && bar < durationBars) { const existingKeyframe = keyframes.find((kf) => kf.bar === bar); if (existingKeyframe) { onSelect(existingKeyframe.id); setPickerPosition({ x: bar * pixelsPerBar, y: 0 }); } else { onAdd(bar); } } }, [pixelsPerBar, durationBars, keyframes, onSelect, onAdd] ); const handleMarkerSelect = useCallback( (keyframe: T) => { onSelect(keyframe.id); setPickerPosition({ x: keyframe.bar * pixelsPerBar, y: 0 }); }, [onSelect, pixelsPerBar] ); const handleClosePicker = useCallback(() => { onSelect(null); setPickerPosition(null); }, [onSelect]); const selectedKeyframe = selectedId ? keyframes.find((kf) => kf.id === selectedId) : null; return (
{icon} {label}
{Array.from({ length: durationBars }, (_, i) => (
))} {keyframes.map((kf) => ( handleMarkerSelect(kf)} onDelete={() => onDelete(kf.id)} /> ))} {selectedKeyframe && pickerPosition && renderPicker && (
{renderPicker({ keyframe: selectedKeyframe, onClose: handleClosePicker, position: pickerPosition, })}
)}
); }