{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tactile-highlight",
  "title": "Tactile Highlight",
  "description": "A fluid text highlight component that reacts to viewport visibility and user interaction.",
  "dependencies": [
    "framer-motion"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/spark-ui/tactile-highlight.tsx",
      "content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { motion, useInView, Variants } from \"framer-motion\";\nimport React, { useRef } from \"react\";\n\ntype HighlightDirection = \"left\" | \"right\" | \"top\" | \"bottom\";\n\ninterface TactileHighlightProps {\n  children: React.ReactNode;\n  className?: string;\n  direction?: HighlightDirection;\n  delay?: number;\n  trigger?: \"auto\" | \"hover\" | \"inView\";\n}\n\n/**\n * TactileHighlight - A premium animated text highlight component.\n * Uses `mix-blend-difference` to guarantee mathematically perfect contrast\n * across both Light and Dark modes dynamically.\n */\nexport const TactileHighlight = ({\n  children,\n  className,\n  direction = \"left\",\n  delay = 0.1,\n  trigger = \"inView\",\n}: TactileHighlightProps) => {\n  const ref = useRef(null);\n  // once: false allows the animation to elegantly restart when scrolling back into view\n  const isInView = useInView(ref, { once: false, margin: \"-10%\" });\n\n  const isAnimated = trigger === \"auto\" || (trigger === \"inView\" && isInView);\n\n  const variants: Variants = {\n    hidden: {\n      scaleX: direction === \"left\" || direction === \"right\" ? 0 : 1,\n      scaleY: direction === \"top\" || direction === \"bottom\" ? 0 : 1,\n      originX: direction === \"left\" ? 0 : direction === \"right\" ? 1 : 0.5,\n      originY: direction === \"top\" ? 0 : direction === \"bottom\" ? 1 : 0.5,\n      borderRadius: \"12px\", // Starts very rounded\n    },\n    visible: {\n      scaleX: 1,\n      scaleY: 1,\n      borderRadius: \"4px\", // Snaps to sharp corners\n      transition: {\n        type: \"spring\",\n        damping: 22,\n        stiffness: 130,\n        mass: 0.8,\n        delay: delay,\n      },\n    },\n    hover: {\n      scale: 1.05,\n      rotate: direction === \"left\" ? -1.5 : direction === \"right\" ? 1.5 : 0,\n      borderRadius: \"8px\",\n      transition: {\n        type: \"spring\",\n        damping: 15,\n        stiffness: 400,\n      },\n    },\n  };\n\n  return (\n    <span\n      ref={ref}\n      className={cn(\n        \"relative inline-block whitespace-nowrap cursor-default group/tactile\",\n        className,\n      )}\n      style={{ padding: \"0 0.15em\", margin: \"0 -0.15em\" }}\n    >\n      {/* Background Block: Dark in light mode, Light in dark mode */}\n      <motion.span\n        initial=\"hidden\"\n        animate={isAnimated ? \"visible\" : \"hidden\"}\n        whileHover={trigger === \"hover\" ? \"visible\" : \"hover\"}\n        variants={variants}\n        className=\"absolute inset-0 bg-zinc-950 dark:bg-white shadow-xl z-0 origin-[var(--origin-x)_var(--origin-y)]\"\n        style={\n          {\n            \"--origin-x\":\n              direction === \"left\" ? 0 : direction === \"right\" ? 1 : 0.5,\n            \"--origin-y\":\n              direction === \"top\" ? 0 : direction === \"bottom\" ? 1 : 0.5,\n          } as React.CSSProperties\n        }\n      />\n\n      {/* \n        Text Layer: Always white, but uses difference blending.\n        Light Mode (White Page): White text difference White page = Black Text.\n        Dark Mode (Black Page): White text difference Black page = White Text.\n        Inside Highlight: Color perfectly inverts. \n      */}\n      <span className=\"relative z-10 text-white mix-blend-difference pointer-events-none\">\n        {children}\n      </span>\n    </span>\n  );\n};\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}