@yhattav/react-component-cursor
Version:
A lightweight, TypeScript-first React library for creating beautiful custom cursors with SSR support, smooth animations, and zero dependencies. Perfect for interactive websites, games, and creative applications.
30 lines (29 loc) • 6.4 kB
JavaScript
import {d,f,a,b}from'./chunk-IYYPIASE.mjs';export{e as browserOnly,c as isBrowser,b as isSSR,f as safeDocument,g as safeWindow}from'./chunk-IYYPIASE.mjs';import*as o from'react';import {useState,useRef,useCallback,useEffect}from'react';import {createPortal}from'react-dom';function k(t,e,a,m,b=0){let[r,u]=useState({x:null,y:null}),[s,d]=useState({x:null,y:null}),p=useRef(false),v=s.x!==null&&s.y!==null,x=useCallback(i=>{let C={x:i.x+a,y:i.y+m};if(e!=null&&e.current){let y=e.current.getBoundingClientRect(),$=i.x>=y.left&&i.x<=y.right&&i.y>=y.top&&i.y<=y.bottom;d($?C:{x:null,y:null});}else d(C);},[e,a,m]),h=useCallback(i=>{x(i);},[x]);return useEffect(()=>{if(!(e!=null&&e.current))return;let i=e.current,C=()=>{d({x:null,y:null});};return i.addEventListener("mouseleave",C),()=>{i.removeEventListener("mouseleave",C);}},[e]),useEffect(()=>{let i=false,C={unsubscribe:null};return import('./CursorCoordinator-M32HDHIO.mjs').then(({CursorCoordinator:y})=>{if(i)return;let $=y.getInstance();C.unsubscribe=$.subscribe({id:t,onPositionChange:h,throttleMs:b});}).catch(y=>{console.warn("Failed to load cursor coordinator:",y);}),()=>{var y;i=true,(y=C.unsubscribe)==null||y.call(C);}},[t,b,h]),useEffect(()=>{s.x!==null&&s.y!==null&&!p.current&&(u(s),p.current=true);},[s]),{position:r,setPosition:u,targetPosition:s,isVisible:v}}var K=.1;function O(t,e,a){let m=useCallback(r=>{if(r.x===null||r.y===null||t.x===null||t.y===null)return r;let u=t.x-r.x,s=t.y-r.y;return Math.abs(u)<K&&Math.abs(s)<K?r:{x:r.x+u/e,y:r.y+s/e}},[t.x,t.y,e]),b$1=useCallback(()=>{let r,u=()=>{a(s=>{let d=m(s);return d.x===s.x&&d.y===s.y?s:d}),r=requestAnimationFrame(u);};return r=requestAnimationFrame(u),()=>{r&&cancelAnimationFrame(r);}},[m,a,t]);useEffect(()=>{var s;if(b())return;let r=typeof window!="undefined"&&window.matchMedia?window.matchMedia("(prefers-reduced-motion: reduce)"):null,u=(s=r==null?void 0:r.matches)!=null?s:false;if(e<=1||u){a(t);return}return b$1()},[e,t.x,t.y,b$1,a]);}var ne="0.3s",T="cursorFadeIn",ie=9999,ue=({position:t,show:e})=>{return null},ae=(t,e)=>{var u,s,d,p,v,x;if(t.id!==e.id||t.enabled!==e.enabled||t.className!==e.className||t.zIndex!==e.zIndex||t.smoothness!==e.smoothness||t.centered!==e.centered||t.throttleMs!==e.throttleMs||t.showDevIndicator!==e.showDevIndicator||((u=t.offset)==null?void 0:u.x)!==((s=e.offset)==null?void 0:s.x)||((d=t.offset)==null?void 0:d.y)!==((p=e.offset)==null?void 0:p.y)||((v=t.containerRef)==null?void 0:v.current)!==((x=e.containerRef)==null?void 0:x.current))return false;let a=t.style||{},m=e.style||{},b=Object.keys(a),r=Object.keys(m);if(b.length!==r.length)return false;for(let h of b)if(a[h]!==m[h])return false;return !(t.onMove!==e.onMove||t.onVisibilityChange!==e.onVisibilityChange||t.children!==e.children)},le=()=>`cursor-${Math.random().toString(36).substr(2,9)}-${Date.now().toString(36)}`,W=o.memo(({id:t,enabled:e=true,children:a$1,className:m="",style:b$1={},zIndex:r=ie,offset:u={x:0,y:0},smoothness:s=1,containerRef:d$1,centered:p=true,throttleMs:v=0,showDevIndicator:x=true,onMove:h,onVisibilityChange:i,"data-testid":C,role:y,"aria-label":$})=>{let R=o.useMemo(()=>t||le(),[t]);let V=o.useMemo(()=>({x:typeof u=="object"?u.x:0,y:typeof u=="object"?u.y:0}),[u]),E=o.useMemo(()=>d(),[]),G=k(R,d$1,V.x,V.y,v),{position:c,setPosition:Z,targetPosition:J,isVisible:I}=G;O(J,s,Z);let[A,X]=o.useState(null),H=o.useCallback(()=>{let n=f();if(!n)return null;let f$1=n.getElementById("cursor-container");if(f$1)return f$1.style.zIndex=r.toString(),f$1;let l=n.createElement("div");return l.id="cursor-container",l.style.position="fixed",l.style.top="0",l.style.left="0",l.style.pointerEvents="none",l.style.zIndex=r.toString(),n.body.appendChild(l),l},[r]);o.useEffect(()=>(X(H()),()=>{let n=f();if(!n)return;let f$1=n.getElementById("cursor-container");if(f$1&&f$1.children.length===0)try{f$1.parentNode&&f$1.parentNode.removeChild(f$1);}catch(l){console.warn("Portal container cleanup failed:",l);}}),[H]);let j=o.useMemo(()=>{let n=p?" translate(-50%, -50%)":"";return `
@keyframes ${T} {
from {
opacity: 0;
transform: translate(var(--cursor-x), var(--cursor-y))${n} scale(0.8);
}
to {
opacity: 1;
transform: translate(var(--cursor-x), var(--cursor-y))${n} scale(1);
}
}
@media (prefers-reduced-motion: reduce) {
@keyframes ${T} {
from {
opacity: 0;
transform: translate(var(--cursor-x), var(--cursor-y))${n} scale(1);
}
to {
opacity: 1;
transform: translate(var(--cursor-x), var(--cursor-y))${n} scale(1);
}
}
}
`},[p]);o.useEffect(()=>{let n=f();if(!n)return;let f$1=`cursor-style-${R}`,l=n.getElementById(f$1);l&&l.remove();let N=n.createElement("style");return N.id=f$1,N.textContent=j,n.head.appendChild(N),()=>{let g=n.getElementById(f$1);if(g)try{g.remove();}catch(w){console.warn("Style cleanup failed:",w);}}},[R,j]);let L=o.useCallback(()=>{if(c.x!==null&&c.y!==null&&typeof h=="function"){let n={x:c.x,y:c.y};h(n);}},[c.x,c.y,h]);o.useEffect(()=>{L();},[L]);let _=o.useCallback(()=>{typeof i=="function"&&i(e&&I,e?"container":"disabled");},[e,I,i]);if(o.useEffect(()=>{_();},[_]),o.useEffect(()=>{E&&typeof i=="function"&&i(false,"touch");},[E,i]),E)return null;let Q=o.useMemo(()=>{var l,N,g,w;let n=`translate(${(l=c.x)!=null?l:0}px, ${(N=c.y)!=null?N:0}px)`;return a({position:"fixed",top:0,left:0,transform:n+(p?" translate(-50%, -50%)":""),pointerEvents:"none",zIndex:r,opacity:1,visibility:"visible",animation:`${T} ${ne} ease-out`,"--cursor-x":`${(g=c.x)!=null?g:0}px`,"--cursor-y":`${(w=c.y)!=null?w:0}px`},b$1)},[c.x,c.y,r,p,b$1]),Y=o.useMemo(()=>`
#cursor-container {
pointer-events: none !important;
}
`,[]);return !b()&&e&&I&&c.x!==null&&c.y!==null&&A?o.createElement(o.Fragment,null,o.createElement("style",{id:`cursor-style-global-${R}`},Y),createPortal(o.createElement(o.Fragment,{key:`cursor-${R}`},o.createElement("div",{id:`custom-cursor-${R}`,style:Q,className:m,"aria-hidden":"true","data-testid":C,role:y,"aria-label":$},a$1),o.createElement(ue,{position:c,show:x})),A)):null},ae);W.displayName="CustomCursor";var ce=W;export{ce as CustomCursor};//# sourceMappingURL=index.mjs.map
//# sourceMappingURL=index.mjs.map