magnetic
jolyui-ui/magneticFreeComponent
jolyui/ui publishes no description for this item.
Live preview
live · rendered by the registry
Rendered by jolyui/ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://jolyui.dev/r/magnetic.jsonSource
1"use client";23import {4 motion,5 type SpringOptions,6 useMotionValue,7 useSpring,8} from "motion/react";9import type React from "react";10import { useEffect, useRef, useState } from "react";1112const SPRING_CONFIG = { stiffness: 26.7, damping: 4.1, mass: 0.2 };1314export type MagneticProps = {15 children: React.ReactNode;16 intensity?: number;17 range?: number;18 actionArea?: "self" | "parent" | "global";19 springOptions?: SpringOptions;20};2122export function Magnetic({23 children,24 intensity = 0.6,25 range = 100,26 actionArea = "self",27 springOptions = SPRING_CONFIG,28}: MagneticProps) {29 const [isHovered, setIsHovered] = useState(false);30 const ref = useRef<HTMLDivElement>(null);3132 const x = useMotionValue(0);33 const y = useMotionValue(0);3435 const springX = useSpring(x, springOptions);36 const springY = useSpring(y, springOptions);3738 useEffect(() => {39 const calculateDistance = (e: MouseEvent) => {40 if (ref.current) {41 const rect = ref.current.getBoundingClientRect();42 const centerX = rect.left + rect.width / 2;43 const centerY = rect.top + rect.height / 2;44 const distanceX = e.clientX - centerX;45 const distanceY = e.clientY - centerY;4647 const absoluteDistance = Math.sqrt(distanceX ** 2 + distanceY ** 2);4849 if (isHovered && absoluteDistance <= range) {50 const scale = 1 - absoluteDistance / range;51 x.set(distanceX * intensity * scale);52 y.set(distanceY * intensity * scale);53 } else {54 x.set(0);55 y.set(0);56 }57 }58 };5960 document.addEventListener("mousemove", calculateDistance);6162 return () => {63 document.removeEventListener("mousemove", calculateDistance);64 };65 }, [isHovered, intensity, range, x.set, y.set, y, x]);6667 useEffect(() => {68 if (actionArea === "parent" && ref.current?.parentElement) {69 const parent = ref.current.parentElement;7071 const handleParentEnter = () => setIsHovered(true);72 const handleParentLeave = () => setIsHovered(false);7374 parent.addEventListener("mouseenter", handleParentEnter);75 parent.addEventListener("mouseleave", handleParentLeave);7677 return () => {78 parent.removeEventListener("mouseenter", handleParentEnter);79 parent.removeEventListener("mouseleave", handleParentLeave);80 };81 } else if (actionArea === "global") {82 setIsHovered(true);83 }84 }, [actionArea]);8586 const handleMouseEnter = () => {87 if (actionArea === "self") {88// … truncated
What it pulls in
npm packages
Files it writes
More from jolyui/ui
All 199 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| ai-prompt-boxai-prompt-box | jolyui/ui | Components | Free | 4 deps | |
| animated-beamanimated-beam | jolyui/ui | Components | Free | 1 dep | |
| animated-tableanimated-table | jolyui/ui | Components | Free | 2 deps | |
| animated-theme-toggleanimated-theme-toggle | jolyui/ui | Components | Free | 2 deps | |
| animated-toastanimated-toast | jolyui/ui | Components | Free | 2 deps | |
| animated-tooltipanimated-tooltip | jolyui/ui | Components | Free | 1 dep | |
| bento-gridbento-grid | jolyui/ui | Components | Free | no deps | |
| buttonbutton | jolyui/ui | Components | Free | 3 deps |
