UNPKG

lightswind

Version:

A professionally designed animate react component library & templates market that brings together functionality, accessibility, and beautiful aesthetics for modern applications.

65 lines (64 loc) 3.7 kB
"use client"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useState, useEffect } from "react"; import { motion, useMotionValue, useSpring } from "framer-motion"; import { MoveUpRight as ArrowIcon } from "lucide-react"; const visualData = [ { key: 1, url: "https://images.pexels.com/photos/9002742/pexels-photo-9002742.jpeg", label: "Pinky Island", }, { key: 2, url: "https://images.pexels.com/photos/31622979/pexels-photo-31622979.jpeg", label: "Greedy Model", }, { key: 3, url: "https://images.pexels.com/photos/12187128/pexels-photo-12187128.jpeg", label: "Sigma Connect", }, { key: 4, url: "https://images.pexels.com/photos/28168248/pexels-photo-28168248.jpeg", label: "Futuristic Gamma", }, ]; const ImageReveal = () => { const [focusedItem, setFocusedItem] = useState(null); const [isLargeScreen, setIsLargeScreen] = useState(true); const cursorX = useMotionValue(0); const cursorY = useMotionValue(0); const smoothX = useSpring(cursorX, { stiffness: 300, damping: 40 }); const smoothY = useSpring(cursorY, { stiffness: 300, damping: 40 }); useEffect(() => { const updateScreen = () => { setIsLargeScreen(window.innerWidth >= 768); }; updateScreen(); window.addEventListener("resize", updateScreen); return () => window.removeEventListener("resize", updateScreen); }, []); const onMouseTrack = (e) => { cursorX.set(e.clientX); cursorY.set(e.clientY); }; const onHoverActivate = (item) => { setFocusedItem(item); }; const onHoverDeactivate = () => { setFocusedItem(null); }; return (_jsxs("div", { className: "relative mx-auto w-full min-h-fit bg-background rounded-md border overflow-hidden", onMouseMove: onMouseTrack, onMouseLeave: onHoverDeactivate, children: [visualData.map((item) => (_jsxs("div", { className: "p-4 cursor-pointer relative sm:flex items-center justify-between", onMouseEnter: () => onHoverActivate(item), children: [!isLargeScreen && (_jsx("img", { src: item.url, className: "sm:w-32 sm:h-20 w-full h-52 object-cover rounded-md", alt: item.label })), _jsx("h2", { className: `newFont uppercase md:text-5xl sm:text-2xl text-xl font-semibold sm:py-6 py-2 leading-[100%] relative transition-colors duration-300 ${focusedItem?.key === item.key ? "mix-blend-difference z-20 text-gray-300" : "text-foreground"}`, children: item.label }), _jsx("button", { className: `sm:block hidden p-4 rounded-full transition-all duration-300 ease-out ${focusedItem?.key === item.key ? "mix-blend-difference z-20 bg-white text-black" : ""}`, children: _jsx(ArrowIcon, { className: "w-8 h-8" }) }), _jsx("div", { className: `h-[2px] dark:bg-white bg-black absolute bottom-0 left-0 transition-all duration-300 ease-linear ${focusedItem?.key === item.key ? "w-full" : "w-0"}` })] }, item.key))), isLargeScreen && focusedItem && (_jsx(motion.img, { src: focusedItem.url, alt: focusedItem.label, className: "fixed z-30 object-cover w-[300px] h-[400px] rounded-lg pointer-events-none shadow-2xl dark:bg-gray-950 bg-white", style: { left: smoothX, top: smoothY, x: "-50%", y: "-50%", }, initial: { opacity: 0, scale: 0.5 }, animate: { opacity: 1, scale: 1 }, exit: { opacity: 0, scale: 0.5 }, transition: { type: "spring", stiffness: 300, damping: 30 } }))] })); }; export default ImageReveal;