@supermousejs/core 2.0.0 → 2.0.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @supermousejs/core
2
2
 
3
+ ## 2.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Add minimal README.md files to packages
8
+
3
9
  ## 2.0.0
4
10
 
5
11
  ### Major Changes
package/README.md ADDED
@@ -0,0 +1,31 @@
1
+
2
+ # @supermousejs/core
3
+
4
+ The high-performance runtime engine for **Supermouse v2**.
5
+
6
+ It separates cursor **intent** (input, physics, logic) from **rendering** (visuals), exposing a deterministic plugin pipeline.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ pnpm add @supermousejs/core
12
+ ```
13
+
14
+ ## Basic Usage
15
+
16
+ ```ts
17
+ import { Supermouse } from '@supermousejs/core';
18
+ // Import visuals separately to keep bundle size low
19
+ import { Dot } from '@supermousejs/dot';
20
+
21
+ const app = new Supermouse({
22
+ smoothness: 0.15, // 0-1 (Physics damping)
23
+ hideCursor: true, // Auto-hide native cursor
24
+ });
25
+
26
+ app.use(Dot({ size: 8, color: '#f59e0b' }));
27
+ ```
28
+
29
+ ## Documentation
30
+
31
+ Full documentation and interactive playground available at [supermouse](https://supermousejs.vercel.app) (or your repo URL).
package/dist/index.mjs CHANGED
@@ -221,8 +221,8 @@ const g = [
221
221
  ];
222
222
  class y {
223
223
  /** The current version of Supermouse.js */
224
- static version = "2.0.0";
225
- version = "2.0.0";
224
+ static version = "2.0.1";
225
+ version = "2.0.1";
226
226
  /**
227
227
  * The Single Source of Truth.
228
228
  *
package/dist/index.umd.js CHANGED
@@ -2,4 +2,4 @@
2
2
  ${e} {
3
3
  cursor: none !important;
4
4
  }
5
- `}destroy(){this.element.remove(),this.styleTag.remove(),this.container.style.cursor="",this.container.classList.remove(this.scopeClass)}}class v{constructor(t,e,s,n){this.state=t,this.options=e,this.getHoverSelector=s,this.onEnableChange=n,this.checkDeviceCapability(),this.checkMotionPreference(),this.bindEvents()}mediaQueryList;mediaQueryHandler;motionQuery;isEnabled=!0;interactionCache=new WeakMap;checkDeviceCapability(){this.options.autoDisableOnMobile&&(this.mediaQueryList=window.matchMedia("(pointer: fine)"),this.updateEnabledState(this.mediaQueryList.matches),this.mediaQueryHandler=t=>{this.updateEnabledState(t.matches)},this.mediaQueryList.addEventListener("change",this.mediaQueryHandler))}checkMotionPreference(){this.motionQuery=window.matchMedia("(prefer-reduced-motion: reduce)"),this.state.reducedMotion=this.motionQuery.matches,this.motionQuery.addEventListener("change",t=>{this.state.reducedMotion=t.matches})}updateEnabledState(t){this.isEnabled=t,this.onEnableChange(t)}parseDOMInteraction(t){if(this.options.resolveInteraction){this.state.interaction=this.options.resolveInteraction(t);return}if(this.interactionCache.has(t)){this.state.interaction=this.interactionCache.get(t);return}const e={};if(this.options.rules)for(const[n,i]of Object.entries(this.options.rules))t.matches(n)&&Object.assign(e,i);const s=t.dataset;for(const n in s)if(n.startsWith("supermouse")){const i=n.slice(10);if(i){const l=i.charAt(0).toLowerCase()+i.slice(1),r=s[n];e[l]=r===""?!0:r}}this.interactionCache.set(t,e),this.state.interaction=e}handleMove=t=>{if(!this.isEnabled||this.options.autoDisableOnMobile&&t.pointerType==="touch")return;let e=t.clientX,s=t.clientY;if(this.options.container&&this.options.container!==document.body){const n=this.options.container.getBoundingClientRect();e-=n.left,s-=n.top}this.state.pointer.x=e,this.state.pointer.y=s,this.state.hasReceivedInput||(this.state.hasReceivedInput=!0,this.state.target.x=this.state.smooth.x=e,this.state.target.y=this.state.smooth.y=s)};handleDown=()=>{this.isEnabled&&(this.state.isDown=!0)};handleUp=()=>{this.isEnabled&&(this.state.isDown=!1)};handleMouseOver=t=>{if(!this.isEnabled)return;const e=t.target;if(e.closest("[data-supermouse-ignore]")){this.state.isNative=!0;return}const s=this.getHoverSelector(),n=e.closest(s);n&&(this.state.isHover=!0,this.state.hoverTarget=n,this.parseDOMInteraction(this.state.hoverTarget));const i=this.options.ignoreOnNative;if(i){const l=i===!0||i==="auto"||i==="tag",r=i===!0||i==="auto"||i==="css";let h=!1;if(l){const a=e.localName;(a==="input"||a==="textarea"||a==="select"||e.isContentEditable)&&(h=!0)}if(!h&&r){const a=window.getComputedStyle(e).cursor;["default","auto","pointer","none","inherit"].includes(a)||(h=!0)}h&&(this.state.isNative=!0)}};handleMouseOut=t=>{if(!this.isEnabled)return;const e=t.target;(e===this.state.hoverTarget||e.contains(this.state.hoverTarget))&&(!t.relatedTarget||!this.state.hoverTarget?.contains(t.relatedTarget))&&(this.state.isHover=!1,this.state.hoverTarget=null,this.state.interaction={}),this.state.isNative&&(this.state.isNative=!1)};handleWindowLeave=()=>{this.options.hideOnLeave&&(this.state.hasReceivedInput=!1)};bindEvents(){window.addEventListener("pointermove",this.handleMove,{passive:!0}),window.addEventListener("pointerdown",this.handleDown,{passive:!0}),window.addEventListener("pointerup",this.handleUp),document.addEventListener("mouseover",this.handleMouseOver),document.addEventListener("mouseout",this.handleMouseOut),document.addEventListener("mouseleave",this.handleWindowLeave)}destroy(){this.mediaQueryList&&this.mediaQueryHandler&&this.mediaQueryList.removeEventListener("change",this.mediaQueryHandler),window.removeEventListener("pointermove",this.handleMove),window.removeEventListener("pointerdown",this.handleDown),window.removeEventListener("pointerup",this.handleUp),document.removeEventListener("mouseover",this.handleMouseOver),document.removeEventListener("mouseout",this.handleMouseOut),document.removeEventListener("mouseleave",this.handleWindowLeave)}}function m(o,t,e){return o+(t-o)*e}function c(o,t,e,s){return m(o,t,1-Math.exp(-e*s))}function g(o,t){return Math.atan2(t,o)*(180/Math.PI)}const p=["a","button","input","textarea","[data-hover]","[data-cursor]"];class y{static version="2.0.0";version="2.0.0";state;options;plugins=[];stage;input;rafId=0;lastTime=0;isRunning=!1;hoverSelectors;constructor(t={}){this.options={smoothness:.15,enableTouch:!1,autoDisableOnMobile:!0,ignoreOnNative:"auto",hideCursor:!0,hideOnLeave:!0,autoStart:!0,container:document.body,...t},this.options.container||(this.options.container=document.body),this.state={pointer:{x:-100,y:-100},target:{x:-100,y:-100},smooth:{x:-100,y:-100},velocity:{x:0,y:0},angle:0,isDown:!1,isHover:!1,isNative:!1,forcedCursor:null,hoverTarget:null,reducedMotion:!1,hasReceivedInput:!1,shape:null,interaction:{}},this.options.hoverSelectors?this.hoverSelectors=new Set(this.options.hoverSelectors):this.hoverSelectors=new Set(p),this.stage=new f(this.options.container,!!this.options.hideCursor),this.hoverSelectors.forEach(e=>this.stage.addSelector(e)),this.input=new v(this.state,this.options,()=>Array.from(this.hoverSelectors).join(", "),e=>{e||this.resetPosition()}),this.options.plugins&&this.options.plugins.forEach(e=>this.use(e)),this.init()}getPlugin(t){return this.plugins.find(e=>e.name===t)}get isEnabled(){return this.input.isEnabled}enablePlugin(t){const e=this.getPlugin(t);e&&e.isEnabled===!1&&(e.isEnabled=!0,e.onEnable?.(this))}disablePlugin(t){const e=this.getPlugin(t);e&&e.isEnabled!==!1&&(e.isEnabled=!1,e.onDisable?.(this))}togglePlugin(t){const e=this.getPlugin(t);e&&(e.isEnabled===!1?this.enablePlugin(t):this.disablePlugin(t))}registerHoverTarget(t){this.hoverSelectors.has(t)||(this.hoverSelectors.add(t),this.stage.addSelector(t))}get container(){return this.stage.element}setCursor(t){this.state.forcedCursor=t}init(){this.options.autoStart&&this.startLoop()}enable(){this.input.isEnabled=!0,this.stage.setNativeCursor("none")}disable(){this.input.isEnabled=!1,this.stage.setNativeCursor("auto"),this.resetPosition()}use(t){return this.plugins.find(e=>e.name===t.name)?(console.warn(`[Supermouse] Plugin "${t.name}" already installed.`),this):(t.isEnabled===void 0&&(t.isEnabled=!0),this.plugins.push(t),this.plugins.sort((e,s)=>(e.priority||0)-(s.priority||0)),t.install?.(this),this)}resetPosition(){const t={x:-100,y:-100};this.state.pointer={...t},this.state.target={...t},this.state.smooth={...t},this.state.velocity={x:0,y:0},this.state.angle=0,this.state.hasReceivedInput=!1,this.state.shape=null,this.state.interaction={}}startLoop(){this.isRunning||(this.isRunning=!0,this.lastTime=performance.now(),this.tick(this.lastTime))}step(t){this.tick(t)}runPluginSafe(t,e){if(t.isEnabled!==!1)try{t.update?.(this,e)}catch(s){console.error(`[Supermouse] Plugin '${t.name}' crashed and has been disabled.`,s),t.isEnabled=!1,t.onDisable?.(this)}}tick=t=>{const e=t-this.lastTime,s=Math.min(e/1e3,.1);this.lastTime=t;const n=this.input.isEnabled&&!this.state.isNative&&this.state.hasReceivedInput;if(this.stage.setVisibility(n),this.input.isEnabled&&this.options.hideCursor){let i="auto";this.state.forcedCursor!==null?i=this.state.forcedCursor:i=this.state.isNative||!this.state.hasReceivedInput?"auto":"none",this.stage.setNativeCursor(i)}if(this.input.isEnabled){this.state.target.x=this.state.pointer.x,this.state.target.y=this.state.pointer.y;for(let a=0;a<this.plugins.length;a++)this.runPluginSafe(this.plugins[a],e);const i=this.options.smoothness,l=this.state.reducedMotion?1e3:1/i*2;this.state.smooth.x=c(this.state.smooth.x,this.state.target.x,l,s),this.state.smooth.y=c(this.state.smooth.y,this.state.target.y,l,s);const r=this.state.target.x-this.state.smooth.x,h=this.state.target.y-this.state.smooth.y;this.state.velocity.x=r,this.state.velocity.y=h,(Math.abs(r)>.1||Math.abs(h)>.1)&&(this.state.angle=g(r,h))}else{this.state.smooth.x=-100,this.state.smooth.y=-100,this.state.pointer.x=-100,this.state.pointer.y=-100,this.state.velocity.x=0,this.state.velocity.y=0;for(let i=0;i<this.plugins.length;i++)this.runPluginSafe(this.plugins[i],e)}this.options.autoStart&&this.isRunning&&(this.rafId=requestAnimationFrame(this.tick))};destroy(){this.isRunning=!1,cancelAnimationFrame(this.rafId),this.input.destroy(),this.stage.destroy(),this.plugins.forEach(t=>t.destroy?.(this)),this.plugins=[]}}u.DEFAULT_HOVER_SELECTORS=p,u.Supermouse=y,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})}));
5
+ `}destroy(){this.element.remove(),this.styleTag.remove(),this.container.style.cursor="",this.container.classList.remove(this.scopeClass)}}class v{constructor(t,e,s,n){this.state=t,this.options=e,this.getHoverSelector=s,this.onEnableChange=n,this.checkDeviceCapability(),this.checkMotionPreference(),this.bindEvents()}mediaQueryList;mediaQueryHandler;motionQuery;isEnabled=!0;interactionCache=new WeakMap;checkDeviceCapability(){this.options.autoDisableOnMobile&&(this.mediaQueryList=window.matchMedia("(pointer: fine)"),this.updateEnabledState(this.mediaQueryList.matches),this.mediaQueryHandler=t=>{this.updateEnabledState(t.matches)},this.mediaQueryList.addEventListener("change",this.mediaQueryHandler))}checkMotionPreference(){this.motionQuery=window.matchMedia("(prefer-reduced-motion: reduce)"),this.state.reducedMotion=this.motionQuery.matches,this.motionQuery.addEventListener("change",t=>{this.state.reducedMotion=t.matches})}updateEnabledState(t){this.isEnabled=t,this.onEnableChange(t)}parseDOMInteraction(t){if(this.options.resolveInteraction){this.state.interaction=this.options.resolveInteraction(t);return}if(this.interactionCache.has(t)){this.state.interaction=this.interactionCache.get(t);return}const e={};if(this.options.rules)for(const[n,i]of Object.entries(this.options.rules))t.matches(n)&&Object.assign(e,i);const s=t.dataset;for(const n in s)if(n.startsWith("supermouse")){const i=n.slice(10);if(i){const l=i.charAt(0).toLowerCase()+i.slice(1),r=s[n];e[l]=r===""?!0:r}}this.interactionCache.set(t,e),this.state.interaction=e}handleMove=t=>{if(!this.isEnabled||this.options.autoDisableOnMobile&&t.pointerType==="touch")return;let e=t.clientX,s=t.clientY;if(this.options.container&&this.options.container!==document.body){const n=this.options.container.getBoundingClientRect();e-=n.left,s-=n.top}this.state.pointer.x=e,this.state.pointer.y=s,this.state.hasReceivedInput||(this.state.hasReceivedInput=!0,this.state.target.x=this.state.smooth.x=e,this.state.target.y=this.state.smooth.y=s)};handleDown=()=>{this.isEnabled&&(this.state.isDown=!0)};handleUp=()=>{this.isEnabled&&(this.state.isDown=!1)};handleMouseOver=t=>{if(!this.isEnabled)return;const e=t.target;if(e.closest("[data-supermouse-ignore]")){this.state.isNative=!0;return}const s=this.getHoverSelector(),n=e.closest(s);n&&(this.state.isHover=!0,this.state.hoverTarget=n,this.parseDOMInteraction(this.state.hoverTarget));const i=this.options.ignoreOnNative;if(i){const l=i===!0||i==="auto"||i==="tag",r=i===!0||i==="auto"||i==="css";let h=!1;if(l){const a=e.localName;(a==="input"||a==="textarea"||a==="select"||e.isContentEditable)&&(h=!0)}if(!h&&r){const a=window.getComputedStyle(e).cursor;["default","auto","pointer","none","inherit"].includes(a)||(h=!0)}h&&(this.state.isNative=!0)}};handleMouseOut=t=>{if(!this.isEnabled)return;const e=t.target;(e===this.state.hoverTarget||e.contains(this.state.hoverTarget))&&(!t.relatedTarget||!this.state.hoverTarget?.contains(t.relatedTarget))&&(this.state.isHover=!1,this.state.hoverTarget=null,this.state.interaction={}),this.state.isNative&&(this.state.isNative=!1)};handleWindowLeave=()=>{this.options.hideOnLeave&&(this.state.hasReceivedInput=!1)};bindEvents(){window.addEventListener("pointermove",this.handleMove,{passive:!0}),window.addEventListener("pointerdown",this.handleDown,{passive:!0}),window.addEventListener("pointerup",this.handleUp),document.addEventListener("mouseover",this.handleMouseOver),document.addEventListener("mouseout",this.handleMouseOut),document.addEventListener("mouseleave",this.handleWindowLeave)}destroy(){this.mediaQueryList&&this.mediaQueryHandler&&this.mediaQueryList.removeEventListener("change",this.mediaQueryHandler),window.removeEventListener("pointermove",this.handleMove),window.removeEventListener("pointerdown",this.handleDown),window.removeEventListener("pointerup",this.handleUp),document.removeEventListener("mouseover",this.handleMouseOver),document.removeEventListener("mouseout",this.handleMouseOut),document.removeEventListener("mouseleave",this.handleWindowLeave)}}function m(o,t,e){return o+(t-o)*e}function c(o,t,e,s){return m(o,t,1-Math.exp(-e*s))}function g(o,t){return Math.atan2(t,o)*(180/Math.PI)}const p=["a","button","input","textarea","[data-hover]","[data-cursor]"];class y{static version="2.0.1";version="2.0.1";state;options;plugins=[];stage;input;rafId=0;lastTime=0;isRunning=!1;hoverSelectors;constructor(t={}){this.options={smoothness:.15,enableTouch:!1,autoDisableOnMobile:!0,ignoreOnNative:"auto",hideCursor:!0,hideOnLeave:!0,autoStart:!0,container:document.body,...t},this.options.container||(this.options.container=document.body),this.state={pointer:{x:-100,y:-100},target:{x:-100,y:-100},smooth:{x:-100,y:-100},velocity:{x:0,y:0},angle:0,isDown:!1,isHover:!1,isNative:!1,forcedCursor:null,hoverTarget:null,reducedMotion:!1,hasReceivedInput:!1,shape:null,interaction:{}},this.options.hoverSelectors?this.hoverSelectors=new Set(this.options.hoverSelectors):this.hoverSelectors=new Set(p),this.stage=new f(this.options.container,!!this.options.hideCursor),this.hoverSelectors.forEach(e=>this.stage.addSelector(e)),this.input=new v(this.state,this.options,()=>Array.from(this.hoverSelectors).join(", "),e=>{e||this.resetPosition()}),this.options.plugins&&this.options.plugins.forEach(e=>this.use(e)),this.init()}getPlugin(t){return this.plugins.find(e=>e.name===t)}get isEnabled(){return this.input.isEnabled}enablePlugin(t){const e=this.getPlugin(t);e&&e.isEnabled===!1&&(e.isEnabled=!0,e.onEnable?.(this))}disablePlugin(t){const e=this.getPlugin(t);e&&e.isEnabled!==!1&&(e.isEnabled=!1,e.onDisable?.(this))}togglePlugin(t){const e=this.getPlugin(t);e&&(e.isEnabled===!1?this.enablePlugin(t):this.disablePlugin(t))}registerHoverTarget(t){this.hoverSelectors.has(t)||(this.hoverSelectors.add(t),this.stage.addSelector(t))}get container(){return this.stage.element}setCursor(t){this.state.forcedCursor=t}init(){this.options.autoStart&&this.startLoop()}enable(){this.input.isEnabled=!0,this.stage.setNativeCursor("none")}disable(){this.input.isEnabled=!1,this.stage.setNativeCursor("auto"),this.resetPosition()}use(t){return this.plugins.find(e=>e.name===t.name)?(console.warn(`[Supermouse] Plugin "${t.name}" already installed.`),this):(t.isEnabled===void 0&&(t.isEnabled=!0),this.plugins.push(t),this.plugins.sort((e,s)=>(e.priority||0)-(s.priority||0)),t.install?.(this),this)}resetPosition(){const t={x:-100,y:-100};this.state.pointer={...t},this.state.target={...t},this.state.smooth={...t},this.state.velocity={x:0,y:0},this.state.angle=0,this.state.hasReceivedInput=!1,this.state.shape=null,this.state.interaction={}}startLoop(){this.isRunning||(this.isRunning=!0,this.lastTime=performance.now(),this.tick(this.lastTime))}step(t){this.tick(t)}runPluginSafe(t,e){if(t.isEnabled!==!1)try{t.update?.(this,e)}catch(s){console.error(`[Supermouse] Plugin '${t.name}' crashed and has been disabled.`,s),t.isEnabled=!1,t.onDisable?.(this)}}tick=t=>{const e=t-this.lastTime,s=Math.min(e/1e3,.1);this.lastTime=t;const n=this.input.isEnabled&&!this.state.isNative&&this.state.hasReceivedInput;if(this.stage.setVisibility(n),this.input.isEnabled&&this.options.hideCursor){let i="auto";this.state.forcedCursor!==null?i=this.state.forcedCursor:i=this.state.isNative||!this.state.hasReceivedInput?"auto":"none",this.stage.setNativeCursor(i)}if(this.input.isEnabled){this.state.target.x=this.state.pointer.x,this.state.target.y=this.state.pointer.y;for(let a=0;a<this.plugins.length;a++)this.runPluginSafe(this.plugins[a],e);const i=this.options.smoothness,l=this.state.reducedMotion?1e3:1/i*2;this.state.smooth.x=c(this.state.smooth.x,this.state.target.x,l,s),this.state.smooth.y=c(this.state.smooth.y,this.state.target.y,l,s);const r=this.state.target.x-this.state.smooth.x,h=this.state.target.y-this.state.smooth.y;this.state.velocity.x=r,this.state.velocity.y=h,(Math.abs(r)>.1||Math.abs(h)>.1)&&(this.state.angle=g(r,h))}else{this.state.smooth.x=-100,this.state.smooth.y=-100,this.state.pointer.x=-100,this.state.pointer.y=-100,this.state.velocity.x=0,this.state.velocity.y=0;for(let i=0;i<this.plugins.length;i++)this.runPluginSafe(this.plugins[i],e)}this.options.autoStart&&this.isRunning&&(this.rafId=requestAnimationFrame(this.tick))};destroy(){this.isRunning=!1,cancelAnimationFrame(this.rafId),this.input.destroy(),this.stage.destroy(),this.plugins.forEach(t=>t.destroy?.(this)),this.plugins=[]}}u.DEFAULT_HOVER_SELECTORS=p,u.Supermouse=y,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supermousejs/core",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "main": "dist/index.umd.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",