{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "caption-texture",
  "title": "Caption Texture",
  "description": "Captions filled with a rich gradient texture that animates across words.",
  "dependencies": [
    "@editframe/react"
  ],
  "files": [
    {
      "path": "registry/bases/editframe/components/caption-texture/index.tsx",
      "content": "\"use client\";\n\nimport { Timegroup } from \"@editframe/react\";\nimport type { CSSProperties } from \"react\";\n\nexport interface CaptionWord {\n  text: string;\n  start: number;\n  end: number;\n}\n\nexport interface CaptionTextureProps {\n  words?: CaptionWord[];\n  textureFrom?: string;\n  textureMid?: string;\n  textureTo?: string;\n  fontSize?: number;\n  fontWeight?: number | string;\n  background?: string;\n  speed?: number;\n  fps?: number;\n  durationInFrames?: number;\n  width?: number;\n  height?: number;\n  className?: string;\n}\n\nconst DEFAULT_WORDS: CaptionWord[] = [\n  { end: 0.35, start: 0, text: \"Every\" },\n  { end: 0.65, start: 0.35, text: \"great\" },\n  { end: 1, start: 0.65, text: \"video\" },\n  { end: 1.45, start: 1.1, text: \"starts\" },\n  { end: 1.65, start: 1.45, text: \"with\" },\n  { end: 1.8, start: 1.65, text: \"a\" },\n  { end: 2.15, start: 1.8, text: \"single\" },\n  { end: 2.7, start: 2.15, text: \"frame.\" },\n  { end: 3.2, start: 3, text: \"No\" },\n  { end: 3.9, start: 3.2, text: \"timelines.\" },\n  { end: 4.2, start: 4, text: \"No\" },\n  { end: 4.5, start: 4.2, text: \"drag\" },\n  { end: 4.65, start: 4.5, text: \"and\" },\n  { end: 5.1, start: 4.65, text: \"drop.\" },\n  { end: 5.55, start: 5.3, text: \"Just\" },\n  { end: 6, start: 5.55, text: \"code.\" },\n];\n\nconst IN_DURATION = 220;\nconst OUT_DURATION = 140;\n\nexport const CaptionTexture = ({\n  words = DEFAULT_WORDS,\n  textureFrom = \"#ff6414\",\n  textureMid = \"#ff2200\",\n  textureTo = \"#ffd000\",\n  fontSize = 120,\n  fontWeight = 900,\n  background = \"#0a0a0a\",\n  speed = 1,\n  fps = 30,\n  durationInFrames = 180,\n  width = 1280,\n  height = 720,\n  className,\n}: CaptionTextureProps) => {\n  const safeSpeed = Math.max(0.01, speed);\n  const durationMs = (durationInFrames / fps) * 1000;\n\n  const containerStyle: CSSProperties = {\n    alignItems: \"center\",\n    background,\n    display: \"flex\",\n    height,\n    justifyContent: \"center\",\n    overflow: \"hidden\",\n    position: \"relative\",\n    width,\n  };\n\n  const textureBackground = `radial-gradient(ellipse at 20% 30%, ${textureFrom} 0%, transparent 50%), radial-gradient(ellipse at 75% 65%, ${textureMid} 0%, transparent 45%), radial-gradient(ellipse at 50% 50%, ${textureTo} 0%, transparent 60%), ${textureMid}`;\n\n  return (\n    <Timegroup\n      className={className}\n      duration={`${durationMs}ms`}\n      mode=\"fixed\"\n      style={containerStyle}\n    >\n      <>\n        <style>{`\n          @keyframes framecn-ctx-in {\n            0%   { opacity: 0; transform: translateY(-40px) scale(1.3); }\n            60%  { opacity: 1; }\n            100% { opacity: 1; transform: translateY(0) scale(1); }\n          }\n          @keyframes framecn-ctx-out {\n            from { opacity: 1; transform: scale(1); }\n            to   { opacity: 0; transform: scale(0.82); }\n          }\n        `}</style>\n        {words.map((word, i) => {\n          const startMs = (word.start * 1000) / safeSpeed;\n          const endMs = (word.end * 1000) / safeSpeed;\n          const wordDurationMs = endMs - startMs;\n          const outStart = Math.max(\n            startMs + IN_DURATION,\n            endMs - OUT_DURATION\n          );\n          return (\n            <span\n              key={i}\n              style={{\n                WebkitBackgroundClip: \"text\",\n                animation: [\n                  `framecn-ctx-in ${Math.min(IN_DURATION, wordDurationMs * 0.6)}ms cubic-bezier(0.16,1,0.3,1) ${startMs}ms backwards`,\n                  `framecn-ctx-out ${OUT_DURATION}ms ease-in ${outStart}ms forwards`,\n                ].join(\", \"),\n                backgroundClip: \"text\",\n                backgroundImage: textureBackground,\n                color: \"transparent\",\n                display: \"inline-block\",\n                fontFamily:\n                  \"'Anton', 'Impact', var(--font-geist-sans), -apple-system, BlinkMacSystemFont, sans-serif\",\n                fontSize,\n                fontWeight,\n                left: 0,\n                letterSpacing: \"0.04em\",\n                lineHeight: 1,\n                position: \"absolute\",\n                right: 0,\n                textAlign: \"center\",\n                textTransform: \"uppercase\",\n              }}\n            >\n              {word.text}\n            </span>\n          );\n        })}\n      </>\n    </Timegroup>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/framecn/caption-texture.tsx"
    }
  ],
  "type": "registry:component"
}