@supermousejs/core 2.1.0 → 2.2.0

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,51 +1,57 @@
1
- # @supermousejs/core
2
-
3
- ## 2.1.0
4
-
5
- ### Minor Changes
6
-
7
- - 2590af3: - Refactored engine by removing 200 lines of redundant comments and typedocs, with appropriate re-reference to canon web docs
8
- - Fixed a framework reactivity cache trap by moving away from WeakMap (computations are light and relatively inexpensive)
9
- - Fixed double crashing by implementing a `try {} catch {}` safety net for plugin installation
10
- - Fixed the Input layer not refreshing plugin states (particularly on hover) when DOM content is detached in reactive frameworks with `Node.isConnected`
11
-
12
- ### Patch Changes
13
-
14
- - 6d70c18: remove legacy package and update supermouse domain in readme
15
- - 14fb5b6: Updated tsconfig to be reference-compliant with core, utils and zoetrope when required
16
-
17
- ## 2.0.5
18
-
19
- ### Patch Changes
20
-
21
- - 67f771b: Add relevant npm metadata to package.json file
22
-
23
- ## 2.0.4
24
-
25
- ### Patch Changes
26
-
27
- - 993dc67: Updated supemousejs packages with proper author, license and url descriptors to repo
28
-
29
- ## 2.0.3
30
-
31
- ### Patch Changes
32
-
33
- - Add keywords to core package
34
-
35
- ## 2.0.2
36
-
37
- ### Patch Changes
38
-
39
- - ae219a0: Update READMEs with correct link to documentation
40
-
41
- ## 2.0.1
42
-
43
- ### Patch Changes
44
-
45
- - Add minimal README.md files to packages
46
-
47
- ## 2.0.0
48
-
49
- ### Major Changes
50
-
51
- - Initial v2.0.0 release
1
+ # @supermousejs/core
2
+
3
+ ## 2.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - f6f44b2: Improved tree-shaking by consolidating subordinate files and helpers into the main module file
8
+
9
+ ## 2.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 2590af3: - Refactored engine by removing 200 lines of redundant comments and typedocs, with appropriate re-reference to canon web docs
14
+ - Fixed a framework reactivity cache trap by moving away from WeakMap (computations are light and relatively inexpensive)
15
+ - Fixed double crashing by implementing a `try {} catch {}` safety net for plugin installation
16
+ - Fixed the Input layer not refreshing plugin states (particularly on hover) when DOM content is detached in reactive frameworks with `Node.isConnected`
17
+
18
+ ### Patch Changes
19
+
20
+ - 6d70c18: remove legacy package and update supermouse domain in readme
21
+ - 14fb5b6: Updated tsconfig to be reference-compliant with core, utils and zoetrope when required
22
+
23
+ ## 2.0.5
24
+
25
+ ### Patch Changes
26
+
27
+ - 67f771b: Add relevant npm metadata to package.json file
28
+
29
+ ## 2.0.4
30
+
31
+ ### Patch Changes
32
+
33
+ - 993dc67: Updated supemousejs packages with proper author, license and url descriptors to repo
34
+
35
+ ## 2.0.3
36
+
37
+ ### Patch Changes
38
+
39
+ - Add keywords to core package
40
+
41
+ ## 2.0.2
42
+
43
+ ### Patch Changes
44
+
45
+ - ae219a0: Update READMEs with correct link to documentation
46
+
47
+ ## 2.0.1
48
+
49
+ ### Patch Changes
50
+
51
+ - Add minimal README.md files to packages
52
+
53
+ ## 2.0.0
54
+
55
+ ### Major Changes
56
+
57
+ - Initial v2.0.0 release
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export declare const DEFAULT_HOVER_SELECTORS: string[];
2
2
 
3
+ /* Excluded from this release type: Input */
4
+
3
5
  /**
4
6
  * The Interface for interaction state.
5
7
  * Plugins should use Module Augmentation to add their specific properties to this interface.
@@ -69,11 +71,15 @@ export declare interface ShapeState {
69
71
  borderRadius: number;
70
72
  }
71
73
 
74
+ /* Excluded from this release type: Stage */
75
+
72
76
  /**
73
- * Runtime Loop of Supermouse.
77
+ * Supermouse Runtime Loop
78
+ *
79
+ * This class orchestrates the application state, manages the animation loop,
80
+ * and coordinates data flow between the internal systems, and the plugins.
74
81
  *
75
- * This class orchestrates the application state, manages the animation loop (`requestAnimationFrame`),
76
- * and coordinates data flow between the Input system, the Stage system, and the Plugins.
82
+ * @default
77
83
  */
78
84
  export declare class Supermouse {
79
85
  static readonly version: string;
@@ -139,6 +145,7 @@ export declare class Supermouse {
139
145
  * @param plugin - The plugin object to install.
140
146
  */
141
147
  use(plugin: SupermousePlugin): this;
148
+ private resetCoords;
142
149
  private resetPosition;
143
150
  private startLoop;
144
151
  /**
package/dist/index.mjs CHANGED
@@ -1,78 +1,15 @@
1
- let d = 0;
2
- class c {
3
- constructor(t = document.body, e) {
4
- if (this.container = t, this.hideNativeCursor = e, !t || !(t instanceof HTMLElement))
5
- throw new Error(`[Supermouse] Invalid container: ${t}. Must be an HTMLElement.`);
6
- const i = d++;
7
- this.id = `supermouse-style-${i}`, this.scopeClass = `supermouse-scope-${i}`;
8
- const n = t === document.body;
9
- this.element = document.createElement("div"), Object.assign(this.element.style, {
10
- position: n ? "fixed" : "absolute",
11
- top: "0",
12
- left: "0",
13
- width: "100%",
14
- height: "100%",
15
- pointerEvents: "none",
16
- zIndex: "9999",
17
- opacity: "1",
18
- transition: "opacity 0.15s ease"
19
- }), n || window.getComputedStyle(t).position === "static" && (t.style.position = "relative"), t.appendChild(this.element), this.styleTag = document.createElement("style"), this.styleTag.id = this.id, document.head.appendChild(this.styleTag), this.container.classList.add(this.scopeClass), this.hideNativeCursor && this.setNativeCursor("none");
20
- }
21
- container;
22
- hideNativeCursor;
23
- /** The container element appended to the document. */
24
- element;
25
- styleTag;
26
- id;
27
- scopeClass;
28
- currentCursorState = null;
29
- selectors = /* @__PURE__ */ new Set([
30
- "a",
31
- "button",
32
- "input",
33
- "textarea",
34
- "select",
35
- '[role="button"]',
36
- "[tabindex]"
37
- ]);
38
- /**
39
- * Adds a new CSS selector to the Hide Native Cursor list.
40
- * Called by `Supermouse` (and subsequently plugins) during install to ensure
41
- * the native cursor is hidden on their specific interactive targets.
42
- */
43
- addSelector(t) {
44
- this.selectors.add(t), this.hideNativeCursor && this.updateCursorCSS();
45
- }
46
- setVisibility(t) {
47
- this.element.style.opacity = t ? "1" : "0";
48
- }
49
- /**
50
- * Toggles the visibility of the native cursor via CSS injection.
51
- * @param type 'none' to hide, 'auto' to show.
52
- */
53
- setNativeCursor(t) {
54
- !this.hideNativeCursor && t === "none" || t !== this.currentCursorState && (this.currentCursorState = t, t === "none" ? (this.container.style.cursor = "none", this.updateCursorCSS()) : (this.container.style.cursor = "", this.styleTag.innerText = ""));
55
- }
56
- updateCursorCSS() {
57
- const t = Array.from(this.selectors);
58
- if (t.length === 0) {
59
- this.styleTag.innerText = "";
60
- return;
61
- }
62
- const e = t.map((i) => `.${this.scopeClass} ${i}`).join(", ");
63
- this.styleTag.innerText = `
64
- ${e} {
65
- cursor: none !important;
66
- }
67
- `;
68
- }
69
- destroy() {
70
- this.element.remove(), this.styleTag.remove(), this.container.style.cursor = "", this.container.classList.remove(this.scopeClass);
71
- }
1
+ function c(n, t, e) {
2
+ return n + (t - n) * e;
3
+ }
4
+ function d(n, t, e, i) {
5
+ return c(n, t, 1 - Math.exp(-e * i));
72
6
  }
73
- class p {
74
- constructor(t, e, i, n) {
75
- this.state = t, this.options = e, this.getHoverSelector = i, this.onEnableChange = n, this.checkDeviceCapability(), this.checkMotionPreference(), this.bindEvents();
7
+ function p(n, t) {
8
+ return Math.atan2(t, n) * (180 / Math.PI);
9
+ }
10
+ class f {
11
+ constructor(t, e, i, o) {
12
+ this.state = t, this.options = e, this.getHoverSelector = i, this.onEnableChange = o, this.checkDeviceCapability(), this.checkMotionPreference(), this.bindEvents();
76
13
  }
77
14
  state;
78
15
  options;
@@ -86,23 +23,29 @@ class p {
86
23
  * Toggled by `Supermouse.enable()`/`disable()` or automatically by device capability checks.
87
24
  */
88
25
  isEnabled = !0;
26
+ abortController = new AbortController();
89
27
  /**
90
28
  * Automatically disables the custom cursor on devices without fine pointer control.
91
- * Relies on `matchMedia('(pointer: fine)')`.
92
29
  */
93
30
  checkDeviceCapability() {
94
31
  this.options.autoDisableOnMobile && (this.mediaQueryList = window.matchMedia("(pointer: fine)"), this.updateEnabledState(this.mediaQueryList.matches), this.mediaQueryHandler = (t) => {
95
32
  this.updateEnabledState(t.matches);
96
- }, this.mediaQueryList.addEventListener("change", this.mediaQueryHandler));
33
+ }, this.mediaQueryList.addEventListener("change", this.mediaQueryHandler, {
34
+ signal: this.abortController.signal
35
+ }));
97
36
  }
98
37
  /**
99
38
  * Checks for `prefers-reduced-motion`.
100
39
  * If true, the core physics engine will switch to instant snapping (high damping) to avoid motion sickness.
101
40
  */
102
41
  checkMotionPreference() {
103
- this.motionQuery = window.matchMedia("(prefers-reduced-motion: reduce)"), this.state.reducedMotion = this.motionQuery.matches, this.motionQuery.addEventListener("change", (t) => {
104
- this.state.reducedMotion = t.matches;
105
- });
42
+ this.motionQuery = window.matchMedia("(prefers-reduced-motion: reduce)"), this.state.reducedMotion = this.motionQuery.matches, this.motionQuery.addEventListener(
43
+ "change",
44
+ (t) => {
45
+ this.state.reducedMotion = t.matches;
46
+ },
47
+ { signal: this.abortController.signal }
48
+ );
106
49
  }
107
50
  updateEnabledState(t) {
108
51
  this.isEnabled = t, this.onEnableChange(t);
@@ -114,14 +57,14 @@ class p {
114
57
  }
115
58
  const e = {};
116
59
  if (this.options.rules)
117
- for (const [n, s] of Object.entries(this.options.rules))
118
- t.matches(n) && Object.assign(e, s);
60
+ for (const [o, s] of Object.entries(this.options.rules))
61
+ t.matches(o) && Object.assign(e, s);
119
62
  const i = t.dataset;
120
- for (const n in i)
121
- if (n.startsWith("supermouse")) {
122
- const s = n.slice(10);
63
+ for (const o in i)
64
+ if (o.startsWith("supermouse")) {
65
+ const s = o.slice(10);
123
66
  if (s) {
124
- const r = s.charAt(0).toLowerCase() + s.slice(1), a = i[n];
67
+ const r = s.charAt(0).toLowerCase() + s.slice(1), a = i[o];
125
68
  a !== void 0 && (e[r] = a === "" ? !0 : a);
126
69
  }
127
70
  }
@@ -131,8 +74,8 @@ class p {
131
74
  if (!this.isEnabled || this.options.autoDisableOnMobile && t.pointerType === "touch") return;
132
75
  let e = t.clientX, i = t.clientY;
133
76
  if (this.options.container && this.options.container !== document.body) {
134
- const n = this.options.container.getBoundingClientRect();
135
- e -= n.left, i -= n.top;
77
+ const o = this.options.container.getBoundingClientRect();
78
+ e -= o.left, i -= o.top;
136
79
  }
137
80
  this.state.pointer.x = e, this.state.pointer.y = i, this.state.hasReceivedInput || (this.state.hasReceivedInput = !0, this.state.target.x = this.state.smooth.x = e, this.state.target.y = this.state.smooth.y = i);
138
81
  }
@@ -149,21 +92,21 @@ class p {
149
92
  this.state.isNative = !0;
150
93
  return;
151
94
  }
152
- const i = this.getHoverSelector(), n = e.closest(i);
153
- n && (this.state.isHover = !0, this.state.hoverTarget = n, this.parseDOMInteraction(this.state.hoverTarget));
95
+ const i = this.getHoverSelector(), o = e.closest(i);
96
+ o && (this.state.isHover = !0, this.state.hoverTarget = o, this.parseDOMInteraction(this.state.hoverTarget));
154
97
  const s = this.options.ignoreOnNative;
155
98
  if (s) {
156
99
  const r = s === !0 || s === "auto" || s === "tag", a = s === !0 || s === "auto" || s === "css";
157
- let h = !1;
100
+ let l = !1;
158
101
  if (r) {
159
- const l = e.localName;
160
- (l === "input" || l === "textarea" || l === "select" || e.isContentEditable) && (h = !0);
102
+ const h = e.localName;
103
+ (h === "input" || h === "textarea" || h === "select" || e.isContentEditable) && (l = !0);
161
104
  }
162
- if (!h && a) {
163
- const l = window.getComputedStyle(e).cursor;
164
- ["default", "auto", "pointer", "none", "inherit"].includes(l) || (h = !0);
105
+ if (!l && a) {
106
+ const h = window.getComputedStyle(e).cursor;
107
+ ["default", "auto", "pointer", "none", "inherit"].includes(h) || (l = !0);
165
108
  }
166
- h && (this.state.isNative = !0);
109
+ l && (this.state.isNative = !0);
167
110
  }
168
111
  }
169
112
  handleMouseOut(t) {
@@ -178,22 +121,86 @@ class p {
178
121
  this.state.isHover = !1, this.state.hoverTarget = null, this.state.isNative = !1;
179
122
  }
180
123
  bindEvents() {
181
- window.addEventListener("pointermove", this.handleMove.bind(this), { passive: !0 }), window.addEventListener("pointerdown", this.handleDown.bind(this), { passive: !0 }), window.addEventListener("pointerup", this.handleUp.bind(this)), document.addEventListener("mouseover", this.handleMouseOver.bind(this)), document.addEventListener("mouseout", this.handleMouseOut.bind(this)), document.addEventListener("mouseleave", this.handleWindowLeave.bind(this));
124
+ const { signal: t } = this.abortController;
125
+ window.addEventListener("pointermove", this.handleMove.bind(this), { passive: !0, signal: t }), window.addEventListener("pointerdown", this.handleDown.bind(this), { passive: !0, signal: t }), window.addEventListener("pointerup", this.handleUp.bind(this), { signal: t }), document.addEventListener("mouseover", this.handleMouseOver.bind(this), { signal: t }), document.addEventListener("mouseout", this.handleMouseOut.bind(this), { signal: t }), document.addEventListener("mouseleave", this.handleWindowLeave.bind(this), { signal: t });
182
126
  }
183
127
  destroy() {
184
- this.mediaQueryList && this.mediaQueryHandler && this.mediaQueryList.removeEventListener("change", this.mediaQueryHandler), this.motionQuery && (this.motionQuery.onchange = null), 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);
128
+ this.abortController.abort();
185
129
  }
186
130
  }
187
- function v(o, t, e) {
188
- return o + (t - o) * e;
189
- }
190
- function u(o, t, e, i) {
191
- return v(o, t, 1 - Math.exp(-e * i));
192
- }
193
- function f(o, t) {
194
- return Math.atan2(t, o) * (180 / Math.PI);
131
+ let g = 0;
132
+ class v {
133
+ constructor(t = document.body, e) {
134
+ if (this.container = t, this.hideNativeCursor = e, !t || !(t instanceof HTMLElement))
135
+ throw new Error(`[Supermouse] Invalid container: ${t}. Must be an HTMLElement.`);
136
+ const i = g++;
137
+ this.id = `supermouse-style-${i}`, this.scopeClass = `supermouse-scope-${i}`;
138
+ const o = t === document.body;
139
+ this.element = document.createElement("div"), Object.assign(this.element.style, {
140
+ position: o ? "fixed" : "absolute",
141
+ top: "0",
142
+ left: "0",
143
+ width: "100%",
144
+ height: "100%",
145
+ pointerEvents: "none",
146
+ zIndex: "9999",
147
+ opacity: "1",
148
+ transition: "opacity 0.15s ease"
149
+ }), o || window.getComputedStyle(t).position === "static" && (t.style.position = "relative"), t.appendChild(this.element), this.styleTag = document.createElement("style"), this.styleTag.id = this.id, document.head.appendChild(this.styleTag), this.container.classList.add(this.scopeClass), this.hideNativeCursor && this.setNativeCursor("none");
150
+ }
151
+ container;
152
+ hideNativeCursor;
153
+ /** The container element appended to the document. */
154
+ element;
155
+ styleTag;
156
+ id;
157
+ scopeClass;
158
+ currentCursorState = null;
159
+ selectors = /* @__PURE__ */ new Set([
160
+ "a",
161
+ "button",
162
+ "input",
163
+ "textarea",
164
+ "select",
165
+ '[role="button"]',
166
+ "[tabindex]"
167
+ ]);
168
+ /**
169
+ * Adds a new CSS selector to the `selectors` set.
170
+ * Called by `Supermouse` and subsequently plugins during install to ensure
171
+ * the native cursor is hidden on their specific interactive targets.
172
+ */
173
+ addSelector(t) {
174
+ this.selectors.add(t), this.hideNativeCursor && this.updateCursorCSS();
175
+ }
176
+ setVisibility(t) {
177
+ this.element.style.opacity = t ? "1" : "0";
178
+ }
179
+ /**
180
+ * Toggles the visibility of the native cursor via CSS injection.
181
+ * @param type 'none' to hide, 'auto' to show.
182
+ */
183
+ setNativeCursor(t) {
184
+ !this.hideNativeCursor && t === "none" || t !== this.currentCursorState && (this.currentCursorState = t, t === "none" ? (this.container.style.cursor = "none", this.updateCursorCSS()) : (this.container.style.cursor = "", this.styleTag.innerText = ""));
185
+ }
186
+ updateCursorCSS() {
187
+ const t = Array.from(this.selectors);
188
+ if (t.length === 0) {
189
+ this.styleTag.innerText = "";
190
+ return;
191
+ }
192
+ const e = t.map((i) => `.${this.scopeClass} ${i}`).join(", ");
193
+ this.styleTag.innerText = `
194
+ ${e} {
195
+ cursor: none !important;
196
+ }
197
+ `;
198
+ }
199
+ destroy() {
200
+ this.element.remove(), this.styleTag.remove(), this.container.style.cursor = "", this.container.classList.remove(this.scopeClass);
201
+ }
195
202
  }
196
- const g = [
203
+ const u = { x: -100, y: -100 }, m = [
197
204
  "a",
198
205
  "button",
199
206
  "input",
@@ -202,8 +209,8 @@ const g = [
202
209
  "[data-cursor]"
203
210
  ];
204
211
  class y {
205
- static version = "2.1.0";
206
- version = "2.1.0";
212
+ static version = "2.2.0";
213
+ version = "2.2.0";
207
214
  state;
208
215
  /**
209
216
  * Configuration options.
@@ -248,7 +255,7 @@ class y {
248
255
  hasReceivedInput: !1,
249
256
  shape: null,
250
257
  interaction: {}
251
- }, this.options.hoverSelectors ? this.hoverSelectors = new Set(this.options.hoverSelectors) : this.hoverSelectors = new Set(g), this.stage = new c(this.options.container, !!this.options.hideCursor), this.hoverSelectors.forEach((e) => this.stage.addSelector(e)), this.input = new p(
258
+ }, this.options.hoverSelectors ? this.hoverSelectors = new Set(this.options.hoverSelectors) : this.hoverSelectors = new Set(m), this.stage = new v(this.options.container, !!this.options.hideCursor), this.hoverSelectors.forEach((e) => this.stage.addSelector(e)), this.input = new f(
252
259
  this.state,
253
260
  this.options,
254
261
  () => Array.from(this.hoverSelectors).join(", "),
@@ -326,9 +333,11 @@ class y {
326
333
  use(t) {
327
334
  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, i) => (e.priority || 0) - (i.priority || 0)), t.install?.(this), this);
328
335
  }
336
+ resetCoords() {
337
+ this.state.pointer = { ...u }, this.state.target = { ...u }, this.state.smooth = { ...u }, this.state.velocity = { x: 0, y: 0 }, this.state.angle = 0;
338
+ }
329
339
  resetPosition() {
330
- const t = { x: -100, y: -100 };
331
- 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 = {};
340
+ this.resetCoords(), this.state.hasReceivedInput = !1, this.state.shape = null, this.state.interaction = {};
332
341
  }
333
342
  startLoop() {
334
343
  this.isRunning || (this.isRunning = !0, this.lastTime = performance.now(), this.tick(this.lastTime));
@@ -349,7 +358,8 @@ class y {
349
358
  console.error(`[Supermouse] Plugin '${t.name}' crashed and has been disabled.`, i), t.isEnabled = !1;
350
359
  try {
351
360
  t.onDisable?.(this);
352
- } catch {
361
+ } catch (o) {
362
+ console.error(`[Supermouse] Failed to execute onDisable for plugin '${t.name}'.`, o);
353
363
  }
354
364
  }
355
365
  }
@@ -359,23 +369,19 @@ class y {
359
369
  tick = (t) => {
360
370
  const e = t - this.lastTime, i = Math.min(e / 1e3, 0.1);
361
371
  this.lastTime = t, this.state.hoverTarget && !this.state.hoverTarget.isConnected && this.input.clearHover();
362
- const n = this.input.isEnabled && !this.state.isNative && this.state.hasReceivedInput;
363
- if (this.stage.setVisibility(n), this.input.isEnabled && this.options.hideCursor) {
372
+ const o = this.input.isEnabled && !this.state.isNative && this.state.hasReceivedInput;
373
+ if (this.stage.setVisibility(o), this.input.isEnabled && this.options.hideCursor) {
364
374
  let s = "auto";
365
375
  this.state.forcedCursor !== null ? s = this.state.forcedCursor : s = this.state.isNative || !this.state.hasReceivedInput ? "auto" : "none", this.stage.setNativeCursor(s);
366
376
  }
377
+ this.input.isEnabled ? (this.state.target.x = this.state.pointer.x, this.state.target.y = this.state.pointer.y) : this.resetCoords();
378
+ for (let s = 0; s < this.plugins.length; s++)
379
+ this.runPluginSafe(this.plugins[s], e);
367
380
  if (this.input.isEnabled) {
368
- this.state.target.x = this.state.pointer.x, this.state.target.y = this.state.pointer.y;
369
- for (let h = 0; h < this.plugins.length; h++)
370
- this.runPluginSafe(this.plugins[h], e);
371
381
  const s = this.state.reducedMotion ? 1e3 : 1 / this.options.smoothness * 2;
372
- this.state.smooth.x = u(this.state.smooth.x, this.state.target.x, s, i), this.state.smooth.y = u(this.state.smooth.y, this.state.target.y, s, i);
382
+ this.state.smooth.x = d(this.state.smooth.x, this.state.target.x, s, i), this.state.smooth.y = d(this.state.smooth.y, this.state.target.y, s, i);
373
383
  const r = this.state.target.x - this.state.smooth.x, a = this.state.target.y - this.state.smooth.y;
374
- this.state.velocity.x = r, this.state.velocity.y = a, (Math.abs(r) > 0.1 || Math.abs(a) > 0.1) && (this.state.angle = f(r, a));
375
- } else {
376
- 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;
377
- for (let s = 0; s < this.plugins.length; s++)
378
- this.runPluginSafe(this.plugins[s], e);
384
+ this.state.velocity.x = r, this.state.velocity.y = a, (Math.abs(r) > 0.1 || Math.abs(a) > 0.1) && (this.state.angle = p(r, a));
379
385
  }
380
386
  this.options.autoStart && this.isRunning && (this.rafId = requestAnimationFrame(this.tick));
381
387
  };
@@ -387,6 +393,8 @@ class y {
387
393
  }
388
394
  }
389
395
  export {
390
- g as DEFAULT_HOVER_SELECTORS,
396
+ m as DEFAULT_HOVER_SELECTORS,
397
+ f as Input,
398
+ v as Stage,
391
399
  y as Supermouse
392
400
  };
package/dist/index.umd.js CHANGED
@@ -1,5 +1,5 @@
1
- (function(l,u){typeof exports=="object"&&typeof module<"u"?u(exports):typeof define=="function"&&define.amd?define(["exports"],u):(l=typeof globalThis<"u"?globalThis:l||self,u(l.SupermouseCore={}))})(this,(function(l){"use strict";let u=0;class f{constructor(t=document.body,e){if(this.container=t,this.hideNativeCursor=e,!t||!(t instanceof HTMLElement))throw new Error(`[Supermouse] Invalid container: ${t}. Must be an HTMLElement.`);const i=u++;this.id=`supermouse-style-${i}`,this.scopeClass=`supermouse-scope-${i}`;const n=t===document.body;this.element=document.createElement("div"),Object.assign(this.element.style,{position:n?"fixed":"absolute",top:"0",left:"0",width:"100%",height:"100%",pointerEvents:"none",zIndex:"9999",opacity:"1",transition:"opacity 0.15s ease"}),n||window.getComputedStyle(t).position==="static"&&(t.style.position="relative"),t.appendChild(this.element),this.styleTag=document.createElement("style"),this.styleTag.id=this.id,document.head.appendChild(this.styleTag),this.container.classList.add(this.scopeClass),this.hideNativeCursor&&this.setNativeCursor("none")}container;hideNativeCursor;element;styleTag;id;scopeClass;currentCursorState=null;selectors=new Set(["a","button","input","textarea","select",'[role="button"]',"[tabindex]"]);addSelector(t){this.selectors.add(t),this.hideNativeCursor&&this.updateCursorCSS()}setVisibility(t){this.element.style.opacity=t?"1":"0"}setNativeCursor(t){!this.hideNativeCursor&&t==="none"||t!==this.currentCursorState&&(this.currentCursorState=t,t==="none"?(this.container.style.cursor="none",this.updateCursorCSS()):(this.container.style.cursor="",this.styleTag.innerText=""))}updateCursorCSS(){const t=Array.from(this.selectors);if(t.length===0){this.styleTag.innerText="";return}const e=t.map(i=>`.${this.scopeClass} ${i}`).join(", ");this.styleTag.innerText=`
1
+ (function(n,l){typeof exports=="object"&&typeof module<"u"?l(exports):typeof define=="function"&&define.amd?define(["exports"],l):(n=typeof globalThis<"u"?globalThis:n||self,l(n.SupermouseCore={}))})(this,(function(n){"use strict";function l(a,t,e){return a+(t-a)*e}function p(a,t,e,i){return l(a,t,1-Math.exp(-e*i))}function m(a,t){return Math.atan2(t,a)*(180/Math.PI)}class f{constructor(t,e,i,o){this.state=t,this.options=e,this.getHoverSelector=i,this.onEnableChange=o,this.checkDeviceCapability(),this.checkMotionPreference(),this.bindEvents()}state;options;getHoverSelector;onEnableChange;mediaQueryList;mediaQueryHandler;motionQuery;isEnabled=!0;abortController=new AbortController;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,{signal:this.abortController.signal}))}checkMotionPreference(){this.motionQuery=window.matchMedia("(prefers-reduced-motion: reduce)"),this.state.reducedMotion=this.motionQuery.matches,this.motionQuery.addEventListener("change",t=>{this.state.reducedMotion=t.matches},{signal:this.abortController.signal})}updateEnabledState(t){this.isEnabled=t,this.onEnableChange(t)}parseDOMInteraction(t){if(this.options.resolveInteraction){this.state.interaction=this.options.resolveInteraction(t);return}const e={};if(this.options.rules)for(const[o,s]of Object.entries(this.options.rules))t.matches(o)&&Object.assign(e,s);const i=t.dataset;for(const o in i)if(o.startsWith("supermouse")){const s=o.slice(10);if(s){const h=s.charAt(0).toLowerCase()+s.slice(1),r=i[o];r!==void 0&&(e[h]=r===""?!0:r)}}this.state.interaction=e}handleMove(t){if(!this.isEnabled||this.options.autoDisableOnMobile&&t.pointerType==="touch")return;let e=t.clientX,i=t.clientY;if(this.options.container&&this.options.container!==document.body){const o=this.options.container.getBoundingClientRect();e-=o.left,i-=o.top}this.state.pointer.x=e,this.state.pointer.y=i,this.state.hasReceivedInput||(this.state.hasReceivedInput=!0,this.state.target.x=this.state.smooth.x=e,this.state.target.y=this.state.smooth.y=i)}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 i=this.getHoverSelector(),o=e.closest(i);o&&(this.state.isHover=!0,this.state.hoverTarget=o,this.parseDOMInteraction(this.state.hoverTarget));const s=this.options.ignoreOnNative;if(s){const h=s===!0||s==="auto"||s==="tag",r=s===!0||s==="auto"||s==="css";let d=!1;if(h){const u=e.localName;(u==="input"||u==="textarea"||u==="select"||e.isContentEditable)&&(d=!0)}if(!d&&r){const u=window.getComputedStyle(e).cursor;["default","auto","pointer","none","inherit"].includes(u)||(d=!0)}d&&(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)}clearHover(){this.state.isHover=!1,this.state.hoverTarget=null,this.state.isNative=!1}bindEvents(){const{signal:t}=this.abortController;window.addEventListener("pointermove",this.handleMove.bind(this),{passive:!0,signal:t}),window.addEventListener("pointerdown",this.handleDown.bind(this),{passive:!0,signal:t}),window.addEventListener("pointerup",this.handleUp.bind(this),{signal:t}),document.addEventListener("mouseover",this.handleMouseOver.bind(this),{signal:t}),document.addEventListener("mouseout",this.handleMouseOut.bind(this),{signal:t}),document.addEventListener("mouseleave",this.handleWindowLeave.bind(this),{signal:t})}destroy(){this.abortController.abort()}}let b=0;class g{constructor(t=document.body,e){if(this.container=t,this.hideNativeCursor=e,!t||!(t instanceof HTMLElement))throw new Error(`[Supermouse] Invalid container: ${t}. Must be an HTMLElement.`);const i=b++;this.id=`supermouse-style-${i}`,this.scopeClass=`supermouse-scope-${i}`;const o=t===document.body;this.element=document.createElement("div"),Object.assign(this.element.style,{position:o?"fixed":"absolute",top:"0",left:"0",width:"100%",height:"100%",pointerEvents:"none",zIndex:"9999",opacity:"1",transition:"opacity 0.15s ease"}),o||window.getComputedStyle(t).position==="static"&&(t.style.position="relative"),t.appendChild(this.element),this.styleTag=document.createElement("style"),this.styleTag.id=this.id,document.head.appendChild(this.styleTag),this.container.classList.add(this.scopeClass),this.hideNativeCursor&&this.setNativeCursor("none")}container;hideNativeCursor;element;styleTag;id;scopeClass;currentCursorState=null;selectors=new Set(["a","button","input","textarea","select",'[role="button"]',"[tabindex]"]);addSelector(t){this.selectors.add(t),this.hideNativeCursor&&this.updateCursorCSS()}setVisibility(t){this.element.style.opacity=t?"1":"0"}setNativeCursor(t){!this.hideNativeCursor&&t==="none"||t!==this.currentCursorState&&(this.currentCursorState=t,t==="none"?(this.container.style.cursor="none",this.updateCursorCSS()):(this.container.style.cursor="",this.styleTag.innerText=""))}updateCursorCSS(){const t=Array.from(this.selectors);if(t.length===0){this.styleTag.innerText="";return}const e=t.map(i=>`.${this.scopeClass} ${i}`).join(", ");this.styleTag.innerText=`
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,i,n){this.state=t,this.options=e,this.getHoverSelector=i,this.onEnableChange=n,this.checkDeviceCapability(),this.checkMotionPreference(),this.bindEvents()}state;options;getHoverSelector;onEnableChange;mediaQueryList;mediaQueryHandler;motionQuery;isEnabled=!0;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("(prefers-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}const e={};if(this.options.rules)for(const[n,s]of Object.entries(this.options.rules))t.matches(n)&&Object.assign(e,s);const i=t.dataset;for(const n in i)if(n.startsWith("supermouse")){const s=n.slice(10);if(s){const r=s.charAt(0).toLowerCase()+s.slice(1),a=i[n];a!==void 0&&(e[r]=a===""?!0:a)}}this.state.interaction=e}handleMove(t){if(!this.isEnabled||this.options.autoDisableOnMobile&&t.pointerType==="touch")return;let e=t.clientX,i=t.clientY;if(this.options.container&&this.options.container!==document.body){const n=this.options.container.getBoundingClientRect();e-=n.left,i-=n.top}this.state.pointer.x=e,this.state.pointer.y=i,this.state.hasReceivedInput||(this.state.hasReceivedInput=!0,this.state.target.x=this.state.smooth.x=e,this.state.target.y=this.state.smooth.y=i)}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 i=this.getHoverSelector(),n=e.closest(i);n&&(this.state.isHover=!0,this.state.hoverTarget=n,this.parseDOMInteraction(this.state.hoverTarget));const s=this.options.ignoreOnNative;if(s){const r=s===!0||s==="auto"||s==="tag",a=s===!0||s==="auto"||s==="css";let h=!1;if(r){const d=e.localName;(d==="input"||d==="textarea"||d==="select"||e.isContentEditable)&&(h=!0)}if(!h&&a){const d=window.getComputedStyle(e).cursor;["default","auto","pointer","none","inherit"].includes(d)||(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)}clearHover(){this.state.isHover=!1,this.state.hoverTarget=null,this.state.isNative=!1}bindEvents(){window.addEventListener("pointermove",this.handleMove.bind(this),{passive:!0}),window.addEventListener("pointerdown",this.handleDown.bind(this),{passive:!0}),window.addEventListener("pointerup",this.handleUp.bind(this)),document.addEventListener("mouseover",this.handleMouseOver.bind(this)),document.addEventListener("mouseout",this.handleMouseOut.bind(this)),document.addEventListener("mouseleave",this.handleWindowLeave.bind(this))}destroy(){this.mediaQueryList&&this.mediaQueryHandler&&this.mediaQueryList.removeEventListener("change",this.mediaQueryHandler),this.motionQuery&&(this.motionQuery.onchange=null),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,i){return m(o,t,1-Math.exp(-e*i))}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.1.0";version="2.1.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,i)=>(e.priority||0)-(i.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(i){console.error(`[Supermouse] Plugin '${t.name}' crashed and has been disabled.`,i),t.isEnabled=!1;try{t.onDisable?.(this)}catch{}}}tick=t=>{const e=t-this.lastTime,i=Math.min(e/1e3,.1);this.lastTime=t,this.state.hoverTarget&&!this.state.hoverTarget.isConnected&&this.input.clearHover();const n=this.input.isEnabled&&!this.state.isNative&&this.state.hasReceivedInput;if(this.stage.setVisibility(n),this.input.isEnabled&&this.options.hideCursor){let s="auto";this.state.forcedCursor!==null?s=this.state.forcedCursor:s=this.state.isNative||!this.state.hasReceivedInput?"auto":"none",this.stage.setNativeCursor(s)}if(this.input.isEnabled){this.state.target.x=this.state.pointer.x,this.state.target.y=this.state.pointer.y;for(let h=0;h<this.plugins.length;h++)this.runPluginSafe(this.plugins[h],e);const s=this.state.reducedMotion?1e3:1/this.options.smoothness*2;this.state.smooth.x=c(this.state.smooth.x,this.state.target.x,s,i),this.state.smooth.y=c(this.state.smooth.y,this.state.target.y,s,i);const r=this.state.target.x-this.state.smooth.x,a=this.state.target.y-this.state.smooth.y;this.state.velocity.x=r,this.state.velocity.y=a,(Math.abs(r)>.1||Math.abs(a)>.1)&&(this.state.angle=g(r,a))}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 s=0;s<this.plugins.length;s++)this.runPluginSafe(this.plugins[s],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=[]}}l.DEFAULT_HOVER_SELECTORS=p,l.Supermouse=y,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})}));
5
+ `}destroy(){this.element.remove(),this.styleTag.remove(),this.container.style.cursor="",this.container.classList.remove(this.scopeClass)}}const c={x:-100,y:-100},v=["a","button","input","textarea","[data-hover]","[data-cursor]"];class y{static version="2.2.0";version="2.2.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(v),this.stage=new g(this.options.container,!!this.options.hideCursor),this.hoverSelectors.forEach(e=>this.stage.addSelector(e)),this.input=new f(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,i)=>(e.priority||0)-(i.priority||0)),t.install?.(this),this)}resetCoords(){this.state.pointer={...c},this.state.target={...c},this.state.smooth={...c},this.state.velocity={x:0,y:0},this.state.angle=0}resetPosition(){this.resetCoords(),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(i){console.error(`[Supermouse] Plugin '${t.name}' crashed and has been disabled.`,i),t.isEnabled=!1;try{t.onDisable?.(this)}catch(o){console.error(`[Supermouse] Failed to execute onDisable for plugin '${t.name}'.`,o)}}}tick=t=>{const e=t-this.lastTime,i=Math.min(e/1e3,.1);this.lastTime=t,this.state.hoverTarget&&!this.state.hoverTarget.isConnected&&this.input.clearHover();const o=this.input.isEnabled&&!this.state.isNative&&this.state.hasReceivedInput;if(this.stage.setVisibility(o),this.input.isEnabled&&this.options.hideCursor){let s="auto";this.state.forcedCursor!==null?s=this.state.forcedCursor:s=this.state.isNative||!this.state.hasReceivedInput?"auto":"none",this.stage.setNativeCursor(s)}this.input.isEnabled?(this.state.target.x=this.state.pointer.x,this.state.target.y=this.state.pointer.y):this.resetCoords();for(let s=0;s<this.plugins.length;s++)this.runPluginSafe(this.plugins[s],e);if(this.input.isEnabled){const s=this.state.reducedMotion?1e3:1/this.options.smoothness*2;this.state.smooth.x=p(this.state.smooth.x,this.state.target.x,s,i),this.state.smooth.y=p(this.state.smooth.y,this.state.target.y,s,i);const h=this.state.target.x-this.state.smooth.x,r=this.state.target.y-this.state.smooth.y;this.state.velocity.x=h,this.state.velocity.y=r,(Math.abs(h)>.1||Math.abs(r)>.1)&&(this.state.angle=m(h,r))}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=[]}}n.DEFAULT_HOVER_SELECTORS=v,n.Input=f,n.Stage=g,n.Supermouse=y,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supermousejs/core",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "The core physics engine and state manager for Supermouse.",
5
5
  "main": "dist/index.umd.js",
6
6
  "module": "dist/index.mjs",