@tonybonet/magnetic 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/README.md +2 -2
- package/dist/Magnetic.cjs +1 -2
- package/dist/types.cjs +1 -2
- package/dist/useMagnetic-hzN5_pe4.cjs +1 -2
- package/package.json +37 -30
- package/dist/Magnetic.cjs.map +0 -1
- package/dist/Magnetic.d.cts.map +0 -1
- package/dist/Magnetic.d.mts.map +0 -1
- package/dist/Magnetic.mjs.map +0 -1
- package/dist/types.cjs.map +0 -1
- package/dist/types.d.cts.map +0 -1
- package/dist/types.d.mts.map +0 -1
- package/dist/types.mjs.map +0 -1
- package/dist/useMagnetic-Cih9JSy3.mjs.map +0 -1
- package/dist/useMagnetic-hzN5_pe4.cjs.map +0 -1
- package/dist/useMagnetic.d.cts.map +0 -1
- package/dist/useMagnetic.d.mts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.0] - 2026-05-17
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Removed sourcemaps from published package (cleaner dist, smaller install size)
|
|
13
|
+
- Added `engines.node >= 18.0.0` field
|
|
14
|
+
- Added `publint` and `attw` dev scripts for publish validation
|
|
15
|
+
|
|
8
16
|
## [0.1.0] - 2026-05-15
|
|
9
17
|
|
|
10
18
|
### Added
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Antonio Bonet
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -65,8 +65,8 @@ import { TACTILE, SMOOTH, BOUNCY_SNAP } from "@tonybonet/magnetic/presets";
|
|
|
65
65
|
|
|
66
66
|
## Exports
|
|
67
67
|
|
|
68
|
-
| Subpath
|
|
69
|
-
|
|
|
68
|
+
| Subpath | What |
|
|
69
|
+
| ------------------------------- | -------------------------------------------------------------------------------------------- |
|
|
70
70
|
| `@tonybonet/magnetic` | `useMagnetic` hook + `UseMagneticResult` type |
|
|
71
71
|
| `@tonybonet/magnetic/component` | `Magnetic` JSX component + `MagneticProps` type |
|
|
72
72
|
| `@tonybonet/magnetic/presets` | `TACTILE`, `SMOOTH`, `BOUNCY_SNAP`, `LINEAR_RESET`, `MAGNET_DEFAULTS` + `MagnetOptions` type |
|
package/dist/Magnetic.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./types.cjs`),t=require(`./useMagnetic-hzN5_pe4.cjs`);let n=require(`motion/react`),r=require(`react`),i=require(`react/jsx-runtime`);function a(e){return!!e&&typeof e==`object`&&`current`in e}function o(e,t){if(typeof e==`function`)return e(t);a(e)&&(e.current=t)}function s(t){return`${t?.enabled??e.MAGNET_DEFAULTS.enabled}|${t?.maxDistance??e.MAGNET_DEFAULTS.maxDistance}|${t?.maxOffset??e.MAGNET_DEFAULTS.maxOffset}|${t?.elastic??e.MAGNET_DEFAULTS.elastic}|${t?.originX??e.MAGNET_DEFAULTS.originX}|${t?.originY??e.MAGNET_DEFAULTS.originY}`}function c({options:e,style:a,children:s,forwardedRef:c,...l}){let u=t.t(e),d=(0,r.useRef)(null);d.current===null?d.current={externalRef:c,magneticRef:u.ref}:(d.current.externalRef=c,d.current.magneticRef=u.ref);let f=(0,r.useRef)(null);f.current===null&&(f.current=e=>{let t=d.current,n=o(t.externalRef,e),r=t.magneticRef(e);return()=>{typeof r==`function`&&r(),typeof n==`function`&&n()}});let p=f.current;return(0,i.jsx)(n.m.div,{...l,ref:p,style:{...a,...u.style},children:s})}function l({children:e}){return(0,i.jsx)(n.LazyMotion,{features:n.domAnimation,strict:!0,children:e})}function u({options:t,magneticKey:r,style:a,children:o,ref:u,...d}){let f=(0,n.useReducedMotion)();if(!((t?.enabled??e.MAGNET_DEFAULTS.enabled)&&!f))return(0,i.jsx)(l,{children:(0,i.jsx)(n.m.div,{...d,ref:u,style:a,children:o})});let p=r??s(t);return(0,i.jsx)(l,{children:(0,i.jsx)(c,{options:t,style:a,forwardedRef:u,...d,children:o},p)})}u.displayName=`Magnetic`,exports.Magnetic=u;
|
|
2
|
-
//# sourceMappingURL=Magnetic.cjs.map
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./types.cjs`),t=require(`./useMagnetic-hzN5_pe4.cjs`);let n=require(`motion/react`),r=require(`react`),i=require(`react/jsx-runtime`);function a(e){return!!e&&typeof e==`object`&&`current`in e}function o(e,t){if(typeof e==`function`)return e(t);a(e)&&(e.current=t)}function s(t){return`${t?.enabled??e.MAGNET_DEFAULTS.enabled}|${t?.maxDistance??e.MAGNET_DEFAULTS.maxDistance}|${t?.maxOffset??e.MAGNET_DEFAULTS.maxOffset}|${t?.elastic??e.MAGNET_DEFAULTS.elastic}|${t?.originX??e.MAGNET_DEFAULTS.originX}|${t?.originY??e.MAGNET_DEFAULTS.originY}`}function c({options:e,style:a,children:s,forwardedRef:c,...l}){let u=t.t(e),d=(0,r.useRef)(null);d.current===null?d.current={externalRef:c,magneticRef:u.ref}:(d.current.externalRef=c,d.current.magneticRef=u.ref);let f=(0,r.useRef)(null);f.current===null&&(f.current=e=>{let t=d.current,n=o(t.externalRef,e),r=t.magneticRef(e);return()=>{typeof r==`function`&&r(),typeof n==`function`&&n()}});let p=f.current;return(0,i.jsx)(n.m.div,{...l,ref:p,style:{...a,...u.style},children:s})}function l({children:e}){return(0,i.jsx)(n.LazyMotion,{features:n.domAnimation,strict:!0,children:e})}function u({options:t,magneticKey:r,style:a,children:o,ref:u,...d}){let f=(0,n.useReducedMotion)();if(!((t?.enabled??e.MAGNET_DEFAULTS.enabled)&&!f))return(0,i.jsx)(l,{children:(0,i.jsx)(n.m.div,{...d,ref:u,style:a,children:o})});let p=r??s(t);return(0,i.jsx)(l,{children:(0,i.jsx)(c,{options:t,style:a,forwardedRef:u,...d,children:o},p)})}u.displayName=`Magnetic`,exports.Magnetic=u;
|
package/dist/types.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e={stiffness:400,damping:30,mass:.5},t={stiffness:150,damping:20,mass:1.2},n={stiffness:400,damping:20,mass:.5,restDelta:.001},r={stiffness:200,damping:50,mass:1},i={enabled:!0,maxDistance:320,maxOffset:64,originX:.5,originY:.5,elastic:!0,smooth:!0,snap:!0,smoothSpring:t,snapSpring:n,trigger:`distance`};exports.BOUNCY_SNAP=n,exports.LINEAR_RESET=r,exports.MAGNET_DEFAULTS=i,exports.SMOOTH=t,exports.TACTILE=e;
|
|
2
|
-
//# sourceMappingURL=types.cjs.map
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e={stiffness:400,damping:30,mass:.5},t={stiffness:150,damping:20,mass:1.2},n={stiffness:400,damping:20,mass:.5,restDelta:.001},r={stiffness:200,damping:50,mass:1},i={enabled:!0,maxDistance:320,maxOffset:64,originX:.5,originY:.5,elastic:!0,smooth:!0,snap:!0,smoothSpring:t,snapSpring:n,trigger:`distance`};exports.BOUNCY_SNAP=n,exports.LINEAR_RESET=r,exports.MAGNET_DEFAULTS=i,exports.SMOOTH=t,exports.TACTILE=e;
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
const e=require(`./types.cjs`);let t=require(`motion/react`),n=require(`react`);var r=class{elements=new Map;activeElements=new Set;intersectionObserver=null;resizeObserver=null;trackedCount=0;distanceCount=0;listenersAttached=!1;rafId=null;framePending=!1;needsInvalidate=!1;hasPointer=!1;pointerX=0;pointerY=0;constructor(){typeof window>`u`||(typeof IntersectionObserver<`u`&&(this.intersectionObserver=new IntersectionObserver(e=>{for(let t of e){let e=t.target,n=this.elements.get(e);if(n){if(n.isIntersecting=t.isIntersecting,t.isIntersecting){n.options.trigger===`distance`&&this.activeElements.add(e),n.rect=null,this.requestFrame();continue}this.activeElements.delete(e),this.setActive(n,!1),this.reset(n)}}},{root:null,rootMargin:`80px`,threshold:0})),typeof ResizeObserver<`u`&&(this.resizeObserver=new ResizeObserver(e=>{for(let t of e){let e=this.elements.get(t.target);e&&(e.rect=null,this.requestFrame())}})),this.handlePointerMove=this.handlePointerMove.bind(this),this.handleInvalidate=this.handleInvalidate.bind(this),this.handleWindowBlur=this.handleWindowBlur.bind(this),this.handleVisibilityChange=this.handleVisibilityChange.bind(this),this.tick=this.tick.bind(this))}register(t,n,r,i={},a){this.elements.has(t)&&this.unregister(t);let o={...e.MAGNET_DEFAULTS,...i},s={x:n,y:r,options:o,rect:null,isIntersecting:!this.intersectionObserver,isActive:!1,onActiveChange:a};this.elements.set(t,s),this.trackedCount+=1,o.trigger===`distance`?(this.distanceCount+=1,s.isIntersecting&&this.activeElements.add(t)):o.trigger===`hover`?this.setupHoverMode(t,s):o.trigger===`click`&&this.setupClickMode(t,s),this.intersectionObserver?.observe(t),this.resizeObserver?.observe(t),this.trackedCount===1&&this.start()}unregister(e){let t=this.elements.get(e);t&&(this.intersectionObserver?.unobserve(e),this.resizeObserver?.unobserve(e),this.activeElements.delete(e),t.options.trigger===`distance`&&(this.distanceCount=Math.max(0,this.distanceCount-1)),t.cleanup?.(),this.setActive(t,!1),this.reset(t),this.elements.delete(e),this.trackedCount=Math.max(0,this.trackedCount-1),this.trackedCount===0&&this.stop())}setupHoverMode(e,t){let n=n=>{let r=e.getBoundingClientRect(),i=n.clientX>=r.left&&n.clientX<=r.right&&n.clientY>=r.top&&n.clientY<=r.bottom;i&&!t.isActive?(t.rect=r,this.setActive(t,!0)):!i&&t.isActive&&(this.setActive(t,!1),this.reset(t),t.rect=null),t.isActive&&this.updateMagnetic(e,t,n.clientX,n.clientY)},r=()=>{t.isActive&&(this.setActive(t,!1),this.reset(t),t.rect=null)};window.addEventListener(`pointermove`,n),e.addEventListener(`pointerleave`,r),t.cleanup=()=>{window.removeEventListener(`pointermove`,n),e.removeEventListener(`pointerleave`,r)}}setupClickMode(e,t){let n=!1,r=0,i=0,a=0,o=0,s=s=>{if(e.contains(s.target)){if(n){n=!1,e.style.cursor=`grab`,this.setActive(t,!1),this.reset(t),t.rect=null;return}t.rect=e.getBoundingClientRect(),a=t.rect.left+t.rect.width/2,o=t.rect.top+t.rect.height/2,r=s.clientX-a,i=s.clientY-o,n=!0,e.style.cursor=`grabbing`,this.setActive(t,!0)}},c=e=>{if(!n)return;let s=e.clientX-r-a,c=e.clientY-i-o;this.setTarget(t,s,c)},l=()=>{n&&(n=!1,e.style.cursor=`grab`,this.setActive(t,!1),this.reset(t),t.rect=null)};e.style.cursor=`grab`,window.addEventListener(`pointerdown`,s),window.addEventListener(`pointermove`,c),window.addEventListener(`pointerup`,l),t.cleanup=()=>{e.style.cursor=``,window.removeEventListener(`pointerdown`,s),window.removeEventListener(`pointermove`,c),window.removeEventListener(`pointerup`,l)}}updateMagnetic(e,t,n,r){t.rect||=e.getBoundingClientRect();let i=t.rect,{maxDistance:a,maxOffset:o,elastic:s,originX:c,originY:l}=t.options,u=i.left+i.width*c,d=i.top+i.height*l,f=n-u,p=r-d,m=f*f+p*p;if(m>=a*a){this.setActive(t,!1),this.reset(t);return}this.setActive(t,!0);let h=Math.sqrt(m),g=Math.min(1,h/a),_=0,v=0;if(s){let e=Math.sin(Math.PI/2*g)*o,t=f/(h||1),n=p/(h||1);_=t*e,v=n*e}else _=f/a*o,v=p/a*o;this.setTarget(t,_,v)}start(){this.listenersAttached||(this.listenersAttached=!0,window.addEventListener(`pointermove`,this.handlePointerMove,{passive:!0}),window.addEventListener(`scroll`,this.handleInvalidate,{passive:!0,capture:!0}),window.addEventListener(`resize`,this.handleInvalidate,{passive:!0}),window.addEventListener(`blur`,this.handleWindowBlur),document.addEventListener(`visibilitychange`,this.handleVisibilityChange))}stop(){this.listenersAttached&&(this.listenersAttached=!1,window.removeEventListener(`pointermove`,this.handlePointerMove),window.removeEventListener(`scroll`,this.handleInvalidate,{capture:!0}),window.removeEventListener(`resize`,this.handleInvalidate),window.removeEventListener(`blur`,this.handleWindowBlur),document.removeEventListener(`visibilitychange`,this.handleVisibilityChange),this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.framePending=!1,this.needsInvalidate=!1,this.hasPointer=!1)}handlePointerMove(e){this.pointerX=e.clientX,this.pointerY=e.clientY,this.hasPointer=!0,this.requestFrame()}handleInvalidate(){this.needsInvalidate=!0,this.requestFrame()}handleWindowBlur(){this.hasPointer=!1,this.resetAllActive()}handleVisibilityChange(){document.hidden&&(this.hasPointer=!1,this.resetAllActive())}requestFrame(){!this.listenersAttached||this.framePending||(this.framePending=!0,this.rafId=requestAnimationFrame(this.tick))}tick(){if(this.framePending=!1,this.rafId=null,this.listenersAttached&&(this.needsInvalidate&&this.invalidateVisibleRects(),!(!this.hasPointer||this.distanceCount===0)))for(let e of this.activeElements){let t=this.elements.get(e);if(!t||t.options.trigger!==`distance`||!t.isIntersecting)continue;t.rect||=e.getBoundingClientRect();let n=t.rect,{maxDistance:r,maxOffset:i,elastic:a,originX:o,originY:s}=t.options,c=n.left+n.width*o,l=n.top+n.height*s,u=this.pointerX-c,d=this.pointerY-l,f=u*u+d*d;if(f>=r*r){this.setActive(t,!1),this.reset(t);continue}this.setActive(t,!0);let p=Math.sqrt(f),m=Math.min(1,p/r),h=0,g=0;if(a){let e=Math.sin(Math.PI/2*m)*i,t=u/(p||1),n=d/(p||1);h=t*e,g=n*e}else h=u/r*i,g=d/r*i;this.setTarget(t,h,g)}}setActive(e,t){e.isActive!==t&&(e.isActive=t,e.onActiveChange?.(t))}setTarget(e,t,n){e.x.set(t),e.y.set(n)}reset(e){this.setTarget(e,0,0)}invalidateVisibleRects(){this.needsInvalidate=!1;for(let e of this.activeElements){let t=this.elements.get(e);t&&(t.rect=null)}}resetAllActive(){for(let e of this.activeElements){let t=this.elements.get(e);t&&(this.setActive(t,!1),this.reset(t),t.rect=null)}}};let i=null;function a(){return i===null&&(i=new r),i}const o={register(e,t,n,r,i){a().register(e,t,n,r,i)},unregister(e){a().unregister(e)}};function s(t){return{enabled:t?.enabled??e.MAGNET_DEFAULTS.enabled,maxDistance:t?.maxDistance??e.MAGNET_DEFAULTS.maxDistance,maxOffset:t?.maxOffset??e.MAGNET_DEFAULTS.maxOffset,elastic:t?.elastic??e.MAGNET_DEFAULTS.elastic,originX:t?.originX??e.MAGNET_DEFAULTS.originX,originY:t?.originY??e.MAGNET_DEFAULTS.originY,trigger:t?.trigger??e.MAGNET_DEFAULTS.trigger}}function c(t){let n=t?.smooth??e.MAGNET_DEFAULTS.smooth;return{hoverSpring:t?.smoothSpring??(n?e.SMOOTH:e.TACTILE),returnSpring:t?.snap??e.MAGNET_DEFAULTS.snap?t?.snapSpring??e.BOUNCY_SNAP:e.LINEAR_RESET}}function l(e){let r=(0,t.useReducedMotion)(),i=s(e),a=c(e),l=i.enabled&&!r,[u,d]=(0,n.useState)(!1),f=(0,t.useMotionValue)(0),p=(0,t.useMotionValue)(0),m=(0,t.useSpring)(f,u?a.hoverSpring:a.returnSpring),h=(0,t.useSpring)(p,u?a.hoverSpring:a.returnSpring),g=(0,n.useRef)(null),_=(0,n.useRef)(null),v=(0,n.useRef)(null),y=(0,n.useRef)(null),b=(0,n.useRef)(f),x=(0,n.useRef)(p),S=(0,n.useRef)(d);b.current=f,x.current=p,S.current=d;let C=(0,n.useRef)(()=>{b.current.set(0),x.current.set(0),S.current(!1)}).current,w=(0,n.useRef)(null);w.current===null?w.current={enabled:l,structural:i,rawX:f,rawY:p,reset:C,setIsComposing:d,registeredNode:null}:(w.current.enabled=l,w.current.rawX=f,w.current.rawY=p,w.current.reset=C,w.current.setIsComposing=d,w.current.registeredNode===null&&(w.current.structural=i));let T=(0,n.useRef)(null);return T.current===null&&(T.current=e=>{v.current=e;let t=w.current,n=_.current;if(e===t.registeredNode)return n??void 0;if(e===null){n?.(),_.current=null,t.registeredNode=null,g.current=null,t.reset();return}if(n?.(),_.current=null,t.registeredNode=null,!t.enabled){g.current=null,t.reset();return}let r=g.current??t.structural;g.current=r,t.registeredNode=e,o.register(e,t.rawX,t.rawY,r,t.setIsComposing);let i=()=>{o.unregister(e),_.current=null,t.registeredNode===e&&(t.registeredNode=null),g.current=null,t.reset()};return _.current=i,i}),(0,n.useLayoutEffect)(()=>{let e=v.current,t=w.current;if(y.current===null){y.current=l;return}if(y.current===l||(y.current=l,!e))return;if(_.current?.(),_.current=null,t.registeredNode=null,!t.enabled){g.current=null,t.reset();return}let n=g.current??t.structural;g.current=n,t.registeredNode=e,o.register(e,t.rawX,t.rawY,n,t.setIsComposing),_.current=()=>{o.unregister(e),_.current=null,t.registeredNode===e&&(t.registeredNode=null),g.current=null,t.reset()}},[l]),{ref:T.current,x:l?m:f,y:l?h:p,style:l?{x:m,y:h}:{x:f,y:p},enabled:l,isComposing:l&&u,reset:C}}Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return l}});
|
|
2
|
-
//# sourceMappingURL=useMagnetic-hzN5_pe4.cjs.map
|
|
1
|
+
const e=require(`./types.cjs`);let t=require(`motion/react`),n=require(`react`);var r=class{elements=new Map;activeElements=new Set;intersectionObserver=null;resizeObserver=null;trackedCount=0;distanceCount=0;listenersAttached=!1;rafId=null;framePending=!1;needsInvalidate=!1;hasPointer=!1;pointerX=0;pointerY=0;constructor(){typeof window>`u`||(typeof IntersectionObserver<`u`&&(this.intersectionObserver=new IntersectionObserver(e=>{for(let t of e){let e=t.target,n=this.elements.get(e);if(n){if(n.isIntersecting=t.isIntersecting,t.isIntersecting){n.options.trigger===`distance`&&this.activeElements.add(e),n.rect=null,this.requestFrame();continue}this.activeElements.delete(e),this.setActive(n,!1),this.reset(n)}}},{root:null,rootMargin:`80px`,threshold:0})),typeof ResizeObserver<`u`&&(this.resizeObserver=new ResizeObserver(e=>{for(let t of e){let e=this.elements.get(t.target);e&&(e.rect=null,this.requestFrame())}})),this.handlePointerMove=this.handlePointerMove.bind(this),this.handleInvalidate=this.handleInvalidate.bind(this),this.handleWindowBlur=this.handleWindowBlur.bind(this),this.handleVisibilityChange=this.handleVisibilityChange.bind(this),this.tick=this.tick.bind(this))}register(t,n,r,i={},a){this.elements.has(t)&&this.unregister(t);let o={...e.MAGNET_DEFAULTS,...i},s={x:n,y:r,options:o,rect:null,isIntersecting:!this.intersectionObserver,isActive:!1,onActiveChange:a};this.elements.set(t,s),this.trackedCount+=1,o.trigger===`distance`?(this.distanceCount+=1,s.isIntersecting&&this.activeElements.add(t)):o.trigger===`hover`?this.setupHoverMode(t,s):o.trigger===`click`&&this.setupClickMode(t,s),this.intersectionObserver?.observe(t),this.resizeObserver?.observe(t),this.trackedCount===1&&this.start()}unregister(e){let t=this.elements.get(e);t&&(this.intersectionObserver?.unobserve(e),this.resizeObserver?.unobserve(e),this.activeElements.delete(e),t.options.trigger===`distance`&&(this.distanceCount=Math.max(0,this.distanceCount-1)),t.cleanup?.(),this.setActive(t,!1),this.reset(t),this.elements.delete(e),this.trackedCount=Math.max(0,this.trackedCount-1),this.trackedCount===0&&this.stop())}setupHoverMode(e,t){let n=n=>{let r=e.getBoundingClientRect(),i=n.clientX>=r.left&&n.clientX<=r.right&&n.clientY>=r.top&&n.clientY<=r.bottom;i&&!t.isActive?(t.rect=r,this.setActive(t,!0)):!i&&t.isActive&&(this.setActive(t,!1),this.reset(t),t.rect=null),t.isActive&&this.updateMagnetic(e,t,n.clientX,n.clientY)},r=()=>{t.isActive&&(this.setActive(t,!1),this.reset(t),t.rect=null)};window.addEventListener(`pointermove`,n),e.addEventListener(`pointerleave`,r),t.cleanup=()=>{window.removeEventListener(`pointermove`,n),e.removeEventListener(`pointerleave`,r)}}setupClickMode(e,t){let n=!1,r=0,i=0,a=0,o=0,s=s=>{if(e.contains(s.target)){if(n){n=!1,e.style.cursor=`grab`,this.setActive(t,!1),this.reset(t),t.rect=null;return}t.rect=e.getBoundingClientRect(),a=t.rect.left+t.rect.width/2,o=t.rect.top+t.rect.height/2,r=s.clientX-a,i=s.clientY-o,n=!0,e.style.cursor=`grabbing`,this.setActive(t,!0)}},c=e=>{if(!n)return;let s=e.clientX-r-a,c=e.clientY-i-o;this.setTarget(t,s,c)},l=()=>{n&&(n=!1,e.style.cursor=`grab`,this.setActive(t,!1),this.reset(t),t.rect=null)};e.style.cursor=`grab`,window.addEventListener(`pointerdown`,s),window.addEventListener(`pointermove`,c),window.addEventListener(`pointerup`,l),t.cleanup=()=>{e.style.cursor=``,window.removeEventListener(`pointerdown`,s),window.removeEventListener(`pointermove`,c),window.removeEventListener(`pointerup`,l)}}updateMagnetic(e,t,n,r){t.rect||=e.getBoundingClientRect();let i=t.rect,{maxDistance:a,maxOffset:o,elastic:s,originX:c,originY:l}=t.options,u=i.left+i.width*c,d=i.top+i.height*l,f=n-u,p=r-d,m=f*f+p*p;if(m>=a*a){this.setActive(t,!1),this.reset(t);return}this.setActive(t,!0);let h=Math.sqrt(m),g=Math.min(1,h/a),_=0,v=0;if(s){let e=Math.sin(Math.PI/2*g)*o,t=f/(h||1),n=p/(h||1);_=t*e,v=n*e}else _=f/a*o,v=p/a*o;this.setTarget(t,_,v)}start(){this.listenersAttached||(this.listenersAttached=!0,window.addEventListener(`pointermove`,this.handlePointerMove,{passive:!0}),window.addEventListener(`scroll`,this.handleInvalidate,{passive:!0,capture:!0}),window.addEventListener(`resize`,this.handleInvalidate,{passive:!0}),window.addEventListener(`blur`,this.handleWindowBlur),document.addEventListener(`visibilitychange`,this.handleVisibilityChange))}stop(){this.listenersAttached&&(this.listenersAttached=!1,window.removeEventListener(`pointermove`,this.handlePointerMove),window.removeEventListener(`scroll`,this.handleInvalidate,{capture:!0}),window.removeEventListener(`resize`,this.handleInvalidate),window.removeEventListener(`blur`,this.handleWindowBlur),document.removeEventListener(`visibilitychange`,this.handleVisibilityChange),this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.framePending=!1,this.needsInvalidate=!1,this.hasPointer=!1)}handlePointerMove(e){this.pointerX=e.clientX,this.pointerY=e.clientY,this.hasPointer=!0,this.requestFrame()}handleInvalidate(){this.needsInvalidate=!0,this.requestFrame()}handleWindowBlur(){this.hasPointer=!1,this.resetAllActive()}handleVisibilityChange(){document.hidden&&(this.hasPointer=!1,this.resetAllActive())}requestFrame(){!this.listenersAttached||this.framePending||(this.framePending=!0,this.rafId=requestAnimationFrame(this.tick))}tick(){if(this.framePending=!1,this.rafId=null,this.listenersAttached&&(this.needsInvalidate&&this.invalidateVisibleRects(),!(!this.hasPointer||this.distanceCount===0)))for(let e of this.activeElements){let t=this.elements.get(e);if(!t||t.options.trigger!==`distance`||!t.isIntersecting)continue;t.rect||=e.getBoundingClientRect();let n=t.rect,{maxDistance:r,maxOffset:i,elastic:a,originX:o,originY:s}=t.options,c=n.left+n.width*o,l=n.top+n.height*s,u=this.pointerX-c,d=this.pointerY-l,f=u*u+d*d;if(f>=r*r){this.setActive(t,!1),this.reset(t);continue}this.setActive(t,!0);let p=Math.sqrt(f),m=Math.min(1,p/r),h=0,g=0;if(a){let e=Math.sin(Math.PI/2*m)*i,t=u/(p||1),n=d/(p||1);h=t*e,g=n*e}else h=u/r*i,g=d/r*i;this.setTarget(t,h,g)}}setActive(e,t){e.isActive!==t&&(e.isActive=t,e.onActiveChange?.(t))}setTarget(e,t,n){e.x.set(t),e.y.set(n)}reset(e){this.setTarget(e,0,0)}invalidateVisibleRects(){this.needsInvalidate=!1;for(let e of this.activeElements){let t=this.elements.get(e);t&&(t.rect=null)}}resetAllActive(){for(let e of this.activeElements){let t=this.elements.get(e);t&&(this.setActive(t,!1),this.reset(t),t.rect=null)}}};let i=null;function a(){return i===null&&(i=new r),i}const o={register(e,t,n,r,i){a().register(e,t,n,r,i)},unregister(e){a().unregister(e)}};function s(t){return{enabled:t?.enabled??e.MAGNET_DEFAULTS.enabled,maxDistance:t?.maxDistance??e.MAGNET_DEFAULTS.maxDistance,maxOffset:t?.maxOffset??e.MAGNET_DEFAULTS.maxOffset,elastic:t?.elastic??e.MAGNET_DEFAULTS.elastic,originX:t?.originX??e.MAGNET_DEFAULTS.originX,originY:t?.originY??e.MAGNET_DEFAULTS.originY,trigger:t?.trigger??e.MAGNET_DEFAULTS.trigger}}function c(t){let n=t?.smooth??e.MAGNET_DEFAULTS.smooth;return{hoverSpring:t?.smoothSpring??(n?e.SMOOTH:e.TACTILE),returnSpring:t?.snap??e.MAGNET_DEFAULTS.snap?t?.snapSpring??e.BOUNCY_SNAP:e.LINEAR_RESET}}function l(e){let r=(0,t.useReducedMotion)(),i=s(e),a=c(e),l=i.enabled&&!r,[u,d]=(0,n.useState)(!1),f=(0,t.useMotionValue)(0),p=(0,t.useMotionValue)(0),m=(0,t.useSpring)(f,u?a.hoverSpring:a.returnSpring),h=(0,t.useSpring)(p,u?a.hoverSpring:a.returnSpring),g=(0,n.useRef)(null),_=(0,n.useRef)(null),v=(0,n.useRef)(null),y=(0,n.useRef)(null),b=(0,n.useRef)(f),x=(0,n.useRef)(p),S=(0,n.useRef)(d);b.current=f,x.current=p,S.current=d;let C=(0,n.useRef)(()=>{b.current.set(0),x.current.set(0),S.current(!1)}).current,w=(0,n.useRef)(null);w.current===null?w.current={enabled:l,structural:i,rawX:f,rawY:p,reset:C,setIsComposing:d,registeredNode:null}:(w.current.enabled=l,w.current.rawX=f,w.current.rawY=p,w.current.reset=C,w.current.setIsComposing=d,w.current.registeredNode===null&&(w.current.structural=i));let T=(0,n.useRef)(null);return T.current===null&&(T.current=e=>{v.current=e;let t=w.current,n=_.current;if(e===t.registeredNode)return n??void 0;if(e===null){n?.(),_.current=null,t.registeredNode=null,g.current=null,t.reset();return}if(n?.(),_.current=null,t.registeredNode=null,!t.enabled){g.current=null,t.reset();return}let r=g.current??t.structural;g.current=r,t.registeredNode=e,o.register(e,t.rawX,t.rawY,r,t.setIsComposing);let i=()=>{o.unregister(e),_.current=null,t.registeredNode===e&&(t.registeredNode=null),g.current=null,t.reset()};return _.current=i,i}),(0,n.useLayoutEffect)(()=>{let e=v.current,t=w.current;if(y.current===null){y.current=l;return}if(y.current===l||(y.current=l,!e))return;if(_.current?.(),_.current=null,t.registeredNode=null,!t.enabled){g.current=null,t.reset();return}let n=g.current??t.structural;g.current=n,t.registeredNode=e,o.register(e,t.rawX,t.rawY,n,t.setIsComposing),_.current=()=>{o.unregister(e),_.current=null,t.registeredNode===e&&(t.registeredNode=null),g.current=null,t.reset()}},[l]),{ref:T.current,x:l?m:f,y:l?h:p,style:l?{x:m,y:h}:{x:f,y:p},enabled:l,isComposing:l&&u,reset:C}}Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return l}});
|
package/package.json
CHANGED
|
@@ -1,32 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tonybonet/magnetic",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Pointer-tracking magnetic UI elements for React with spring physics and a shared orchestrator.",
|
|
5
|
-
"
|
|
6
|
-
|
|
5
|
+
"keywords": [
|
|
6
|
+
"animation",
|
|
7
|
+
"cursor",
|
|
8
|
+
"interaction",
|
|
9
|
+
"magnetic",
|
|
10
|
+
"motion",
|
|
11
|
+
"physics",
|
|
12
|
+
"pointer",
|
|
13
|
+
"react",
|
|
14
|
+
"spring",
|
|
15
|
+
"ui"
|
|
16
|
+
],
|
|
7
17
|
"homepage": "https://github.com/tonyblu331/magnetic#readme",
|
|
8
18
|
"bugs": {
|
|
9
19
|
"url": "https://github.com/tonyblu331/magnetic/issues"
|
|
10
20
|
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": "Antonio Bonet",
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18.0.0"
|
|
25
|
+
},
|
|
11
26
|
"repository": {
|
|
12
27
|
"type": "git",
|
|
13
28
|
"url": "git+https://github.com/tonyblu331/magnetic.git",
|
|
14
29
|
"directory": "packages/magnetic"
|
|
15
30
|
},
|
|
16
|
-
"keywords": [
|
|
17
|
-
"magnetic",
|
|
18
|
-
"cursor",
|
|
19
|
-
"pointer",
|
|
20
|
-
"animation",
|
|
21
|
-
"react",
|
|
22
|
-
"motion",
|
|
23
|
-
"spring",
|
|
24
|
-
"physics",
|
|
25
|
-
"ui",
|
|
26
|
-
"interaction"
|
|
27
|
-
],
|
|
28
31
|
"files": [
|
|
29
32
|
"dist",
|
|
33
|
+
"LICENSE",
|
|
30
34
|
"README.md",
|
|
31
35
|
"CHANGELOG.md"
|
|
32
36
|
],
|
|
@@ -71,24 +75,27 @@
|
|
|
71
75
|
"publishConfig": {
|
|
72
76
|
"access": "public"
|
|
73
77
|
},
|
|
74
|
-
"scripts": {
|
|
75
|
-
"build": "vp pack src/useMagnetic.ts src/Magnetic.tsx src/types.ts --dts --format esm --format cjs --deps.never-bundle react --deps.never-bundle motion/react --minify --sourcemap --clean",
|
|
76
|
-
"check": "vp check",
|
|
77
|
-
"test": "vp test"
|
|
78
|
-
},
|
|
79
78
|
"devDependencies": {
|
|
80
|
-
"@
|
|
81
|
-
"@
|
|
82
|
-
"@types/
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
79
|
+
"@arethetypeswrong/cli": "^0.18.2",
|
|
80
|
+
"@testing-library/react": "16.3.2",
|
|
81
|
+
"@types/node": "25.6.2",
|
|
82
|
+
"@types/react": "19.2.14",
|
|
83
|
+
"jsdom": "26.1.0",
|
|
84
|
+
"motion": "12.38.0",
|
|
85
|
+
"publint": "^0.3.21",
|
|
86
|
+
"react": "19.2.6",
|
|
87
|
+
"typescript": "6.0.3",
|
|
88
|
+
"vite-plus": "0.1.20"
|
|
88
89
|
},
|
|
89
90
|
"peerDependencies": {
|
|
90
91
|
"motion": "^12.0.0",
|
|
91
92
|
"react": "^19.0.0"
|
|
92
93
|
},
|
|
93
|
-
"
|
|
94
|
-
|
|
94
|
+
"scripts": {
|
|
95
|
+
"build": "vp pack src/useMagnetic.ts src/Magnetic.tsx src/types.ts --dts --format esm --format cjs --deps.never-bundle react --deps.never-bundle motion/react --minify --clean && node -e \"const fs=require('fs');fs.readdirSync('dist').filter(f=>f.endsWith('.map')).forEach(f=>fs.rmSync('dist/'+f))\"",
|
|
96
|
+
"check": "vp check",
|
|
97
|
+
"test": "vp test",
|
|
98
|
+
"publint": "publint",
|
|
99
|
+
"attw": "attw --pack ."
|
|
100
|
+
}
|
|
101
|
+
}
|
package/dist/Magnetic.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Magnetic.cjs","names":["MAGNET_DEFAULTS","useMagnetic","m","LazyMotion","domAnimation"],"sources":["../src/Magnetic.tsx"],"sourcesContent":["import { useRef, type Key, type MutableRefObject, type ReactNode, type Ref } from \"react\";\nimport {\n LazyMotion,\n domAnimation,\n m,\n useReducedMotion,\n type HTMLMotionProps,\n type MotionStyle,\n} from \"motion/react\";\nimport { useMagnetic } from \"./useMagnetic\";\nimport { MAGNET_DEFAULTS, type MagnetOptions } from \"./types\";\n\ntype MagneticDivProps = HTMLMotionProps<\"div\">;\n\nexport interface MagneticProps extends Omit<MagneticDivProps, \"style\"> {\n options?: MagnetOptions;\n style?: MotionStyle;\n magneticKey?: Key;\n}\n\ntype RefCleanup = void | (() => void);\ntype CleanupRefCallback<T> = (instance: T | null) => RefCleanup;\n\nfunction isMutableRefObject<T>(ref: Ref<T> | undefined): ref is MutableRefObject<T | null> {\n return !!ref && typeof ref === \"object\" && \"current\" in ref;\n}\n\nfunction setForwardedRef<T>(ref: Ref<T> | undefined, node: T | null): RefCleanup {\n if (typeof ref === \"function\") {\n return (ref as CleanupRefCallback<T>)(node);\n }\n\n if (isMutableRefObject(ref)) {\n ref.current = node;\n }\n}\n\nfunction composeStructuralKey(options: MagnetOptions | undefined): string {\n const enabled = options?.enabled ?? MAGNET_DEFAULTS.enabled;\n const maxDistance = options?.maxDistance ?? MAGNET_DEFAULTS.maxDistance;\n const maxOffset = options?.maxOffset ?? MAGNET_DEFAULTS.maxOffset;\n const elastic = options?.elastic ?? MAGNET_DEFAULTS.elastic;\n const originX = options?.originX ?? MAGNET_DEFAULTS.originX;\n const originY = options?.originY ?? MAGNET_DEFAULTS.originY;\n\n return `${enabled}|${maxDistance}|${maxOffset}|${elastic}|${originX}|${originY}`;\n}\n\ninterface MagneticEnabledInnerProps extends Omit<MagneticProps, \"magneticKey\" | \"ref\"> {\n forwardedRef: Ref<HTMLDivElement> | undefined;\n}\n\ninterface MergedRefState {\n externalRef: Ref<HTMLDivElement> | undefined;\n magneticRef: (node: HTMLDivElement | null) => RefCleanup;\n}\n\n/**\n * Inner magnetic branch.\n * Structural options are already hardened by the outer key.\n */\nfunction MagneticEnabledInner({\n options,\n style,\n children,\n forwardedRef,\n ...rest\n}: MagneticEnabledInnerProps) {\n const magnetic = useMagnetic<HTMLDivElement>(options);\n\n const mergedRefStateRef = useRef<MergedRefState | null>(null);\n if (mergedRefStateRef.current === null) {\n mergedRefStateRef.current = {\n externalRef: forwardedRef,\n magneticRef: magnetic.ref,\n };\n } else {\n mergedRefStateRef.current.externalRef = forwardedRef;\n mergedRefStateRef.current.magneticRef = magnetic.ref;\n }\n\n const mergedRefRef = useRef<CleanupRefCallback<HTMLDivElement> | null>(null);\n\n if (mergedRefRef.current === null) {\n mergedRefRef.current = (node) => {\n const state = mergedRefStateRef.current!;\n const externalCleanup = setForwardedRef(state.externalRef, node);\n const magneticCleanup = state.magneticRef(node);\n\n return () => {\n if (typeof magneticCleanup === \"function\") magneticCleanup();\n if (typeof externalCleanup === \"function\") externalCleanup();\n };\n };\n }\n\n const mergedRef = mergedRefRef.current;\n\n return (\n <m.div {...rest} ref={mergedRef} style={{ ...style, ...magnetic.style }}>\n {children}\n </m.div>\n );\n}\n\n/**\n * Wraps children with a `<LazyMotion features={domAnimation} strict>` boundary.\n *\n * Motion deduplicates / unions nested `LazyMotion` providers, so an ancestor\n * `LazyMotion features={domMax}` (or any wider set) supplied by the host app\n * keeps its features inside this subtree.\n *\n * This removes the historical contract that callers must wrap with LazyMotion\n * themselves — `<Magnetic>` is now self-contained.\n */\nfunction MagneticLazyMotion({ children }: { children: ReactNode }) {\n return (\n <LazyMotion features={domAnimation} strict>\n {children}\n </LazyMotion>\n );\n}\n\n/**\n * Public primitive.\n *\n * Structural option changes remount the magnetic instance automatically.\n * `magneticKey` overrides the derived structural key when provided.\n *\n * Owns its own `<LazyMotion features={domAnimation} strict>` boundary; callers\n * no longer need to provide one.\n */\nexport function Magnetic({\n options,\n magneticKey,\n style,\n children,\n ref: forwardedRef,\n ...rest\n}: MagneticProps) {\n const reducedMotion = useReducedMotion();\n const isEnabled = (options?.enabled ?? MAGNET_DEFAULTS.enabled) && !reducedMotion;\n\n if (!isEnabled) {\n return (\n <MagneticLazyMotion>\n <m.div {...rest} ref={forwardedRef} style={style}>\n {children}\n </m.div>\n </MagneticLazyMotion>\n );\n }\n\n const resolvedMagneticKey = magneticKey ?? composeStructuralKey(options);\n\n return (\n <MagneticLazyMotion>\n <MagneticEnabledInner\n key={resolvedMagneticKey}\n options={options}\n style={style}\n forwardedRef={forwardedRef}\n {...rest}\n >\n {children}\n </MagneticEnabledInner>\n </MagneticLazyMotion>\n );\n}\n\nMagnetic.displayName = \"Magnetic\";\n"],"mappings":"0NAuBA,SAAS,EAAsB,EAA4D,CACzF,MAAO,CAAC,CAAC,GAAO,OAAO,GAAQ,UAAY,YAAa,EAG1D,SAAS,EAAmB,EAAyB,EAA4B,CAC/E,GAAI,OAAO,GAAQ,WACjB,OAAQ,EAA8B,EAAK,CAGzC,EAAmB,EAAI,GACzB,EAAI,QAAU,GAIlB,SAAS,EAAqB,EAA4C,CAQxE,MAAO,GAPS,GAAS,SAAWA,EAAAA,gBAAgB,QAOlC,GANE,GAAS,aAAeA,EAAAA,gBAAgB,YAM3B,GALf,GAAS,WAAaA,EAAAA,gBAAgB,UAKV,GAJ9B,GAAS,SAAWA,EAAAA,gBAAgB,QAIK,GAHzC,GAAS,SAAWA,EAAAA,gBAAgB,QAGgB,GAFpD,GAAS,SAAWA,EAAAA,gBAAgB,UAkBtD,SAAS,EAAqB,CAC5B,UACA,QACA,WACA,eACA,GAAG,GACyB,CAC5B,IAAM,EAAWC,EAAAA,EAA4B,EAAQ,CAE/C,GAAA,EAAA,EAAA,QAAkD,KAAK,CACzD,EAAkB,UAAY,KAChC,EAAkB,QAAU,CAC1B,YAAa,EACb,YAAa,EAAS,IACvB,EAED,EAAkB,QAAQ,YAAc,EACxC,EAAkB,QAAQ,YAAc,EAAS,KAGnD,IAAM,GAAA,EAAA,EAAA,QAAiE,KAAK,CAExE,EAAa,UAAY,OAC3B,EAAa,QAAW,GAAS,CAC/B,IAAM,EAAQ,EAAkB,QAC1B,EAAkB,EAAgB,EAAM,YAAa,EAAK,CAC1D,EAAkB,EAAM,YAAY,EAAK,CAE/C,UAAa,CACP,OAAO,GAAoB,YAAY,GAAiB,CACxD,OAAO,GAAoB,YAAY,GAAiB,IAKlE,IAAM,EAAY,EAAa,QAE/B,OACE,EAAA,EAAA,KAACC,EAAAA,EAAE,IAAH,CAAO,GAAI,EAAM,IAAK,EAAW,MAAO,CAAE,GAAG,EAAO,GAAG,EAAS,MAAO,CACpE,WACK,CAAA,CAcZ,SAAS,EAAmB,CAAE,YAAqC,CACjE,OACE,EAAA,EAAA,KAACC,EAAAA,WAAD,CAAY,SAAUC,EAAAA,aAAc,OAAA,GACjC,WACU,CAAA,CAajB,SAAgB,EAAS,CACvB,UACA,cACA,QACA,WACA,IAAK,EACL,GAAG,GACa,CAChB,IAAM,GAAA,EAAA,EAAA,mBAAkC,CAGxC,GAAI,GAFe,GAAS,SAAWJ,EAAAA,gBAAgB,UAAY,CAAC,GAGlE,OACE,EAAA,EAAA,KAAC,EAAD,CAAA,UACE,EAAA,EAAA,KAACE,EAAAA,EAAE,IAAH,CAAO,GAAI,EAAM,IAAK,EAAqB,QACxC,WACK,CAAA,CACW,CAAA,CAIzB,IAAM,EAAsB,GAAe,EAAqB,EAAQ,CAExE,OACE,EAAA,EAAA,KAAC,EAAD,CAAA,UACE,EAAA,EAAA,KAAC,EAAD,CAEW,UACF,QACO,eACd,GAAI,EAEH,WACoB,CAPhB,EAOgB,CACJ,CAAA,CAIzB,EAAS,YAAc"}
|
package/dist/Magnetic.d.cts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Magnetic.d.cts","names":[],"sources":["../src/Magnetic.tsx"],"mappings":";;;;;;KAYK,gBAAA,GAAmB,eAAA;AAAA,UAEP,aAAA,SAAsB,IAAA,CAAK,gBAAA;EAC1C,OAAA,GAAU,aAAA;EACV,KAAA,GAAQ,WAAA;EACR,WAAA,GAAc,GAAA;AAAA;;;AAHhB;;;;;;;iBAsHgB,QAAA,CAAA;EACd,OAAA;EACA,WAAA;EACA,KAAA;EACA,QAAA;EACA,GAAA,EAAK,YAAA;EAAA,GACF;AAAA,GACF,aAAA,GAAa,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBAPA,QAAA;EAAA,IAAQ,WAAA;AAAA"}
|
package/dist/Magnetic.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Magnetic.d.mts","names":[],"sources":["../src/Magnetic.tsx"],"mappings":";;;;;;KAYK,gBAAA,GAAmB,eAAA;AAAA,UAEP,aAAA,SAAsB,IAAA,CAAK,gBAAA;EAC1C,OAAA,GAAU,aAAA;EACV,KAAA,GAAQ,WAAA;EACR,WAAA,GAAc,GAAA;AAAA;;;AAHhB;;;;;;;iBAsHgB,QAAA,CAAA;EACd,OAAA;EACA,WAAA;EACA,KAAA;EACA,QAAA;EACA,GAAA,EAAK,YAAA;EAAA,GACF;AAAA,GACF,aAAA,GAAa,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBAPA,QAAA;EAAA,IAAQ,WAAA;AAAA"}
|
package/dist/Magnetic.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Magnetic.mjs","names":[],"sources":["../src/Magnetic.tsx"],"sourcesContent":["import { useRef, type Key, type MutableRefObject, type ReactNode, type Ref } from \"react\";\nimport {\n LazyMotion,\n domAnimation,\n m,\n useReducedMotion,\n type HTMLMotionProps,\n type MotionStyle,\n} from \"motion/react\";\nimport { useMagnetic } from \"./useMagnetic\";\nimport { MAGNET_DEFAULTS, type MagnetOptions } from \"./types\";\n\ntype MagneticDivProps = HTMLMotionProps<\"div\">;\n\nexport interface MagneticProps extends Omit<MagneticDivProps, \"style\"> {\n options?: MagnetOptions;\n style?: MotionStyle;\n magneticKey?: Key;\n}\n\ntype RefCleanup = void | (() => void);\ntype CleanupRefCallback<T> = (instance: T | null) => RefCleanup;\n\nfunction isMutableRefObject<T>(ref: Ref<T> | undefined): ref is MutableRefObject<T | null> {\n return !!ref && typeof ref === \"object\" && \"current\" in ref;\n}\n\nfunction setForwardedRef<T>(ref: Ref<T> | undefined, node: T | null): RefCleanup {\n if (typeof ref === \"function\") {\n return (ref as CleanupRefCallback<T>)(node);\n }\n\n if (isMutableRefObject(ref)) {\n ref.current = node;\n }\n}\n\nfunction composeStructuralKey(options: MagnetOptions | undefined): string {\n const enabled = options?.enabled ?? MAGNET_DEFAULTS.enabled;\n const maxDistance = options?.maxDistance ?? MAGNET_DEFAULTS.maxDistance;\n const maxOffset = options?.maxOffset ?? MAGNET_DEFAULTS.maxOffset;\n const elastic = options?.elastic ?? MAGNET_DEFAULTS.elastic;\n const originX = options?.originX ?? MAGNET_DEFAULTS.originX;\n const originY = options?.originY ?? MAGNET_DEFAULTS.originY;\n\n return `${enabled}|${maxDistance}|${maxOffset}|${elastic}|${originX}|${originY}`;\n}\n\ninterface MagneticEnabledInnerProps extends Omit<MagneticProps, \"magneticKey\" | \"ref\"> {\n forwardedRef: Ref<HTMLDivElement> | undefined;\n}\n\ninterface MergedRefState {\n externalRef: Ref<HTMLDivElement> | undefined;\n magneticRef: (node: HTMLDivElement | null) => RefCleanup;\n}\n\n/**\n * Inner magnetic branch.\n * Structural options are already hardened by the outer key.\n */\nfunction MagneticEnabledInner({\n options,\n style,\n children,\n forwardedRef,\n ...rest\n}: MagneticEnabledInnerProps) {\n const magnetic = useMagnetic<HTMLDivElement>(options);\n\n const mergedRefStateRef = useRef<MergedRefState | null>(null);\n if (mergedRefStateRef.current === null) {\n mergedRefStateRef.current = {\n externalRef: forwardedRef,\n magneticRef: magnetic.ref,\n };\n } else {\n mergedRefStateRef.current.externalRef = forwardedRef;\n mergedRefStateRef.current.magneticRef = magnetic.ref;\n }\n\n const mergedRefRef = useRef<CleanupRefCallback<HTMLDivElement> | null>(null);\n\n if (mergedRefRef.current === null) {\n mergedRefRef.current = (node) => {\n const state = mergedRefStateRef.current!;\n const externalCleanup = setForwardedRef(state.externalRef, node);\n const magneticCleanup = state.magneticRef(node);\n\n return () => {\n if (typeof magneticCleanup === \"function\") magneticCleanup();\n if (typeof externalCleanup === \"function\") externalCleanup();\n };\n };\n }\n\n const mergedRef = mergedRefRef.current;\n\n return (\n <m.div {...rest} ref={mergedRef} style={{ ...style, ...magnetic.style }}>\n {children}\n </m.div>\n );\n}\n\n/**\n * Wraps children with a `<LazyMotion features={domAnimation} strict>` boundary.\n *\n * Motion deduplicates / unions nested `LazyMotion` providers, so an ancestor\n * `LazyMotion features={domMax}` (or any wider set) supplied by the host app\n * keeps its features inside this subtree.\n *\n * This removes the historical contract that callers must wrap with LazyMotion\n * themselves — `<Magnetic>` is now self-contained.\n */\nfunction MagneticLazyMotion({ children }: { children: ReactNode }) {\n return (\n <LazyMotion features={domAnimation} strict>\n {children}\n </LazyMotion>\n );\n}\n\n/**\n * Public primitive.\n *\n * Structural option changes remount the magnetic instance automatically.\n * `magneticKey` overrides the derived structural key when provided.\n *\n * Owns its own `<LazyMotion features={domAnimation} strict>` boundary; callers\n * no longer need to provide one.\n */\nexport function Magnetic({\n options,\n magneticKey,\n style,\n children,\n ref: forwardedRef,\n ...rest\n}: MagneticProps) {\n const reducedMotion = useReducedMotion();\n const isEnabled = (options?.enabled ?? MAGNET_DEFAULTS.enabled) && !reducedMotion;\n\n if (!isEnabled) {\n return (\n <MagneticLazyMotion>\n <m.div {...rest} ref={forwardedRef} style={style}>\n {children}\n </m.div>\n </MagneticLazyMotion>\n );\n }\n\n const resolvedMagneticKey = magneticKey ?? composeStructuralKey(options);\n\n return (\n <MagneticLazyMotion>\n <MagneticEnabledInner\n key={resolvedMagneticKey}\n options={options}\n style={style}\n forwardedRef={forwardedRef}\n {...rest}\n >\n {children}\n </MagneticEnabledInner>\n </MagneticLazyMotion>\n );\n}\n\nMagnetic.displayName = \"Magnetic\";\n"],"mappings":"wPAuBA,SAAS,EAAsB,EAA4D,CACzF,MAAO,CAAC,CAAC,GAAO,OAAO,GAAQ,UAAY,YAAa,EAG1D,SAAS,EAAmB,EAAyB,EAA4B,CAC/E,GAAI,OAAO,GAAQ,WACjB,OAAQ,EAA8B,EAAK,CAGzC,EAAmB,EAAI,GACzB,EAAI,QAAU,GAIlB,SAAS,EAAqB,EAA4C,CAQxE,MAAO,GAPS,GAAS,SAAW,EAAgB,QAOlC,GANE,GAAS,aAAe,EAAgB,YAM3B,GALf,GAAS,WAAa,EAAgB,UAKV,GAJ9B,GAAS,SAAW,EAAgB,QAIK,GAHzC,GAAS,SAAW,EAAgB,QAGgB,GAFpD,GAAS,SAAW,EAAgB,UAkBtD,SAAS,EAAqB,CAC5B,UACA,QACA,WACA,eACA,GAAG,GACyB,CAC5B,IAAM,EAAW,EAA4B,EAAQ,CAE/C,EAAoB,EAA8B,KAAK,CACzD,EAAkB,UAAY,KAChC,EAAkB,QAAU,CAC1B,YAAa,EACb,YAAa,EAAS,IACvB,EAED,EAAkB,QAAQ,YAAc,EACxC,EAAkB,QAAQ,YAAc,EAAS,KAGnD,IAAM,EAAe,EAAkD,KAAK,CAExE,EAAa,UAAY,OAC3B,EAAa,QAAW,GAAS,CAC/B,IAAM,EAAQ,EAAkB,QAC1B,EAAkB,EAAgB,EAAM,YAAa,EAAK,CAC1D,EAAkB,EAAM,YAAY,EAAK,CAE/C,UAAa,CACP,OAAO,GAAoB,YAAY,GAAiB,CACxD,OAAO,GAAoB,YAAY,GAAiB,IAKlE,IAAM,EAAY,EAAa,QAE/B,OACE,EAAC,EAAE,IAAH,CAAO,GAAI,EAAM,IAAK,EAAW,MAAO,CAAE,GAAG,EAAO,GAAG,EAAS,MAAO,CACpE,WACK,CAAA,CAcZ,SAAS,EAAmB,CAAE,YAAqC,CACjE,OACE,EAAC,EAAD,CAAY,SAAU,EAAc,OAAA,GACjC,WACU,CAAA,CAajB,SAAgB,EAAS,CACvB,UACA,cACA,QACA,WACA,IAAK,EACL,GAAG,GACa,CAChB,IAAM,EAAgB,GAAkB,CAGxC,GAAI,GAFe,GAAS,SAAW,EAAgB,UAAY,CAAC,GAGlE,OACE,EAAC,EAAD,CAAA,SACE,EAAC,EAAE,IAAH,CAAO,GAAI,EAAM,IAAK,EAAqB,QACxC,WACK,CAAA,CACW,CAAA,CAIzB,IAAM,EAAsB,GAAe,EAAqB,EAAQ,CAExE,OACE,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAEW,UACF,QACO,eACd,GAAI,EAEH,WACoB,CAPhB,EAOgB,CACJ,CAAA,CAIzB,EAAS,YAAc"}
|
package/dist/types.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.cjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["import type { SpringOptions } from \"motion/react\";\n\n/**\n * Configuration options for the Magnetic component.\n *\n * Structural options define the identity of a magnetic instance.\n * Changing them requires a remount.\n *\n * Visual options only affect how the instance feels.\n * They can update live without remounting.\n */\nexport interface MagnetOptions {\n /**\n * **Structural Option**\n *\n * Turns the magnetic effect on or off.\n * Changing this triggers a remount to ensure a clean state.\n *\n * @default true\n */\n enabled?: boolean;\n\n /**\n * **Structural Option**\n *\n * Maximum distance (radius) from center where pull begins.\n * Changing this triggers a remount.\n *\n * @default 320\n */\n maxDistance?: number;\n\n /**\n * **Structural Option**\n *\n * Maximum translation toward the pointer.\n * Changing this triggers a remount.\n *\n * @default 64\n */\n maxOffset?: number;\n\n /**\n * **Structural Option**\n *\n * Horizontal anchor for the magnetic origin inside the element bounds (`0` = left edge, `1` = right).\n * Changing this triggers a remount.\n *\n * @default 0.5\n */\n originX?: number;\n\n /**\n * **Structural Option**\n *\n * Vertical anchor for the magnetic origin (`0` = top, `1` = bottom). Values above `0.5` bias the\n * pull point downward (useful for tall controls where the “mass” should feel lower).\n * Changing this triggers a remount.\n *\n * @default 0.5\n */\n originY?: number;\n\n /**\n * **Structural Option**\n *\n * Whether pull translates using an elastic curve mapping.\n * Changing this triggers a remount.\n *\n * @default true\n */\n elastic?: boolean;\n\n /**\n * **Visual Option**\n *\n * Selects the hover preset.\n * - `true`: uses `SMOOTH`\n * - `false`: uses `TACTILE`\n *\n * Can update live without remounting.\n *\n * @default true\n */\n smooth?: boolean;\n\n /**\n * **Visual Option**\n *\n * Controls return behavior.\n * - `true`: use snap-back physics (`BOUNCY_SNAP`)\n * - `false`: use linear reset (`LINEAR_RESET`)\n *\n * Can update live without remounting.\n *\n * @default true\n */\n snap?: boolean;\n\n /**\n * **Visual Option**\n *\n * Overrides the hover spring.\n */\n smoothSpring?: SpringOptions;\n\n /**\n * **Visual Option**\n *\n * Overrides the return spring.\n * Only used when `snap !== false`.\n */\n snapSpring?: SpringOptions;\n\n /**\n * **Structural Option**\n *\n * How the magnetic effect is triggered.\n * - `\"distance\"`: activates when pointer is within `maxDistance` (default, shared orchestrator)\n * - `\"hover\"`: activates only when pointer is directly over the element\n * - `\"click\"`: click to lock and follow cursor, click again to release\n *\n * Changing this triggers a remount.\n *\n * @default \"distance\"\n */\n trigger?: \"distance\" | \"hover\" | \"click\";\n}\n\nexport const TACTILE = {\n stiffness: 400,\n damping: 30,\n mass: 0.5,\n} satisfies SpringOptions;\n\nexport const SMOOTH = {\n stiffness: 150,\n damping: 20,\n mass: 1.2,\n} satisfies SpringOptions;\n\nexport const BOUNCY_SNAP = {\n stiffness: 400,\n damping: 20,\n mass: 0.5,\n restDelta: 0.001,\n} satisfies SpringOptions;\n\nexport const LINEAR_RESET = {\n stiffness: 200,\n damping: 50,\n mass: 1,\n} satisfies SpringOptions;\n\nexport const MAGNET_DEFAULTS = {\n enabled: true,\n maxDistance: 320,\n maxOffset: 64,\n originX: 0.5,\n originY: 0.5,\n elastic: true,\n smooth: true,\n snap: true,\n smoothSpring: SMOOTH,\n snapSpring: BOUNCY_SNAP,\n trigger: \"distance\",\n} satisfies Required<MagnetOptions>;\n"],"mappings":"mEAiIA,MAAa,EAAU,CACrB,UAAW,IACX,QAAS,GACT,KAAM,GACP,CAEY,EAAS,CACpB,UAAW,IACX,QAAS,GACT,KAAM,IACP,CAEY,EAAc,CACzB,UAAW,IACX,QAAS,GACT,KAAM,GACN,UAAW,KACZ,CAEY,EAAe,CAC1B,UAAW,IACX,QAAS,GACT,KAAM,EACP,CAEY,EAAkB,CAC7B,QAAS,GACT,YAAa,IACb,UAAW,GACX,QAAS,GACT,QAAS,GACT,QAAS,GACT,OAAQ,GACR,KAAM,GACN,aAAc,EACd,WAAY,EACZ,QAAS,WACV"}
|
package/dist/types.d.cts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.cts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;AAWA;;;;;;;UAAiB,aAAA;EAkDf;;;;;;;;EAzCA,OAAA;EA0GO;;AAGT;;;;;;EAnGE,WAAA;;;AAyGF;;;;;;EA/FE,SAAA;;;AAqGF;;;;;;EA3FE,OAAA;;;;AAkGF;;;;;;EAvFE,OAAA;;;AA6FF;;;;;;EAnFE,OAAA;;;;;;;;;;;;EAaA,MAAA;;;;;;;;;;;;EAaA,IAAA;;;;;;EAOA,YAAA,GAAe,aAAA;;;;;;;EAQf,UAAA,GAAa,aAAA;;;;;;;;;;;;;EAcb,OAAA;AAAA;AAAA,cAGW,OAAA;;;;;cAMA,MAAA;;;;;cAMA,WAAA;;;;;;cAOA,YAAA;;;;;cAMA,eAAA"}
|
package/dist/types.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.mts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;AAWA;;;;;;;UAAiB,aAAA;EAkDf;;;;;;;;EAzCA,OAAA;EA0GO;;AAGT;;;;;;EAnGE,WAAA;;;AAyGF;;;;;;EA/FE,SAAA;;;AAqGF;;;;;;EA3FE,OAAA;;;;AAkGF;;;;;;EAvFE,OAAA;;;AA6FF;;;;;;EAnFE,OAAA;;;;;;;;;;;;EAaA,MAAA;;;;;;;;;;;;EAaA,IAAA;;;;;;EAOA,YAAA,GAAe,aAAA;;;;;;;EAQf,UAAA,GAAa,aAAA;;;;;;;;;;;;;EAcb,OAAA;AAAA;AAAA,cAGW,OAAA;;;;;cAMA,MAAA;;;;;cAMA,WAAA;;;;;;cAOA,YAAA;;;;;cAMA,eAAA"}
|
package/dist/types.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.mjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["import type { SpringOptions } from \"motion/react\";\n\n/**\n * Configuration options for the Magnetic component.\n *\n * Structural options define the identity of a magnetic instance.\n * Changing them requires a remount.\n *\n * Visual options only affect how the instance feels.\n * They can update live without remounting.\n */\nexport interface MagnetOptions {\n /**\n * **Structural Option**\n *\n * Turns the magnetic effect on or off.\n * Changing this triggers a remount to ensure a clean state.\n *\n * @default true\n */\n enabled?: boolean;\n\n /**\n * **Structural Option**\n *\n * Maximum distance (radius) from center where pull begins.\n * Changing this triggers a remount.\n *\n * @default 320\n */\n maxDistance?: number;\n\n /**\n * **Structural Option**\n *\n * Maximum translation toward the pointer.\n * Changing this triggers a remount.\n *\n * @default 64\n */\n maxOffset?: number;\n\n /**\n * **Structural Option**\n *\n * Horizontal anchor for the magnetic origin inside the element bounds (`0` = left edge, `1` = right).\n * Changing this triggers a remount.\n *\n * @default 0.5\n */\n originX?: number;\n\n /**\n * **Structural Option**\n *\n * Vertical anchor for the magnetic origin (`0` = top, `1` = bottom). Values above `0.5` bias the\n * pull point downward (useful for tall controls where the “mass” should feel lower).\n * Changing this triggers a remount.\n *\n * @default 0.5\n */\n originY?: number;\n\n /**\n * **Structural Option**\n *\n * Whether pull translates using an elastic curve mapping.\n * Changing this triggers a remount.\n *\n * @default true\n */\n elastic?: boolean;\n\n /**\n * **Visual Option**\n *\n * Selects the hover preset.\n * - `true`: uses `SMOOTH`\n * - `false`: uses `TACTILE`\n *\n * Can update live without remounting.\n *\n * @default true\n */\n smooth?: boolean;\n\n /**\n * **Visual Option**\n *\n * Controls return behavior.\n * - `true`: use snap-back physics (`BOUNCY_SNAP`)\n * - `false`: use linear reset (`LINEAR_RESET`)\n *\n * Can update live without remounting.\n *\n * @default true\n */\n snap?: boolean;\n\n /**\n * **Visual Option**\n *\n * Overrides the hover spring.\n */\n smoothSpring?: SpringOptions;\n\n /**\n * **Visual Option**\n *\n * Overrides the return spring.\n * Only used when `snap !== false`.\n */\n snapSpring?: SpringOptions;\n\n /**\n * **Structural Option**\n *\n * How the magnetic effect is triggered.\n * - `\"distance\"`: activates when pointer is within `maxDistance` (default, shared orchestrator)\n * - `\"hover\"`: activates only when pointer is directly over the element\n * - `\"click\"`: click to lock and follow cursor, click again to release\n *\n * Changing this triggers a remount.\n *\n * @default \"distance\"\n */\n trigger?: \"distance\" | \"hover\" | \"click\";\n}\n\nexport const TACTILE = {\n stiffness: 400,\n damping: 30,\n mass: 0.5,\n} satisfies SpringOptions;\n\nexport const SMOOTH = {\n stiffness: 150,\n damping: 20,\n mass: 1.2,\n} satisfies SpringOptions;\n\nexport const BOUNCY_SNAP = {\n stiffness: 400,\n damping: 20,\n mass: 0.5,\n restDelta: 0.001,\n} satisfies SpringOptions;\n\nexport const LINEAR_RESET = {\n stiffness: 200,\n damping: 50,\n mass: 1,\n} satisfies SpringOptions;\n\nexport const MAGNET_DEFAULTS = {\n enabled: true,\n maxDistance: 320,\n maxOffset: 64,\n originX: 0.5,\n originY: 0.5,\n elastic: true,\n smooth: true,\n snap: true,\n smoothSpring: SMOOTH,\n snapSpring: BOUNCY_SNAP,\n trigger: \"distance\",\n} satisfies Required<MagnetOptions>;\n"],"mappings":"AAiIA,MAAa,EAAU,CACrB,UAAW,IACX,QAAS,GACT,KAAM,GACP,CAEY,EAAS,CACpB,UAAW,IACX,QAAS,GACT,KAAM,IACP,CAEY,EAAc,CACzB,UAAW,IACX,QAAS,GACT,KAAM,GACN,UAAW,KACZ,CAEY,EAAe,CAC1B,UAAW,IACX,QAAS,GACT,KAAM,EACP,CAEY,EAAkB,CAC7B,QAAS,GACT,YAAa,IACb,UAAW,GACX,QAAS,GACT,QAAS,GACT,QAAS,GACT,OAAQ,GACR,KAAM,GACN,aAAc,EACd,WAAY,EACZ,QAAS,WACV"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useMagnetic-Cih9JSy3.mjs","names":[],"sources":["../src/orchestrator.ts","../src/useMagnetic.ts"],"sourcesContent":["import type { MotionValue } from \"motion/react\";\nimport { MAGNET_DEFAULTS, type MagnetOptions } from \"./types\";\n\ninterface MagnetMetadata {\n x: MotionValue<number>;\n y: MotionValue<number>;\n options: Required<MagnetOptions>;\n rect: DOMRect | null;\n isIntersecting: boolean;\n isActive: boolean;\n onActiveChange?: (isActive: boolean) => void;\n cleanup?: () => void;\n}\n\nclass MagnetOrchestrator {\n private elements = new Map<HTMLElement, MagnetMetadata>();\n private activeElements = new Set<HTMLElement>();\n private intersectionObserver: IntersectionObserver | null = null;\n private resizeObserver: ResizeObserver | null = null;\n private trackedCount = 0;\n private distanceCount = 0;\n private listenersAttached = false;\n private rafId: number | null = null;\n private framePending = false;\n private needsInvalidate = false;\n private hasPointer = false;\n private pointerX = 0;\n private pointerY = 0;\n\n constructor() {\n if (typeof window === \"undefined\") return;\n\n if (typeof IntersectionObserver !== \"undefined\") {\n this.intersectionObserver = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n const el = entry.target as HTMLElement;\n const meta = this.elements.get(el);\n if (!meta) continue;\n\n meta.isIntersecting = entry.isIntersecting;\n\n if (entry.isIntersecting) {\n if (meta.options.trigger === \"distance\") {\n this.activeElements.add(el);\n }\n meta.rect = null;\n this.requestFrame();\n continue;\n }\n\n this.activeElements.delete(el);\n this.setActive(meta, false);\n this.reset(meta);\n }\n },\n { root: null, rootMargin: \"80px\", threshold: 0 },\n );\n }\n\n if (typeof ResizeObserver !== \"undefined\") {\n this.resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const meta = this.elements.get(entry.target as HTMLElement);\n if (!meta) continue;\n meta.rect = null;\n this.requestFrame();\n }\n });\n }\n\n this.handlePointerMove = this.handlePointerMove.bind(this);\n this.handleInvalidate = this.handleInvalidate.bind(this);\n this.handleWindowBlur = this.handleWindowBlur.bind(this);\n this.handleVisibilityChange = this.handleVisibilityChange.bind(this);\n this.tick = this.tick.bind(this);\n }\n\n public register(\n el: HTMLElement,\n x: MotionValue<number>,\n y: MotionValue<number>,\n options: MagnetOptions = {},\n onActiveChange?: (isActive: boolean) => void,\n ) {\n if (this.elements.has(el)) this.unregister(el);\n\n const resolved = { ...MAGNET_DEFAULTS, ...options };\n const meta: MagnetMetadata = {\n x,\n y,\n options: resolved,\n rect: null,\n isIntersecting: !this.intersectionObserver,\n isActive: false,\n onActiveChange,\n };\n\n this.elements.set(el, meta);\n this.trackedCount += 1;\n\n if (resolved.trigger === \"distance\") {\n this.distanceCount += 1;\n if (meta.isIntersecting) {\n this.activeElements.add(el);\n }\n } else if (resolved.trigger === \"hover\") {\n this.setupHoverMode(el, meta);\n } else if (resolved.trigger === \"click\") {\n this.setupClickMode(el, meta);\n }\n\n this.intersectionObserver?.observe(el);\n this.resizeObserver?.observe(el);\n\n if (this.trackedCount === 1) this.start();\n }\n\n public unregister(el: HTMLElement) {\n const meta = this.elements.get(el);\n if (!meta) return;\n\n this.intersectionObserver?.unobserve(el);\n this.resizeObserver?.unobserve(el);\n this.activeElements.delete(el);\n\n if (meta.options.trigger === \"distance\") {\n this.distanceCount = Math.max(0, this.distanceCount - 1);\n }\n\n meta.cleanup?.();\n\n this.setActive(meta, false);\n this.reset(meta);\n\n this.elements.delete(el);\n this.trackedCount = Math.max(0, this.trackedCount - 1);\n\n if (this.trackedCount === 0) this.stop();\n }\n\n private setupHoverMode(el: HTMLElement, meta: MagnetMetadata) {\n const handleMove = (e: PointerEvent) => {\n const rect = el.getBoundingClientRect();\n const inside =\n e.clientX >= rect.left &&\n e.clientX <= rect.right &&\n e.clientY >= rect.top &&\n e.clientY <= rect.bottom;\n\n if (inside && !meta.isActive) {\n meta.rect = rect;\n this.setActive(meta, true);\n } else if (!inside && meta.isActive) {\n this.setActive(meta, false);\n this.reset(meta);\n meta.rect = null;\n }\n\n if (meta.isActive) {\n this.updateMagnetic(el, meta, e.clientX, e.clientY);\n }\n };\n\n const handleLeave = () => {\n if (meta.isActive) {\n this.setActive(meta, false);\n this.reset(meta);\n meta.rect = null;\n }\n };\n\n window.addEventListener(\"pointermove\", handleMove);\n el.addEventListener(\"pointerleave\", handleLeave);\n\n meta.cleanup = () => {\n window.removeEventListener(\"pointermove\", handleMove);\n el.removeEventListener(\"pointerleave\", handleLeave);\n };\n }\n\n private setupClickMode(el: HTMLElement, meta: MagnetMetadata) {\n let locked = false;\n let grabOffsetX = 0;\n let grabOffsetY = 0;\n let naturalCenterX = 0;\n let naturalCenterY = 0;\n\n const handlePointerDown = (e: PointerEvent) => {\n if (!el.contains(e.target as Node)) return;\n if (locked) {\n locked = false;\n el.style.cursor = \"grab\";\n this.setActive(meta, false);\n this.reset(meta);\n meta.rect = null;\n return;\n }\n meta.rect = el.getBoundingClientRect();\n naturalCenterX = meta.rect.left + meta.rect.width / 2;\n naturalCenterY = meta.rect.top + meta.rect.height / 2;\n grabOffsetX = e.clientX - naturalCenterX;\n grabOffsetY = e.clientY - naturalCenterY;\n locked = true;\n el.style.cursor = \"grabbing\";\n this.setActive(meta, true);\n };\n\n const handlePointerMove = (e: PointerEvent) => {\n if (!locked) return;\n const targetX = e.clientX - grabOffsetX - naturalCenterX;\n const targetY = e.clientY - grabOffsetY - naturalCenterY;\n this.setTarget(meta, targetX, targetY);\n };\n\n const handleGlobalUp = () => {\n if (locked) {\n locked = false;\n el.style.cursor = \"grab\";\n this.setActive(meta, false);\n this.reset(meta);\n meta.rect = null;\n }\n };\n\n el.style.cursor = \"grab\";\n window.addEventListener(\"pointerdown\", handlePointerDown);\n window.addEventListener(\"pointermove\", handlePointerMove);\n window.addEventListener(\"pointerup\", handleGlobalUp);\n\n meta.cleanup = () => {\n el.style.cursor = \"\";\n window.removeEventListener(\"pointerdown\", handlePointerDown);\n window.removeEventListener(\"pointermove\", handlePointerMove);\n window.removeEventListener(\"pointerup\", handleGlobalUp);\n };\n }\n\n private updateMagnetic(el: HTMLElement, meta: MagnetMetadata, px: number, py: number) {\n if (!meta.rect) meta.rect = el.getBoundingClientRect();\n\n const r = meta.rect;\n const { maxDistance, maxOffset, elastic, originX, originY } = meta.options;\n\n const cx = r.left + r.width * originX;\n const cy = r.top + r.height * originY;\n const dx = px - cx;\n const dy = py - cy;\n const dSq = dx * dx + dy * dy;\n\n if (dSq >= maxDistance * maxDistance) {\n this.setActive(meta, false);\n this.reset(meta);\n return;\n }\n\n this.setActive(meta, true);\n\n const dist = Math.sqrt(dSq);\n const progress = Math.min(1, dist / maxDistance);\n\n let targetX = 0;\n let targetY = 0;\n\n if (elastic) {\n const strength = Math.sin(progress * (Math.PI / 2)) * maxOffset;\n const dirX = dx / (dist || 1);\n const dirY = dy / (dist || 1);\n targetX = dirX * strength;\n targetY = dirY * strength;\n } else {\n targetX = (dx / maxDistance) * maxOffset;\n targetY = (dy / maxDistance) * maxOffset;\n }\n\n this.setTarget(meta, targetX, targetY);\n }\n\n private start() {\n if (this.listenersAttached) return;\n this.listenersAttached = true;\n\n window.addEventListener(\"pointermove\", this.handlePointerMove, { passive: true });\n window.addEventListener(\"scroll\", this.handleInvalidate, { passive: true, capture: true });\n window.addEventListener(\"resize\", this.handleInvalidate, { passive: true });\n window.addEventListener(\"blur\", this.handleWindowBlur);\n document.addEventListener(\"visibilitychange\", this.handleVisibilityChange);\n }\n\n private stop() {\n if (!this.listenersAttached) return;\n this.listenersAttached = false;\n\n window.removeEventListener(\"pointermove\", this.handlePointerMove);\n window.removeEventListener(\"scroll\", this.handleInvalidate, { capture: true });\n window.removeEventListener(\"resize\", this.handleInvalidate);\n window.removeEventListener(\"blur\", this.handleWindowBlur);\n document.removeEventListener(\"visibilitychange\", this.handleVisibilityChange);\n\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n this.framePending = false;\n this.needsInvalidate = false;\n this.hasPointer = false;\n }\n\n private handlePointerMove(e: PointerEvent) {\n this.pointerX = e.clientX;\n this.pointerY = e.clientY;\n this.hasPointer = true;\n this.requestFrame();\n }\n\n private handleInvalidate() {\n this.needsInvalidate = true;\n this.requestFrame();\n }\n\n private handleWindowBlur() {\n this.hasPointer = false;\n this.resetAllActive();\n }\n\n private handleVisibilityChange() {\n if (document.hidden) {\n this.hasPointer = false;\n this.resetAllActive();\n }\n }\n\n private requestFrame() {\n if (!this.listenersAttached || this.framePending) return;\n this.framePending = true;\n this.rafId = requestAnimationFrame(this.tick);\n }\n\n private tick() {\n this.framePending = false;\n this.rafId = null;\n\n if (!this.listenersAttached) return;\n\n if (this.needsInvalidate) {\n this.invalidateVisibleRects();\n }\n\n if (!this.hasPointer || this.distanceCount === 0) return;\n\n for (const el of this.activeElements) {\n const meta = this.elements.get(el);\n if (!meta || meta.options.trigger !== \"distance\" || !meta.isIntersecting) continue;\n\n if (!meta.rect) meta.rect = el.getBoundingClientRect();\n\n const r = meta.rect;\n const { maxDistance, maxOffset, elastic, originX, originY } = meta.options;\n\n const cx = r.left + r.width * originX;\n const cy = r.top + r.height * originY;\n const dx = this.pointerX - cx;\n const dy = this.pointerY - cy;\n const dSq = dx * dx + dy * dy;\n\n if (dSq >= maxDistance * maxDistance) {\n this.setActive(meta, false);\n this.reset(meta);\n continue;\n }\n\n this.setActive(meta, true);\n\n const dist = Math.sqrt(dSq);\n const progress = Math.min(1, dist / maxDistance);\n\n let targetX = 0;\n let targetY = 0;\n\n if (elastic) {\n const strength = Math.sin(progress * (Math.PI / 2)) * maxOffset;\n const dirX = dx / (dist || 1);\n const dirY = dy / (dist || 1);\n targetX = dirX * strength;\n targetY = dirY * strength;\n } else {\n targetX = (dx / maxDistance) * maxOffset;\n targetY = (dy / maxDistance) * maxOffset;\n }\n\n this.setTarget(meta, targetX, targetY);\n }\n }\n\n private setActive(meta: MagnetMetadata, next: boolean) {\n if (meta.isActive === next) return;\n meta.isActive = next;\n meta.onActiveChange?.(next);\n }\n\n private setTarget(meta: MagnetMetadata, x: number, y: number) {\n meta.x.set(x);\n meta.y.set(y);\n }\n\n private reset(meta: MagnetMetadata) {\n this.setTarget(meta, 0, 0);\n }\n\n private invalidateVisibleRects() {\n this.needsInvalidate = false;\n for (const el of this.activeElements) {\n const meta = this.elements.get(el);\n if (meta) meta.rect = null;\n }\n }\n\n private resetAllActive() {\n for (const el of this.activeElements) {\n const meta = this.elements.get(el);\n if (!meta) continue;\n this.setActive(meta, false);\n this.reset(meta);\n meta.rect = null;\n }\n }\n}\n\nlet _instance: MagnetOrchestrator | null = null;\n\nfunction get(): MagnetOrchestrator {\n if (_instance === null) {\n _instance = new MagnetOrchestrator();\n }\n return _instance;\n}\n\ninterface MagnetOrchestratorFacade {\n register: MagnetOrchestrator[\"register\"];\n unregister: MagnetOrchestrator[\"unregister\"];\n}\n\nexport const magnetOrchestrator: MagnetOrchestratorFacade = {\n register(el, x, y, options, onActiveChange) {\n get().register(el, x, y, options, onActiveChange);\n },\n unregister(el) {\n get().unregister(el);\n },\n};\n","import {\n type MotionValue,\n type SpringOptions,\n useMotionValue,\n useReducedMotion,\n useSpring,\n} from \"motion/react\";\nimport { useLayoutEffect, useRef, useState } from \"react\";\nimport { magnetOrchestrator } from \"./orchestrator\";\nimport {\n BOUNCY_SNAP,\n LINEAR_RESET,\n MAGNET_DEFAULTS,\n SMOOTH,\n TACTILE,\n type MagnetOptions,\n} from \"./types\";\n\ntype MagneticRefCleanup = void | (() => void);\ntype MagneticRefCallback<T extends HTMLElement> = (node: T | null) => MagneticRefCleanup;\n\nexport interface UseMagneticResult<T extends HTMLElement = HTMLElement> {\n ref: MagneticRefCallback<T>;\n x: MotionValue<number>;\n y: MotionValue<number>;\n style: {\n x: MotionValue<number>;\n y: MotionValue<number>;\n };\n enabled: boolean;\n isComposing: boolean;\n reset: () => void;\n}\n\ninterface VisualOptions {\n hoverSpring: SpringOptions;\n returnSpring: SpringOptions;\n}\n\ninterface StructuralOptions {\n enabled: boolean;\n maxDistance: number;\n maxOffset: number;\n elastic: boolean;\n originX: number;\n originY: number;\n trigger: \"distance\" | \"hover\" | \"click\";\n}\n\ninterface RefState<T extends HTMLElement> {\n enabled: boolean;\n structural: StructuralOptions;\n rawX: MotionValue<number>;\n rawY: MotionValue<number>;\n reset: () => void;\n setIsComposing: (value: boolean) => void;\n registeredNode: T | null;\n}\n\nfunction normalizeStructuralOptions(options: MagnetOptions | undefined): StructuralOptions {\n return {\n enabled: options?.enabled ?? MAGNET_DEFAULTS.enabled,\n maxDistance: options?.maxDistance ?? MAGNET_DEFAULTS.maxDistance,\n maxOffset: options?.maxOffset ?? MAGNET_DEFAULTS.maxOffset,\n elastic: options?.elastic ?? MAGNET_DEFAULTS.elastic,\n originX: options?.originX ?? MAGNET_DEFAULTS.originX,\n originY: options?.originY ?? MAGNET_DEFAULTS.originY,\n trigger: options?.trigger ?? MAGNET_DEFAULTS.trigger,\n };\n}\n\nfunction normalizeVisualOptions(options: MagnetOptions | undefined): VisualOptions {\n const isSmooth = options?.smooth ?? MAGNET_DEFAULTS.smooth;\n const hoverSpring = options?.smoothSpring ?? (isSmooth ? SMOOTH : TACTILE);\n\n const shouldSnap = options?.snap ?? MAGNET_DEFAULTS.snap;\n const returnSpring = shouldSnap ? (options?.snapSpring ?? BOUNCY_SNAP) : LINEAR_RESET;\n\n return { hoverSpring, returnSpring };\n}\n\n/**\n * Expert primitive for headless magnetic interactions.\n *\n * ### The Headless Contract\n * 1. **Structural Options** (`maxDistance`, `maxOffset`, `elastic`, origins) are construction-time\n * while a node is registered. **`enabled` is special**: it may toggle on the same DOM node; the\n * hook syncs orchestrator registration on `enabled` changes via `useLayoutEffect`.\n * 2. **Visual Options** (`smooth`, `snap`, springs) can update live.\n * 3. **Ref Management**: You MUST attach `magnetic.ref` to the element that should track the pointer.\n * 4. **Style Attachment**: You MUST apply `magnetic.style` to a `motion` component.\n *\n * @example\n * ```tsx\n * const magnetic = useMagnetic({ maxOffset: 20 });\n * return <motion.div ref={magnetic.ref} style={magnetic.style} />\n * ```\n */\nexport function useMagnetic<T extends HTMLElement = HTMLElement>(\n options?: MagnetOptions,\n): UseMagneticResult<T> {\n const reducedMotion = useReducedMotion();\n const structural = normalizeStructuralOptions(options);\n const visual = normalizeVisualOptions(options);\n const enabled = structural.enabled && !reducedMotion;\n\n const [isComposing, setIsComposing] = useState(false);\n\n const rawX = useMotionValue(0);\n const rawY = useMotionValue(0);\n\n const x = useSpring(rawX, isComposing ? visual.hoverSpring : visual.returnSpring);\n const y = useSpring(rawY, isComposing ? visual.hoverSpring : visual.returnSpring);\n\n const mountedStructuralRef = useRef<StructuralOptions | null>(null);\n const cleanupRef = useRef<(() => void) | null>(null);\n const domNodeRef = useRef<T | null>(null);\n const layoutSyncPrevEnabledRef = useRef<boolean | null>(null);\n\n const rawXRef = useRef(rawX);\n const rawYRef = useRef(rawY);\n const setIsComposingRef = useRef(setIsComposing);\n rawXRef.current = rawX;\n rawYRef.current = rawY;\n setIsComposingRef.current = setIsComposing;\n\n const reset = useRef(() => {\n rawXRef.current.set(0);\n rawYRef.current.set(0);\n setIsComposingRef.current(false);\n }).current;\n\n const refStateRef = useRef<RefState<T> | null>(null);\n if (refStateRef.current === null) {\n refStateRef.current = {\n enabled,\n structural,\n rawX,\n rawY,\n reset,\n setIsComposing,\n registeredNode: null,\n };\n } else {\n refStateRef.current.enabled = enabled;\n refStateRef.current.rawX = rawX;\n refStateRef.current.rawY = rawY;\n refStateRef.current.reset = reset;\n refStateRef.current.setIsComposing = setIsComposing;\n\n if (refStateRef.current.registeredNode === null) {\n refStateRef.current.structural = structural;\n }\n }\n\n const refRef = useRef<MagneticRefCallback<T> | null>(null);\n\n if (refRef.current === null) {\n refRef.current = (node) => {\n domNodeRef.current = node;\n\n const state = refStateRef.current!;\n const currentCleanup = cleanupRef.current;\n const currentNode = state.registeredNode;\n\n if (node === currentNode) {\n return currentCleanup ?? undefined;\n }\n\n if (node === null) {\n currentCleanup?.();\n cleanupRef.current = null;\n state.registeredNode = null;\n mountedStructuralRef.current = null;\n state.reset();\n return;\n }\n\n currentCleanup?.();\n cleanupRef.current = null;\n state.registeredNode = null;\n\n if (!state.enabled) {\n mountedStructuralRef.current = null;\n state.reset();\n return;\n }\n\n const structuralAtMount = mountedStructuralRef.current ?? state.structural;\n mountedStructuralRef.current = structuralAtMount;\n state.registeredNode = node;\n\n magnetOrchestrator.register(\n node,\n state.rawX,\n state.rawY,\n structuralAtMount,\n state.setIsComposing,\n );\n\n const cleanup = () => {\n magnetOrchestrator.unregister(node);\n cleanupRef.current = null;\n if (state.registeredNode === node) {\n state.registeredNode = null;\n }\n mountedStructuralRef.current = null;\n state.reset();\n };\n\n cleanupRef.current = cleanup;\n return cleanup;\n };\n }\n\n useLayoutEffect(() => {\n const node = domNodeRef.current;\n const state = refStateRef.current!;\n\n if (layoutSyncPrevEnabledRef.current === null) {\n layoutSyncPrevEnabledRef.current = enabled;\n return;\n }\n\n if (layoutSyncPrevEnabledRef.current === enabled) {\n return;\n }\n\n layoutSyncPrevEnabledRef.current = enabled;\n\n if (!node) {\n return;\n }\n\n cleanupRef.current?.();\n cleanupRef.current = null;\n state.registeredNode = null;\n\n if (!state.enabled) {\n mountedStructuralRef.current = null;\n state.reset();\n return;\n }\n\n const structuralAtMount = mountedStructuralRef.current ?? state.structural;\n mountedStructuralRef.current = structuralAtMount;\n state.registeredNode = node;\n\n magnetOrchestrator.register(\n node,\n state.rawX,\n state.rawY,\n structuralAtMount,\n state.setIsComposing,\n );\n\n const cleanup = () => {\n magnetOrchestrator.unregister(node);\n cleanupRef.current = null;\n if (state.registeredNode === node) {\n state.registeredNode = null;\n }\n mountedStructuralRef.current = null;\n state.reset();\n };\n\n cleanupRef.current = cleanup;\n }, [enabled]);\n\n const ref = refRef.current;\n\n return {\n ref,\n x: enabled ? x : rawX,\n y: enabled ? y : rawY,\n style: enabled ? { x, y } : { x: rawX, y: rawY },\n enabled,\n isComposing: enabled && isComposing,\n reset,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useMagnetic-hzN5_pe4.cjs","names":["MAGNET_DEFAULTS","MAGNET_DEFAULTS","SMOOTH","TACTILE","BOUNCY_SNAP","LINEAR_RESET"],"sources":["../src/orchestrator.ts","../src/useMagnetic.ts"],"sourcesContent":["import type { MotionValue } from \"motion/react\";\nimport { MAGNET_DEFAULTS, type MagnetOptions } from \"./types\";\n\ninterface MagnetMetadata {\n x: MotionValue<number>;\n y: MotionValue<number>;\n options: Required<MagnetOptions>;\n rect: DOMRect | null;\n isIntersecting: boolean;\n isActive: boolean;\n onActiveChange?: (isActive: boolean) => void;\n cleanup?: () => void;\n}\n\nclass MagnetOrchestrator {\n private elements = new Map<HTMLElement, MagnetMetadata>();\n private activeElements = new Set<HTMLElement>();\n private intersectionObserver: IntersectionObserver | null = null;\n private resizeObserver: ResizeObserver | null = null;\n private trackedCount = 0;\n private distanceCount = 0;\n private listenersAttached = false;\n private rafId: number | null = null;\n private framePending = false;\n private needsInvalidate = false;\n private hasPointer = false;\n private pointerX = 0;\n private pointerY = 0;\n\n constructor() {\n if (typeof window === \"undefined\") return;\n\n if (typeof IntersectionObserver !== \"undefined\") {\n this.intersectionObserver = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n const el = entry.target as HTMLElement;\n const meta = this.elements.get(el);\n if (!meta) continue;\n\n meta.isIntersecting = entry.isIntersecting;\n\n if (entry.isIntersecting) {\n if (meta.options.trigger === \"distance\") {\n this.activeElements.add(el);\n }\n meta.rect = null;\n this.requestFrame();\n continue;\n }\n\n this.activeElements.delete(el);\n this.setActive(meta, false);\n this.reset(meta);\n }\n },\n { root: null, rootMargin: \"80px\", threshold: 0 },\n );\n }\n\n if (typeof ResizeObserver !== \"undefined\") {\n this.resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const meta = this.elements.get(entry.target as HTMLElement);\n if (!meta) continue;\n meta.rect = null;\n this.requestFrame();\n }\n });\n }\n\n this.handlePointerMove = this.handlePointerMove.bind(this);\n this.handleInvalidate = this.handleInvalidate.bind(this);\n this.handleWindowBlur = this.handleWindowBlur.bind(this);\n this.handleVisibilityChange = this.handleVisibilityChange.bind(this);\n this.tick = this.tick.bind(this);\n }\n\n public register(\n el: HTMLElement,\n x: MotionValue<number>,\n y: MotionValue<number>,\n options: MagnetOptions = {},\n onActiveChange?: (isActive: boolean) => void,\n ) {\n if (this.elements.has(el)) this.unregister(el);\n\n const resolved = { ...MAGNET_DEFAULTS, ...options };\n const meta: MagnetMetadata = {\n x,\n y,\n options: resolved,\n rect: null,\n isIntersecting: !this.intersectionObserver,\n isActive: false,\n onActiveChange,\n };\n\n this.elements.set(el, meta);\n this.trackedCount += 1;\n\n if (resolved.trigger === \"distance\") {\n this.distanceCount += 1;\n if (meta.isIntersecting) {\n this.activeElements.add(el);\n }\n } else if (resolved.trigger === \"hover\") {\n this.setupHoverMode(el, meta);\n } else if (resolved.trigger === \"click\") {\n this.setupClickMode(el, meta);\n }\n\n this.intersectionObserver?.observe(el);\n this.resizeObserver?.observe(el);\n\n if (this.trackedCount === 1) this.start();\n }\n\n public unregister(el: HTMLElement) {\n const meta = this.elements.get(el);\n if (!meta) return;\n\n this.intersectionObserver?.unobserve(el);\n this.resizeObserver?.unobserve(el);\n this.activeElements.delete(el);\n\n if (meta.options.trigger === \"distance\") {\n this.distanceCount = Math.max(0, this.distanceCount - 1);\n }\n\n meta.cleanup?.();\n\n this.setActive(meta, false);\n this.reset(meta);\n\n this.elements.delete(el);\n this.trackedCount = Math.max(0, this.trackedCount - 1);\n\n if (this.trackedCount === 0) this.stop();\n }\n\n private setupHoverMode(el: HTMLElement, meta: MagnetMetadata) {\n const handleMove = (e: PointerEvent) => {\n const rect = el.getBoundingClientRect();\n const inside =\n e.clientX >= rect.left &&\n e.clientX <= rect.right &&\n e.clientY >= rect.top &&\n e.clientY <= rect.bottom;\n\n if (inside && !meta.isActive) {\n meta.rect = rect;\n this.setActive(meta, true);\n } else if (!inside && meta.isActive) {\n this.setActive(meta, false);\n this.reset(meta);\n meta.rect = null;\n }\n\n if (meta.isActive) {\n this.updateMagnetic(el, meta, e.clientX, e.clientY);\n }\n };\n\n const handleLeave = () => {\n if (meta.isActive) {\n this.setActive(meta, false);\n this.reset(meta);\n meta.rect = null;\n }\n };\n\n window.addEventListener(\"pointermove\", handleMove);\n el.addEventListener(\"pointerleave\", handleLeave);\n\n meta.cleanup = () => {\n window.removeEventListener(\"pointermove\", handleMove);\n el.removeEventListener(\"pointerleave\", handleLeave);\n };\n }\n\n private setupClickMode(el: HTMLElement, meta: MagnetMetadata) {\n let locked = false;\n let grabOffsetX = 0;\n let grabOffsetY = 0;\n let naturalCenterX = 0;\n let naturalCenterY = 0;\n\n const handlePointerDown = (e: PointerEvent) => {\n if (!el.contains(e.target as Node)) return;\n if (locked) {\n locked = false;\n el.style.cursor = \"grab\";\n this.setActive(meta, false);\n this.reset(meta);\n meta.rect = null;\n return;\n }\n meta.rect = el.getBoundingClientRect();\n naturalCenterX = meta.rect.left + meta.rect.width / 2;\n naturalCenterY = meta.rect.top + meta.rect.height / 2;\n grabOffsetX = e.clientX - naturalCenterX;\n grabOffsetY = e.clientY - naturalCenterY;\n locked = true;\n el.style.cursor = \"grabbing\";\n this.setActive(meta, true);\n };\n\n const handlePointerMove = (e: PointerEvent) => {\n if (!locked) return;\n const targetX = e.clientX - grabOffsetX - naturalCenterX;\n const targetY = e.clientY - grabOffsetY - naturalCenterY;\n this.setTarget(meta, targetX, targetY);\n };\n\n const handleGlobalUp = () => {\n if (locked) {\n locked = false;\n el.style.cursor = \"grab\";\n this.setActive(meta, false);\n this.reset(meta);\n meta.rect = null;\n }\n };\n\n el.style.cursor = \"grab\";\n window.addEventListener(\"pointerdown\", handlePointerDown);\n window.addEventListener(\"pointermove\", handlePointerMove);\n window.addEventListener(\"pointerup\", handleGlobalUp);\n\n meta.cleanup = () => {\n el.style.cursor = \"\";\n window.removeEventListener(\"pointerdown\", handlePointerDown);\n window.removeEventListener(\"pointermove\", handlePointerMove);\n window.removeEventListener(\"pointerup\", handleGlobalUp);\n };\n }\n\n private updateMagnetic(el: HTMLElement, meta: MagnetMetadata, px: number, py: number) {\n if (!meta.rect) meta.rect = el.getBoundingClientRect();\n\n const r = meta.rect;\n const { maxDistance, maxOffset, elastic, originX, originY } = meta.options;\n\n const cx = r.left + r.width * originX;\n const cy = r.top + r.height * originY;\n const dx = px - cx;\n const dy = py - cy;\n const dSq = dx * dx + dy * dy;\n\n if (dSq >= maxDistance * maxDistance) {\n this.setActive(meta, false);\n this.reset(meta);\n return;\n }\n\n this.setActive(meta, true);\n\n const dist = Math.sqrt(dSq);\n const progress = Math.min(1, dist / maxDistance);\n\n let targetX = 0;\n let targetY = 0;\n\n if (elastic) {\n const strength = Math.sin(progress * (Math.PI / 2)) * maxOffset;\n const dirX = dx / (dist || 1);\n const dirY = dy / (dist || 1);\n targetX = dirX * strength;\n targetY = dirY * strength;\n } else {\n targetX = (dx / maxDistance) * maxOffset;\n targetY = (dy / maxDistance) * maxOffset;\n }\n\n this.setTarget(meta, targetX, targetY);\n }\n\n private start() {\n if (this.listenersAttached) return;\n this.listenersAttached = true;\n\n window.addEventListener(\"pointermove\", this.handlePointerMove, { passive: true });\n window.addEventListener(\"scroll\", this.handleInvalidate, { passive: true, capture: true });\n window.addEventListener(\"resize\", this.handleInvalidate, { passive: true });\n window.addEventListener(\"blur\", this.handleWindowBlur);\n document.addEventListener(\"visibilitychange\", this.handleVisibilityChange);\n }\n\n private stop() {\n if (!this.listenersAttached) return;\n this.listenersAttached = false;\n\n window.removeEventListener(\"pointermove\", this.handlePointerMove);\n window.removeEventListener(\"scroll\", this.handleInvalidate, { capture: true });\n window.removeEventListener(\"resize\", this.handleInvalidate);\n window.removeEventListener(\"blur\", this.handleWindowBlur);\n document.removeEventListener(\"visibilitychange\", this.handleVisibilityChange);\n\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n this.framePending = false;\n this.needsInvalidate = false;\n this.hasPointer = false;\n }\n\n private handlePointerMove(e: PointerEvent) {\n this.pointerX = e.clientX;\n this.pointerY = e.clientY;\n this.hasPointer = true;\n this.requestFrame();\n }\n\n private handleInvalidate() {\n this.needsInvalidate = true;\n this.requestFrame();\n }\n\n private handleWindowBlur() {\n this.hasPointer = false;\n this.resetAllActive();\n }\n\n private handleVisibilityChange() {\n if (document.hidden) {\n this.hasPointer = false;\n this.resetAllActive();\n }\n }\n\n private requestFrame() {\n if (!this.listenersAttached || this.framePending) return;\n this.framePending = true;\n this.rafId = requestAnimationFrame(this.tick);\n }\n\n private tick() {\n this.framePending = false;\n this.rafId = null;\n\n if (!this.listenersAttached) return;\n\n if (this.needsInvalidate) {\n this.invalidateVisibleRects();\n }\n\n if (!this.hasPointer || this.distanceCount === 0) return;\n\n for (const el of this.activeElements) {\n const meta = this.elements.get(el);\n if (!meta || meta.options.trigger !== \"distance\" || !meta.isIntersecting) continue;\n\n if (!meta.rect) meta.rect = el.getBoundingClientRect();\n\n const r = meta.rect;\n const { maxDistance, maxOffset, elastic, originX, originY } = meta.options;\n\n const cx = r.left + r.width * originX;\n const cy = r.top + r.height * originY;\n const dx = this.pointerX - cx;\n const dy = this.pointerY - cy;\n const dSq = dx * dx + dy * dy;\n\n if (dSq >= maxDistance * maxDistance) {\n this.setActive(meta, false);\n this.reset(meta);\n continue;\n }\n\n this.setActive(meta, true);\n\n const dist = Math.sqrt(dSq);\n const progress = Math.min(1, dist / maxDistance);\n\n let targetX = 0;\n let targetY = 0;\n\n if (elastic) {\n const strength = Math.sin(progress * (Math.PI / 2)) * maxOffset;\n const dirX = dx / (dist || 1);\n const dirY = dy / (dist || 1);\n targetX = dirX * strength;\n targetY = dirY * strength;\n } else {\n targetX = (dx / maxDistance) * maxOffset;\n targetY = (dy / maxDistance) * maxOffset;\n }\n\n this.setTarget(meta, targetX, targetY);\n }\n }\n\n private setActive(meta: MagnetMetadata, next: boolean) {\n if (meta.isActive === next) return;\n meta.isActive = next;\n meta.onActiveChange?.(next);\n }\n\n private setTarget(meta: MagnetMetadata, x: number, y: number) {\n meta.x.set(x);\n meta.y.set(y);\n }\n\n private reset(meta: MagnetMetadata) {\n this.setTarget(meta, 0, 0);\n }\n\n private invalidateVisibleRects() {\n this.needsInvalidate = false;\n for (const el of this.activeElements) {\n const meta = this.elements.get(el);\n if (meta) meta.rect = null;\n }\n }\n\n private resetAllActive() {\n for (const el of this.activeElements) {\n const meta = this.elements.get(el);\n if (!meta) continue;\n this.setActive(meta, false);\n this.reset(meta);\n meta.rect = null;\n }\n }\n}\n\nlet _instance: MagnetOrchestrator | null = null;\n\nfunction get(): MagnetOrchestrator {\n if (_instance === null) {\n _instance = new MagnetOrchestrator();\n }\n return _instance;\n}\n\ninterface MagnetOrchestratorFacade {\n register: MagnetOrchestrator[\"register\"];\n unregister: MagnetOrchestrator[\"unregister\"];\n}\n\nexport const magnetOrchestrator: MagnetOrchestratorFacade = {\n register(el, x, y, options, onActiveChange) {\n get().register(el, x, y, options, onActiveChange);\n },\n unregister(el) {\n get().unregister(el);\n },\n};\n","import {\n type MotionValue,\n type SpringOptions,\n useMotionValue,\n useReducedMotion,\n useSpring,\n} from \"motion/react\";\nimport { useLayoutEffect, useRef, useState } from \"react\";\nimport { magnetOrchestrator } from \"./orchestrator\";\nimport {\n BOUNCY_SNAP,\n LINEAR_RESET,\n MAGNET_DEFAULTS,\n SMOOTH,\n TACTILE,\n type MagnetOptions,\n} from \"./types\";\n\ntype MagneticRefCleanup = void | (() => void);\ntype MagneticRefCallback<T extends HTMLElement> = (node: T | null) => MagneticRefCleanup;\n\nexport interface UseMagneticResult<T extends HTMLElement = HTMLElement> {\n ref: MagneticRefCallback<T>;\n x: MotionValue<number>;\n y: MotionValue<number>;\n style: {\n x: MotionValue<number>;\n y: MotionValue<number>;\n };\n enabled: boolean;\n isComposing: boolean;\n reset: () => void;\n}\n\ninterface VisualOptions {\n hoverSpring: SpringOptions;\n returnSpring: SpringOptions;\n}\n\ninterface StructuralOptions {\n enabled: boolean;\n maxDistance: number;\n maxOffset: number;\n elastic: boolean;\n originX: number;\n originY: number;\n trigger: \"distance\" | \"hover\" | \"click\";\n}\n\ninterface RefState<T extends HTMLElement> {\n enabled: boolean;\n structural: StructuralOptions;\n rawX: MotionValue<number>;\n rawY: MotionValue<number>;\n reset: () => void;\n setIsComposing: (value: boolean) => void;\n registeredNode: T | null;\n}\n\nfunction normalizeStructuralOptions(options: MagnetOptions | undefined): StructuralOptions {\n return {\n enabled: options?.enabled ?? MAGNET_DEFAULTS.enabled,\n maxDistance: options?.maxDistance ?? MAGNET_DEFAULTS.maxDistance,\n maxOffset: options?.maxOffset ?? MAGNET_DEFAULTS.maxOffset,\n elastic: options?.elastic ?? MAGNET_DEFAULTS.elastic,\n originX: options?.originX ?? MAGNET_DEFAULTS.originX,\n originY: options?.originY ?? MAGNET_DEFAULTS.originY,\n trigger: options?.trigger ?? MAGNET_DEFAULTS.trigger,\n };\n}\n\nfunction normalizeVisualOptions(options: MagnetOptions | undefined): VisualOptions {\n const isSmooth = options?.smooth ?? MAGNET_DEFAULTS.smooth;\n const hoverSpring = options?.smoothSpring ?? (isSmooth ? SMOOTH : TACTILE);\n\n const shouldSnap = options?.snap ?? MAGNET_DEFAULTS.snap;\n const returnSpring = shouldSnap ? (options?.snapSpring ?? BOUNCY_SNAP) : LINEAR_RESET;\n\n return { hoverSpring, returnSpring };\n}\n\n/**\n * Expert primitive for headless magnetic interactions.\n *\n * ### The Headless Contract\n * 1. **Structural Options** (`maxDistance`, `maxOffset`, `elastic`, origins) are construction-time\n * while a node is registered. **`enabled` is special**: it may toggle on the same DOM node; the\n * hook syncs orchestrator registration on `enabled` changes via `useLayoutEffect`.\n * 2. **Visual Options** (`smooth`, `snap`, springs) can update live.\n * 3. **Ref Management**: You MUST attach `magnetic.ref` to the element that should track the pointer.\n * 4. **Style Attachment**: You MUST apply `magnetic.style` to a `motion` component.\n *\n * @example\n * ```tsx\n * const magnetic = useMagnetic({ maxOffset: 20 });\n * return <motion.div ref={magnetic.ref} style={magnetic.style} />\n * ```\n */\nexport function useMagnetic<T extends HTMLElement = HTMLElement>(\n options?: MagnetOptions,\n): UseMagneticResult<T> {\n const reducedMotion = useReducedMotion();\n const structural = normalizeStructuralOptions(options);\n const visual = normalizeVisualOptions(options);\n const enabled = structural.enabled && !reducedMotion;\n\n const [isComposing, setIsComposing] = useState(false);\n\n const rawX = useMotionValue(0);\n const rawY = useMotionValue(0);\n\n const x = useSpring(rawX, isComposing ? visual.hoverSpring : visual.returnSpring);\n const y = useSpring(rawY, isComposing ? visual.hoverSpring : visual.returnSpring);\n\n const mountedStructuralRef = useRef<StructuralOptions | null>(null);\n const cleanupRef = useRef<(() => void) | null>(null);\n const domNodeRef = useRef<T | null>(null);\n const layoutSyncPrevEnabledRef = useRef<boolean | null>(null);\n\n const rawXRef = useRef(rawX);\n const rawYRef = useRef(rawY);\n const setIsComposingRef = useRef(setIsComposing);\n rawXRef.current = rawX;\n rawYRef.current = rawY;\n setIsComposingRef.current = setIsComposing;\n\n const reset = useRef(() => {\n rawXRef.current.set(0);\n rawYRef.current.set(0);\n setIsComposingRef.current(false);\n }).current;\n\n const refStateRef = useRef<RefState<T> | null>(null);\n if (refStateRef.current === null) {\n refStateRef.current = {\n enabled,\n structural,\n rawX,\n rawY,\n reset,\n setIsComposing,\n registeredNode: null,\n };\n } else {\n refStateRef.current.enabled = enabled;\n refStateRef.current.rawX = rawX;\n refStateRef.current.rawY = rawY;\n refStateRef.current.reset = reset;\n refStateRef.current.setIsComposing = setIsComposing;\n\n if (refStateRef.current.registeredNode === null) {\n refStateRef.current.structural = structural;\n }\n }\n\n const refRef = useRef<MagneticRefCallback<T> | null>(null);\n\n if (refRef.current === null) {\n refRef.current = (node) => {\n domNodeRef.current = node;\n\n const state = refStateRef.current!;\n const currentCleanup = cleanupRef.current;\n const currentNode = state.registeredNode;\n\n if (node === currentNode) {\n return currentCleanup ?? undefined;\n }\n\n if (node === null) {\n currentCleanup?.();\n cleanupRef.current = null;\n state.registeredNode = null;\n mountedStructuralRef.current = null;\n state.reset();\n return;\n }\n\n currentCleanup?.();\n cleanupRef.current = null;\n state.registeredNode = null;\n\n if (!state.enabled) {\n mountedStructuralRef.current = null;\n state.reset();\n return;\n }\n\n const structuralAtMount = mountedStructuralRef.current ?? state.structural;\n mountedStructuralRef.current = structuralAtMount;\n state.registeredNode = node;\n\n magnetOrchestrator.register(\n node,\n state.rawX,\n state.rawY,\n structuralAtMount,\n state.setIsComposing,\n );\n\n const cleanup = () => {\n magnetOrchestrator.unregister(node);\n cleanupRef.current = null;\n if (state.registeredNode === node) {\n state.registeredNode = null;\n }\n mountedStructuralRef.current = null;\n state.reset();\n };\n\n cleanupRef.current = cleanup;\n return cleanup;\n };\n }\n\n useLayoutEffect(() => {\n const node = domNodeRef.current;\n const state = refStateRef.current!;\n\n if (layoutSyncPrevEnabledRef.current === null) {\n layoutSyncPrevEnabledRef.current = enabled;\n return;\n }\n\n if (layoutSyncPrevEnabledRef.current === enabled) {\n return;\n }\n\n layoutSyncPrevEnabledRef.current = enabled;\n\n if (!node) {\n return;\n }\n\n cleanupRef.current?.();\n cleanupRef.current = null;\n state.registeredNode = null;\n\n if (!state.enabled) {\n mountedStructuralRef.current = null;\n state.reset();\n return;\n }\n\n const structuralAtMount = mountedStructuralRef.current ?? state.structural;\n mountedStructuralRef.current = structuralAtMount;\n state.registeredNode = node;\n\n magnetOrchestrator.register(\n node,\n state.rawX,\n state.rawY,\n structuralAtMount,\n state.setIsComposing,\n );\n\n const cleanup = () => {\n magnetOrchestrator.unregister(node);\n cleanupRef.current = null;\n if (state.registeredNode === node) {\n state.registeredNode = null;\n }\n mountedStructuralRef.current = null;\n state.reset();\n };\n\n cleanupRef.current = cleanup;\n }, [enabled]);\n\n const ref = refRef.current;\n\n return {\n ref,\n x: enabled ? x : rawX,\n y: enabled ? y : rawY,\n style: enabled ? { x, y } : { x: rawX, y: rawY },\n enabled,\n isComposing: enabled && isComposing,\n reset,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useMagnetic.d.cts","names":[],"sources":["../src/useMagnetic.ts"],"mappings":";;;;KAkBK,kBAAA;AAAA,KACA,mBAAA,WAA8B,WAAA,KAAgB,IAAA,EAAM,CAAA,YAAa,kBAAA;AAAA,UAErD,iBAAA,WAA4B,WAAA,GAAc,WAAA;EACzD,GAAA,EAAK,mBAAA,CAAoB,CAAA;EACzB,CAAA,EAAG,WAAA;EACH,CAAA,EAAG,WAAA;EACH,KAAA;IACE,CAAA,EAAG,WAAA;IACH,CAAA,EAAG,WAAA;EAAA;EAEL,OAAA;EACA,WAAA;EACA,KAAA;AAAA;;;;;;;;;AAVF;;;;;;;;;iBA6EgB,WAAA,WAAsB,WAAA,GAAc,WAAA,CAAA,CAClD,OAAA,GAAU,aAAA,GACT,iBAAA,CAAkB,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useMagnetic.d.mts","names":[],"sources":["../src/useMagnetic.ts"],"mappings":";;;;KAkBK,kBAAA;AAAA,KACA,mBAAA,WAA8B,WAAA,KAAgB,IAAA,EAAM,CAAA,YAAa,kBAAA;AAAA,UAErD,iBAAA,WAA4B,WAAA,GAAc,WAAA;EACzD,GAAA,EAAK,mBAAA,CAAoB,CAAA;EACzB,CAAA,EAAG,WAAA;EACH,CAAA,EAAG,WAAA;EACH,KAAA;IACE,CAAA,EAAG,WAAA;IACH,CAAA,EAAG,WAAA;EAAA;EAEL,OAAA;EACA,WAAA;EACA,KAAA;AAAA;;;;;;;;;AAVF;;;;;;;;;iBA6EgB,WAAA,WAAsB,WAAA,GAAc,WAAA,CAAA,CAClD,OAAA,GAAU,aAAA,GACT,iBAAA,CAAkB,CAAA"}
|