'use client'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Label } from '@/components/ui/label'; import { Input } from '@/components/ui/input'; import { Slider } from '@/components/ui/slider'; import { Button } from '@/components/ui/button'; import { MousePointerClick } from 'lucide-react'; import { cn } from '@/lib/utils/cn'; import type { Keyframe, KeyframeProperties, TransformValue } from '@/types/animate'; import { DEFAULT_TRANSFORM } from '@/lib/animate/defaults'; interface Props { keyframe: Keyframe | null; onChange: (id: string, props: KeyframeProperties) => void; } interface SliderRowProps { label: string; unit?: string; value: number; min: number; max: number; step?: number; onChange: (v: number) => void; } function SliderRow({ label, unit, value, min, max, step = 1, onChange }: SliderRowProps) { return (
onChange(v)} />
onChange(Number(e.target.value))} className="w-16 text-xs px-1.5 h-7 mt-4" />
); } export function KeyframeProperties({ keyframe, onChange }: Props) { if (!keyframe) { return ( Properties

Select a keyframe on the timeline to edit its properties

); } const props = keyframe.properties; const t: TransformValue = { ...DEFAULT_TRANSFORM, ...props.transform }; const setTransform = (key: keyof TransformValue, value: number) => { onChange(keyframe.id, { ...props, transform: { ...t, [key]: value }, }); }; const setProp = (key: K, value: KeyframeProperties[K]) => { onChange(keyframe.id, { ...props, [key]: value }); }; const hasBg = props.backgroundColor && props.backgroundColor !== 'none'; return ( Properties {keyframe.offset}% {/* Transform */}

Transform

setTransform('translateX', v)} /> setTransform('translateY', v)} /> setTransform('rotate', v)} /> setTransform('scaleX', v)} /> setTransform('scaleY', v)} /> setTransform('skewX', v)} /> setTransform('skewY', v)} />
{/* Visual */}

Visual

setProp('opacity', v)} /> {/* Background color */}
setProp('backgroundColor', e.target.value)} disabled={!hasBg} className={cn('w-9 h-9 p-1 shrink-0 cursor-pointer', !hasBg && 'opacity-30')} /> setProp('backgroundColor', e.target.value)} disabled={!hasBg} placeholder="none" className="font-mono text-xs flex-1" />
setProp('borderRadius', v)} />
{/* Filters */}

Filter

setProp('blur', v)} /> setProp('brightness', v)} />
); }