curzr
Version:
Highly customizable animated cursor with dot or liquid trails for React.
3 lines (2 loc) • 2.8 kB
JavaScript
import e,{useState as r,createContext as t,useContext as n,useRef as o,useEffect as s}from"react";const a=t(),i=({theme:t,children:n})=>{const[o,s]=r(!1);return e.createElement(a.Provider,{value:{theme:t,isHovered:o,setIsHovered:s}},n)},d=()=>{const{theme:t,isHovered:i}=n(a),[d,l]=r({x:window.innerWidth/2,y:window.innerHeight/2}),[c,u]=r([]),m=o(!1),x=o({x:window.innerWidth/2,y:window.innerHeight/2}),y=t.trailLength||16,h=t.trailSmoothing||.5,p=t.trailSize||16,b=t.trailColor||"rgba(255,255,255,0.5)";if(t.trailFade,s((()=>{u(Array.from({length:y},(()=>({x:x.current.x,y:x.current.y}))))}),[y]),s((()=>{const e=e=>{const r=e.clientX,t=e.clientY;x.current={x:r,y:t},l({x:r,y:t}),m.current||(u(Array.from({length:y},(()=>({x:r,y:t})))),m.current=!0)};let r;document.addEventListener("mousemove",e);const t=()=>{u((e=>{if(!e.length)return e;const r=[...e];r[0]={x:r[0].x+(x.current.x-r[0].x)*h,y:r[0].y+(x.current.y-r[0].y)*h};for(let e=1;e<y;e++)r[e]={x:r[e].x+(r[e-1].x-r[e].x)*h,y:r[e].y+(r[e-1].y-r[e].y)*h};return r})),r=requestAnimationFrame(t)};return t(),()=>{document.removeEventListener("mousemove",e),cancelAnimationFrame(r)}}),[y,h]),t.enableTrail&&"dots"===t.trailType)return e.createElement(e.Fragment,null,c.map(((r,n)=>{const o=2+(p-2)*(1-n/y),s=o/2;return e.createElement("div",{key:n,className:"cursor-trail-dot",style:{position:"fixed",left:0,top:0,width:`${o}px`,height:`${o}px`,borderRadius:"50%",backgroundColor:b,pointerEvents:"none",zIndex:9998,opacity:Math.pow(1-n/y,2),transform:`translate3d(${r.x-s}px, ${r.y-s}px, 0)`,transition:"opacity 0.2s, transform 0.05s ease-out",mixBlendMode:t.styles?.mixBlendMode||"normal",border:t.styles?.border||"none",boxShadow:t.styles?.boxShadow||"none"}})})));const g=i?t.baseSize*t.hoverScale:t.baseSize;return e.createElement("div",{className:"cursor",style:{...(()=>{switch(t.type){case"dot":default:return{borderRadius:"50%"};case"ring":return{borderRadius:"50%",backgroundColor:"transparent",border:t.styles?.border||"2px solid"};case"square":return{borderRadius:"4px"};case"blob":return{borderRadius:"40% 60% 60% 40% / 50% 40% 60% 50%",transition:"all 0.3s ease-out"};case"custom":return{backgroundImage:`url(${t.customShape})`,backgroundSize:"cover"}}})(),...t.styles,width:`${g}px`,height:`${g}px`,backgroundColor:t.color,position:"fixed",top:0,left:0,pointerEvents:"none",mixBlendMode:t.styles?.mixBlendMode||"normal",transform:`translate3d(${d.x}px, ${d.y}px, 0) translate(-50%, -50%)`,zIndex:t.zIndex||9999,transition:t.transition||"width 0.25s ease, height 0.25s ease, background-color 0.25s ease, transform 0.3s ease-out"}})},l=()=>{const{setIsHovered:e}=n(a);return{onMouseEnter:()=>e(!0),onMouseLeave:()=>e(!1)}};export{d as Cursor,i as CursorProvider,d as default,l as useCursorHover};
//# sourceMappingURL=index.es.js.map