| "use client"; |
|
|
| import { motion } from "framer-motion"; |
| import type { AnimationSettings, Caption, CaptionStyle } from "@/types"; |
|
|
| interface CaptionWordProps { |
| caption: Caption; |
| currentMs: number; |
| style: CaptionStyle; |
| animation: AnimationSettings; |
| } |
|
|
| export function CaptionWord({ caption, style, animation }: CaptionWordProps) { |
| |
| const text = style.uppercase ? caption.text.toUpperCase() : caption.text; |
|
|
| const textStyle: React.CSSProperties = { |
| fontFamily: `"${style.fontFamily}", "Arial Black", sans-serif`, |
| |
| fontSize: `${(style.fontSize / 1080) * 100}cqw`, |
| color: style.fillColor, |
| WebkitTextStroke: `${(style.strokeWidth / 1080) * 100}cqw ${style.strokeColor}`, |
| paintOrder: "stroke fill", |
| letterSpacing: `${(style.letterSpacing / 1080) * 100}cqw`, |
| textShadow: style.shadow |
| ? `0 ${(style.shadow.offsetY / 1080) * 100}cqw ${(style.shadow.blur / 1080) * 100}cqw ${style.shadow.color}` |
| : undefined, |
| }; |
|
|
| return ( |
| <motion.span |
| style={textStyle} |
| className="inline-block font-black leading-none" |
| // calm entrance matching the export renderer: fade + small rise, then hold still |
| initial={{ scale: animation.style === "pop" ? 0.92 : 0.97, opacity: 0, y: 10 }} |
| animate={{ scale: 1, opacity: 1, y: 0 }} |
| transition={{ |
| duration: 0.24 / animation.speed, |
| ease: animation.style === "pop" ? [0.34, 1.3, 0.64, 1] : "easeOut", |
| }} |
| > |
| {text} |
| </motion.span> |
| ); |
| } |
|
|