diff --git a/apps/web/src/components/editor/properties-panel/text-properties.tsx b/apps/web/src/components/editor/properties-panel/text-properties.tsx index 3dccc226..285bfc41 100644 --- a/apps/web/src/components/editor/properties-panel/text-properties.tsx +++ b/apps/web/src/components/editor/properties-panel/text-properties.tsx @@ -6,6 +6,7 @@ import { useTimelineStore } from "@/stores/timeline-store"; import { Slider } from "@/components/ui/slider"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; +import { useState } from "react"; import { PropertyItem, PropertyItemLabel, @@ -20,6 +21,46 @@ export function TextProperties({ trackId: string; }) { const { updateTextElement } = useTimelineStore(); + + // Local state for input values to allow temporary empty/invalid states + const [fontSizeInput, setFontSizeInput] = useState(element.fontSize.toString()); + const [opacityInput, setOpacityInput] = useState(Math.round(element.opacity * 100).toString()); + + const parseAndValidateNumber = (value: string, min: number, max: number, fallback: number): number => { + const parsed = parseInt(value, 10); + if (isNaN(parsed)) return fallback; + return Math.max(min, Math.min(max, parsed)); + }; + + const handleFontSizeChange = (value: string) => { + setFontSizeInput(value); + + if (value.trim() !== '') { + const fontSize = parseAndValidateNumber(value, 8, 300, element.fontSize); + updateTextElement(trackId, element.id, { fontSize }); + } + }; + + const handleFontSizeBlur = () => { + const fontSize = parseAndValidateNumber(fontSizeInput, 8, 300, element.fontSize); + setFontSizeInput(fontSize.toString()); + updateTextElement(trackId, element.id, { fontSize }); + }; + + const handleOpacityChange = (value: string) => { + setOpacityInput(value); + + if (value.trim() !== '') { + const opacityPercent = parseAndValidateNumber(value, 0, 100, Math.round(element.opacity * 100)); + updateTextElement(trackId, element.id, { opacity: opacityPercent / 100 }); + } + }; + + const handleOpacityBlur = () => { + const opacityPercent = parseAndValidateNumber(opacityInput, 0, 100, Math.round(element.opacity * 100)); + setOpacityInput(opacityPercent.toString()); + updateTextElement(trackId, element.id, { opacity: opacityPercent / 100 }); + }; return (