UNPKG

xlibs-components

Version:

Modern React component library with Aceternity, MagicUI, and ShadCN components for building beautiful web applications

29 lines (28 loc) 3.25 kB
"use client"; import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { useRef, useEffect, useState } from "react"; import { motion } from "framer-motion"; export const TextHoverEffect = ({ text, duration, }) => { const svgRef = useRef(null); const [cursor, setCursor] = useState({ x: 0, y: 0 }); const [hovered, setHovered] = useState(false); const [maskPosition, setMaskPosition] = useState({ cx: "50%", cy: "50%" }); useEffect(() => { if (svgRef.current && cursor.x !== null && cursor.y !== null) { const svgRect = svgRef.current.getBoundingClientRect(); const cxPercentage = ((cursor.x - svgRect.left) / svgRect.width) * 100; const cyPercentage = ((cursor.y - svgRect.top) / svgRect.height) * 100; setMaskPosition({ cx: `${cxPercentage}%`, cy: `${cyPercentage}%`, }); } }, [cursor]); return (_jsxs("svg", { ref: svgRef, width: "100%", height: "100%", viewBox: "0 0 300 100", xmlns: "http://www.w3.org/2000/svg", onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), onMouseMove: (e) => setCursor({ x: e.clientX, y: e.clientY }), className: "select-none", children: [_jsxs("defs", { children: [_jsx("linearGradient", { id: "textGradient", gradientUnits: "userSpaceOnUse", cx: "50%", cy: "50%", r: "25%", children: hovered && (_jsxs(_Fragment, { children: [_jsx("stop", { offset: "0%", stopColor: "#eab308" }), _jsx("stop", { offset: "25%", stopColor: "#ef4444" }), _jsx("stop", { offset: "50%", stopColor: "#3b82f6" }), _jsx("stop", { offset: "75%", stopColor: "#06b6d4" }), _jsx("stop", { offset: "100%", stopColor: "#8b5cf6" })] })) }), _jsxs(motion.radialGradient, { id: "revealMask", gradientUnits: "userSpaceOnUse", r: "20%", initial: { cx: "50%", cy: "50%" }, animate: maskPosition, transition: { duration: duration ?? 0, ease: "easeOut" }, children: [_jsx("stop", { offset: "0%", stopColor: "white" }), _jsx("stop", { offset: "100%", stopColor: "black" })] }), _jsx("mask", { id: "textMask", children: _jsx("rect", { x: "0", y: "0", width: "100%", height: "100%", fill: "url(#revealMask)" }) })] }), _jsx("text", { x: "50%", y: "50%", textAnchor: "middle", dominantBaseline: "middle", strokeWidth: "0.3", className: "fill-transparent stroke-neutral-200 font-[helvetica] text-7xl font-bold dark:stroke-neutral-800", style: { opacity: hovered ? 0.7 : 0 }, children: text }), _jsx(motion.text, { x: "50%", y: "50%", textAnchor: "middle", dominantBaseline: "middle", strokeWidth: "0.3", className: "fill-transparent stroke-neutral-200 font-[helvetica] text-7xl font-bold dark:stroke-neutral-800", initial: { strokeDashoffset: 1000, strokeDasharray: 1000 }, animate: { strokeDashoffset: 0, strokeDasharray: 1000, }, transition: { duration: 4, ease: "easeInOut", }, children: text }), _jsx("text", { x: "50%", y: "50%", textAnchor: "middle", dominantBaseline: "middle", stroke: "url(#textGradient)", strokeWidth: "0.3", mask: "url(#textMask)", className: "fill-transparent font-[helvetica] text-7xl font-bold", children: text })] })); };