{
  "name": "morphing-image-effect-default",
  "type": "registry:block",
  "tier": "free",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://www.craftui.space/r/craftui-base.json"
  ],
  "files": [
    {
      "path": "components/craftui/blocks/morphing-image-effect/default.tsx",
      "content": "\"use client\";\n\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { useState } from \"react\";\n\ntype Stage = 1 | 2 | 3;\n\nconst stageConfig: Record<\n  Stage,\n  {\n    imageW: number;\n    imageH: number;\n    imageRadius: number;\n    fontSize: number;\n    rotate: number;\n  }\n> = {\n  1: {\n    imageW: 54,\n    imageH: 80,\n    imageRadius: 27,\n    fontSize: 88,\n    rotate: 0,\n  },\n  2: {\n    imageW: 620,\n    imageH: 400,\n    imageRadius: 20,\n    fontSize: 176,\n    rotate: -3,\n  },\n  3: {\n    imageW: 260,\n    imageH: 500,\n    imageRadius: 28,\n    fontSize: 144,\n    rotate: 4,\n  },\n};\n\nconst IMAGE_URL =\n  \"https://images.unsplash.com/photo-1586023492125-27b2c045efd7?w=900&auto=format&fit=crop&q=80\";\n\nconst stageLabel = (s: Stage) => `Stage 0${s} — click to advance`;\n\n// ease-in-out-quart — for on-screen morphing elements\nconst morph = {\n  ease: [0.77, 0, 0.175, 1] as const,\n  duration: 0.65,\n};\n\nexport default function MorphingImageEffect() {\n  const [stage, setStage] = useState<Stage>(1);\n  const cfg = stageConfig[stage];\n\n  const advance = () => setStage((s) => ((s % 3) + 1) as Stage);\n\n  return (\n    <div\n      onClick={advance}\n      className=\"flex min-h-screen cursor-pointer flex-col items-center justify-center overflow-hidden bg-[#eceae4] w-full select-none\"\n    >\n      {/* Grid: 1fr [image auto] 1fr — P and ST always adjacent to image */}\n      <div\n        className=\"grid w-full items-center px-8\"\n        style={{ gridTemplateColumns: \"1fr auto 1fr\", gap: \"0 1rem\" }}\n      >\n        {/* P — right-aligned so it touches the image's left edge */}\n        <motion.span\n          animate={{ fontSize: cfg.fontSize }}\n          transition={{ ...morph, delay: 0.04 }}\n          className=\"text-right font-sans font-normal leading-none tracking-tighter text-[#111]\"\n        >\n          P\n        </motion.span>\n\n        {/* Image — CSS t-resize owns width/height, Motion owns borderRadius + rotate */}\n        <motion.div\n          animate={{ borderRadius: cfg.imageRadius, rotate: cfg.rotate }}\n          style={{ width: cfg.imageW, height: cfg.imageH }}\n          transition={morph}\n          className=\"t-resize shrink-0 overflow-hidden\"\n        >\n          <img\n            src={IMAGE_URL}\n            alt=\"interior\"\n            className=\"block h-full w-full object-cover\"\n          />\n        </motion.div>\n\n        {/* ST — left-aligned so it touches the image's right edge */}\n        <motion.span\n          animate={{ fontSize: cfg.fontSize }}\n          transition={{ ...morph, delay: 0.04 }}\n          className=\"text-left font-sans font-normal leading-none tracking-tighter text-[#111]\"\n        >\n          ST\n        </motion.span>\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "~/components/craftui/blocks/morphing-image-effect/default.tsx"
    }
  ],
  "meta": {
    "displayName": "Morphing Image Effect - Image Morph",
    "description": "Three-stage morph: thumbnail pill → landscape card → portrait card. Text scales inversely as the image grows.",
    "category": "creative",
    "tags": [
      "morph",
      "image",
      "typography",
      "interactive",
      "click",
      "animation",
      "layout"
    ],
    "animationType": "click-driven"
  }
}