{
  "name": "link-preview",
  "type": "registry:ui",
  "dependencies": [
    "@radix-ui/react-hover-card",
    "qss",
    "motion"
  ],
  "files": [
    {
      "path": "components/ui/link-preview.tsx",
      "content": "\"use client\";\nimport * as HoverCardPrimitive from \"@radix-ui/react-hover-card\";\n\nimport { encode } from \"qss\";\nimport React from \"react\";\nimport {\n  AnimatePresence,\n  motion,\n  useMotionValue,\n  useSpring,\n} from \"motion/react\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype LinkPreviewProps = {\n  children: React.ReactNode;\n  url: string;\n  className?: string;\n  width?: number;\n  height?: number;\n  quality?: number;\n  layout?: string;\n} & (\n  | { isStatic: true; imageSrc: string }\n  | { isStatic?: false; imageSrc?: never }\n);\n\nexport const LinkPreview = ({\n  children,\n  url,\n  className,\n  width = 200,\n  height = 125,\n  quality = 50,\n  layout = \"fixed\",\n  isStatic = false,\n  imageSrc = \"\",\n}: LinkPreviewProps) => {\n  let src;\n  if (!isStatic) {\n    const params = encode({\n      url,\n      screenshot: true,\n      meta: false,\n      embed: \"screenshot.url\",\n      colorScheme: \"dark\",\n      \"viewport.isMobile\": true,\n      \"viewport.deviceScaleFactor\": 1,\n      \"viewport.width\": width * 3,\n      \"viewport.height\": height * 3,\n    });\n    src = `https://api.microlink.io/?${params}`;\n  } else {\n    src = imageSrc;\n  }\n\n  const [isOpen, setOpen] = React.useState(false);\n\n  const [isMounted, setIsMounted] = React.useState(false);\n\n  React.useEffect(() => {\n    setIsMounted(true);\n  }, []);\n\n  const springConfig = { stiffness: 100, damping: 15 };\n  const x = useMotionValue(0);\n\n  const translateX = useSpring(x, springConfig);\n\n  const handleMouseMove = (event: any) => {\n    const targetRect = event.target.getBoundingClientRect();\n    const eventOffsetX = event.clientX - targetRect.left;\n    const offsetFromCenter = (eventOffsetX - targetRect.width / 2) / 2; // Reduce the effect to make it subtle\n    x.set(offsetFromCenter);\n  };\n\n  return (\n    <>\n      {isMounted ? (\n        <div className=\"hidden\">\n          <img\n            src={src}\n            width={width}\n            height={height}\n            alt=\"hidden image\"\n          />\n        </div>\n      ) : null}\n\n      <HoverCardPrimitive.Root\n        openDelay={50}\n        closeDelay={100}\n        onOpenChange={(open) => {\n          setOpen(open);\n        }}\n      >\n        <HoverCardPrimitive.Trigger\n          onMouseMove={handleMouseMove}\n          className={cn(\"text-black dark:text-white\", className)}\n          href={url}\n        >\n          {children}\n        </HoverCardPrimitive.Trigger>\n\n        <HoverCardPrimitive.Content\n          className=\"[transform-origin:var(--radix-hover-card-content-transform-origin)]\"\n          side=\"top\"\n          align=\"center\"\n          sideOffset={10}\n        >\n          <AnimatePresence>\n            {isOpen && (\n              <motion.div\n                initial={{ opacity: 0, y: 20, scale: 0.6 }}\n                animate={{\n                  opacity: 1,\n                  y: 0,\n                  scale: 1,\n                  transition: {\n                    type: \"spring\",\n                    stiffness: 260,\n                    damping: 20,\n                  },\n                }}\n                exit={{ opacity: 0, y: 20, scale: 0.6 }}\n                className=\"shadow-xl rounded-xl\"\n                style={{\n                  x: translateX,\n                }}\n              >\n                <a\n                  href={url}\n                  className=\"block p-1 bg-white border-2 border-transparent shadow rounded-xl hover:border-neutral-200 dark:hover:border-neutral-800\"\n                  style={{ fontSize: 0 }}\n                >\n                  <img\n                    src={isStatic ? imageSrc : src}\n                    width={width}\n                    height={height}\n                    className=\"rounded-lg\"\n                    alt=\"preview image\"\n                  />\n                </a>\n              </motion.div>\n            )}\n          </AnimatePresence>\n        </HoverCardPrimitive.Content>\n      </HoverCardPrimitive.Root>\n    </>\n  );\n};\n",
      "type": "registry:ui",
      "target": "components/ui/link-preview.tsx"
    }
  ],
  "author": "Manu Arora <hi@manuarora.in>",
  "title": "Link Preview"
}