"use client"; import * as HoverCardPrimitive from "@radix-ui/react-hover-card"; import { AnimatePresence, motion, useMotionValue, useSpring, } from "framer-motion"; import { encode } from "qss"; import { type MouseEvent as ReactMouseEvent, type ReactNode, useEffect, useState, } from "react"; import { createPortal } from "react-dom"; type LinkPreviewProps = { children: ReactNode; url: string; className?: string; width?: number; height?: number; quality?: number; layout?: string; } & ( | { isStatic: true; imageSrc: string } | { isStatic?: false; imageSrc?: never } ); export const LinkPreview = ({ children, url, className, width = 200, height = 125, isStatic = false, imageSrc = "", }: LinkPreviewProps) => { let src: string; if (isStatic) { src = imageSrc; } else { const params = encode({ url, screenshot: true, meta: false, embed: "screenshot.url", colorScheme: "dark", "viewport.isMobile": true, "viewport.deviceScaleFactor": 1, "viewport.width": width * 3, "viewport.height": height * 3, }); src = `https://api.microlink.io/?${params}`; } const [isOpen, setOpen] = useState(false); const [isMounted, setIsMounted] = useState(false); useEffect(() => { setIsMounted(true); }, []); const springConfig = { stiffness: 100, damping: 15 }; const x = useMotionValue(0); const translateX = useSpring(x, springConfig); const handleMouseMove = ( event: ReactMouseEvent, ) => { const targetRect = ( event.target as HTMLAnchorElement ).getBoundingClientRect(); const eventOffsetX = event.clientX - targetRect.left; const offsetFromCenter = (eventOffsetX - targetRect.width / 2) / 2; // Reduce the effect to make it subtle x.set(offsetFromCenter); }; const [isCurrentOrigin, setIsCurrentOrigin] = useState(true); useEffect(() => { if (process && URL.canParse(url)) { setIsCurrentOrigin(new URL(url).origin === window.location.origin); } }, [url]); return ( <> {isMounted ? createPortal(
, document.body, ) : null} { setOpen(open); }} > {children} {isOpen && ( {`Preview )} ); };