{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "inflate",
  "title": "Inflate",
  "description": "A deflated red sliver puffs up like a balloon toy, overshoots, squashes wide and settles into a glossy rounded mark.",
  "dependencies": ["remotion"],
  "files": [
    {
      "path": "registry/remocn/inflate/index.tsx",
      "content": "\"use client\";\n\nimport type React from \"react\";\nimport {\n  AbsoluteFill,\n  Easing,\n  interpolate,\n  spring,\n  useCurrentFrame,\n  useVideoConfig,\n} from \"remotion\";\n\nexport type InflateProps = {\n  /** Wordmark revealed beside the mark once it settles. */\n  children?: React.ReactNode;\n  backgroundColor?: string;\n  /** Body color of the mark. */\n  color?: string;\n  /** Specular highlight color. */\n  highlight?: string;\n  /** Dot inside the mark. */\n  dotColor?: string;\n  speed?: number;\n};\n\nexport const inflateDefaults = {\n  backgroundColor: \"#111111\",\n  color: \"#E5322D\",\n  highlight: \"#FFFFFF\",\n  dotColor: \"#111111\",\n  speed: 1,\n};\n\nconst PUFF = 3;\nconst WOBBLE = 10;\nconst DOT = 15;\nconst SLIDE = 22;\nconst clamp = {\n  extrapolateLeft: \"clamp\" as const,\n  extrapolateRight: \"clamp\" as const,\n};\n\nexport function Inflate(props: InflateProps) {\n  const { children, backgroundColor, color, highlight, dotColor, speed } = {\n    ...inflateDefaults,\n    ...props,\n  };\n  const frame = useCurrentFrame();\n  const { width, height, fps } = useVideoConfig();\n  const t = frame * Math.max(0, speed);\n  const size = Math.round(Math.min(width, height) * 0.22);\n\n  // Main puff: an underdamped spring overshoots the final size.\n  const puff = spring({\n    frame: t - PUFF,\n    fps,\n    config: { damping: 8, stiffness: 150, mass: 0.6 },\n  });\n  // After the peak the body squashes wide and rings out like a balloon.\n  const w0 = t - WOBBLE;\n  const wobble =\n    w0 > 0 ? 0.2 * Math.exp(-w0 / 6) * Math.sin((w0 / 9) * Math.PI * 2) : 0;\n\n  const grow = Math.max(0, puff);\n  const sliverW = interpolate(t, [0, PUFF], [0.7, 1], {\n    ...clamp,\n    easing: Easing.out(Easing.quad),\n  });\n  const bodyH = size * (0.05 + 0.95 * grow) * (1 - wobble);\n  const bodyW = size * (sliverW + (Math.max(1, grow) - 1) * 0.8) * (1 + wobble);\n  const roundness = interpolate(t, [PUFF, PUFF + 7, 26], [0.5, 0.46, 0.27], {\n    ...clamp,\n    easing: Easing.inOut(Easing.quad),\n  });\n  const radius = Math.min(bodyW, bodyH) * roundness;\n  const gloss = interpolate(t, [PUFF + 2, PUFF + 9], [0, 1], clamp);\n  const appear = interpolate(t, [0, 2], [0, 1], clamp);\n\n  const dot = spring({\n    frame: t - DOT,\n    fps,\n    config: { damping: 10, stiffness: 220, mass: 0.5 },\n  });\n  const slide = interpolate(t, [SLIDE, SLIDE + 11], [0, 1], {\n    ...clamp,\n    easing: Easing.inOut(Easing.cubic),\n  });\n  const reveal = interpolate(t, [SLIDE + 2, SLIDE + 13], [0, 1], {\n    ...clamp,\n    easing: Easing.out(Easing.cubic),\n  });\n\n  return (\n    <AbsoluteFill\n      style={{\n        backgroundColor,\n        alignItems: \"center\",\n        justifyContent: \"center\",\n      }}\n    >\n      <div\n        style={{\n          display: \"flex\",\n          alignItems: \"center\",\n          gap: size * 0.24,\n          transform: `translateX(calc((50% - ${size / 2}px) * ${children ? 1 - slide : 0}))`,\n        }}\n      >\n        <div\n          style={{\n            width: size,\n            height: size,\n            flexShrink: 0,\n            display: \"flex\",\n            alignItems: \"center\",\n            justifyContent: \"center\",\n          }}\n        >\n          <div\n            style={{\n              position: \"relative\",\n              flexShrink: 0,\n              width: bodyW,\n              height: bodyH,\n              borderRadius: radius,\n              backgroundColor: color,\n              opacity: appear,\n              overflow: \"hidden\",\n              display: \"flex\",\n              alignItems: \"center\",\n              justifyContent: \"center\",\n              boxShadow: `inset ${-size * 0.06}px ${-size * 0.08}px ${size * 0.14}px rgba(0,0,0,${0.28 * gloss})`,\n            }}\n          >\n            <div\n              style={{\n                position: \"absolute\",\n                left: \"14%\",\n                top: \"10%\",\n                width: \"46%\",\n                height: \"28%\",\n                borderRadius: \"50%\",\n                background: `radial-gradient(ellipse at 45% 40%, ${highlight} 0%, transparent 70%)`,\n                opacity: 0.55 * gloss,\n                transform: \"rotate(-18deg)\",\n              }}\n            />\n            <div\n              style={{\n                width: size * 0.3,\n                height: size * 0.3,\n                borderRadius: \"50%\",\n                backgroundColor: dotColor,\n                transform: `scale(${dot})`,\n              }}\n            />\n          </div>\n        </div>\n        {children && (\n          <div\n            style={{\n              opacity: reveal,\n              clipPath: `inset(-30% ${(1 - reveal) * 100}% -30% -5%)`,\n              transform: `translateX(${(1 - reveal) * -size * 0.3}px)`,\n            }}\n          >\n            {children}\n          </div>\n        )}\n      </div>\n    </AbsoluteFill>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/remocn/inflate.tsx"
    }
  ],
  "type": "registry:component"
}
