{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "primitive-text-morph",
  "type": "registry:ui",
  "title": "Text morph",
  "description": "Transition between similarly sized short labels while preserving reading position.",
  "dependencies": [
    "motion"
  ],
  "categories": [
    "primitive",
    "polish-effects"
  ],
  "docs": "https://motion-lexicon.pages.dev/en/primitives/text-morph/",
  "files": [
    {
      "path": "src/registry/primitives/text-morph.tsx",
      "type": "registry:ui",
      "target": "components/motion-lexicon/primitives/text-morph.tsx",
      "content": "\"use client\";\n\nimport { AnimatePresence, motion, useReducedMotion, type Transition } from \"motion/react\";\n\nconst EASE_OUT = [0.23, 1, 0.32, 1] as const;\n\nexport type TextMorphPrimitiveProps = {\n  value: string;\n  duration?: number;\n  easing?: Transition[\"ease\"];\n  blur?: number;\n  delay?: number;\n  className?: string;\n};\n\nexport function TextMorphPrimitive({\n  value,\n  duration = 0.24,\n  easing = EASE_OUT,\n  blur = 8,\n  delay = 0,\n  className,\n}: TextMorphPrimitiveProps) {\n  const reduceMotion = useReducedMotion();\n\n  return (\n    <span className={`relative inline-grid ${className ?? \"\"}`} aria-live=\"polite\">\n      <AnimatePresence initial={false} mode=\"popLayout\">\n        <motion.span\n          className=\"col-start-1 row-start-1\"\n          key={value}\n          initial={reduceMotion ? { opacity: 0 } : { opacity: 0, filter: `blur(${blur}px)`, transform: \"translate3d(0, 5px, 0)\" }}\n          animate={{ opacity: 1, filter: \"blur(0px)\", transform: \"translate3d(0, 0, 0)\" }}\n          exit={reduceMotion ? { opacity: 0 } : { opacity: 0, filter: `blur(${Math.min(blur, 4)}px)`, transform: \"translate3d(0, -4px, 0)\" }}\n          transition={reduceMotion ? { duration: 0.12 } : { duration, delay, ease: easing }}\n        >\n          {value}\n        </motion.span>\n      </AnimatePresence>\n    </span>\n  );\n}\n"
    }
  ]
}
