@supermousejs/core 2.5.0-beta.2 → 2.5.0-beta.4

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/dist/index.mjs CHANGED
@@ -1,62 +1,76 @@
1
- const x = {
2
- rules: [
3
- { selector: "input", native: !0, hide: !0 },
4
- { selector: "textarea", native: !0, hide: !0 },
5
- { selector: "select", native: !0, hide: !0 },
6
- { selector: "[contenteditable]", native: !0, hide: !0 },
7
- { selector: "a", native: !1, hide: !0 },
8
- { selector: "button", native: !1, hide: !0 },
9
- { selector: '[role="button"]', native: !1, hide: !0 },
10
- { selector: "[tabindex]", native: !1, hide: !0 }
1
+ const S = {
2
+ native: ["input", "textarea", "select", "[contenteditable]"],
3
+ hide: [
4
+ "input",
5
+ "textarea",
6
+ "select",
7
+ "[contenteditable]",
8
+ "a",
9
+ "button",
10
+ '[role="button"]',
11
+ "[tabindex]",
12
+ "label"
11
13
  ]
12
14
  };
13
- function _(i) {
14
- if (!i) return x;
15
- if ("rules" in i) return i;
16
- const t = [], e = new Set(i.native ?? []), s = new Set(i.hide ?? []), n = /* @__PURE__ */ new Set([...e, ...s]);
17
- for (const o of n)
18
- t.push({
19
- selector: o,
20
- native: e.has(o),
21
- hide: s.has(o)
22
- });
23
- return { rules: t };
24
- }
25
- function A(i) {
26
- const t = [], e = [];
27
- for (const s of i.rules)
28
- s.native !== !1 && t.push(s.selector), s.hide !== !1 && e.push(s.selector);
29
- return { native: t, hide: e };
15
+ function b(n) {
16
+ return n ? {
17
+ native: n.native ?? [],
18
+ hide: n.hide ?? []
19
+ } : S;
30
20
  }
31
- let D = 0;
32
- class O {
21
+ let y = 0;
22
+ class C {
23
+ element;
24
+ scopeClass;
25
+ hideClass;
26
+ container;
27
+ currentCursorState = null;
28
+ originalContainerPosition = "";
29
+ originalContainerCursor = "";
30
+ _visible = !0;
33
31
  constructor(t, e) {
34
- if (this.container = t, !t || !(t instanceof HTMLElement))
35
- throw new Error(`[Supermouse] Invalid container: ${t}. Must be an HTMLElement.`);
36
- t.isConnected;
37
- const s = D++;
38
- this.scopeClass = `supermouse-scope-${s}`, this.hideClass = `supermouse-hide-${s}`;
39
- const n = t === document.body;
40
- if (this.element = document.createElement("div"), Object.assign(this.element.style, {
41
- position: n ? "fixed" : "absolute",
32
+ if (!t || !(t instanceof HTMLElement))
33
+ throw new Error(
34
+ `[Supermouse] Invalid container: ${t}. Must be an HTMLElement.`
35
+ );
36
+ const s = t.hasAttribute("data-supermouse-placeholder");
37
+ !t.isConnected && !s && console.warn(
38
+ "[Supermouse] container is not attached to the document — stage sizing/positioning will be wrong until it is."
39
+ );
40
+ const i = y++;
41
+ this.scopeClass = `supermouse-scope-${i}`, this.hideClass = `supermouse-hide-${i}`, this.element = document.createElement("div"), Object.assign(this.element.style, {
42
+ position: "absolute",
42
43
  inset: "0px",
43
44
  pointerEvents: "none",
44
45
  zIndex: String(e),
45
46
  opacity: "1",
46
47
  transition: "opacity 0.15s ease"
47
- }), !n) {
48
- const o = window.getComputedStyle(t);
49
- this.originalContainerPosition = o.position, o.position === "static" && (t.style.position = "relative");
48
+ }), this.container = t, this._attach(t);
49
+ }
50
+ _attach(t) {
51
+ const e = t === document.body;
52
+ if (this.element.style.position = e ? "fixed" : "absolute", e)
53
+ this.originalContainerPosition = "";
54
+ else {
55
+ const s = window.getComputedStyle(t);
56
+ this.originalContainerPosition = s.position, s.position === "static" && (t.style.position = "relative");
50
57
  }
51
58
  this.originalContainerCursor = t.style.cursor, t.appendChild(this.element), t.classList.add("supermouse-scope", this.scopeClass);
52
59
  }
53
- container;
54
- element;
55
- scopeClass;
56
- hideClass;
57
- currentCursorState = null;
58
- originalContainerPosition = "";
59
- originalContainerCursor = "";
60
+ _detach() {
61
+ const t = this.container;
62
+ t.classList.remove("supermouse-scope", this.scopeClass, this.hideClass), t !== document.body && this.originalContainerPosition === "static" && (t.style.position = ""), t.style.cursor = this.originalContainerCursor, this.element.remove();
63
+ }
64
+ /**
65
+ * Rebinds this stage to a new container. The previous container is
66
+ * restored to its pre-Supermouse state, and the current cursor
67
+ * suppression is re-applied to the new container.
68
+ */
69
+ attach(t) {
70
+ if (this.container === t) return;
71
+ const e = this.currentCursorState;
72
+ this._detach(), this.container = t, this._attach(t), this.currentCursorState = null, e && this.setNativeCursor(e);
73
+ }
60
74
  get containerElement() {
61
75
  return this.container;
62
76
  }
@@ -69,23 +83,31 @@ class O {
69
83
  return `:not(.${this.scopeClass} .supermouse-scope):not(.${this.scopeClass} .supermouse-scope *)`;
70
84
  }
71
85
  setVisibility(t) {
72
- this.element.style.opacity = t ? "1" : "0";
86
+ t !== this._visible && (this._visible = t, this.element.style.opacity = t ? "1" : "0");
73
87
  }
74
88
  setNativeCursor(t) {
75
- t !== this.currentCursorState && (this.currentCursorState = t, this.container.classList.toggle(this.hideClass, t === "none"), t === "none" ? this.container.style.cursor = "none" : this.container === document.body ? this.container.style.cursor = this.originalContainerCursor : this.container.style.cursor = this.originalContainerCursor || "auto");
89
+ t !== this.currentCursorState && (this.currentCursorState = t, this.container.classList.toggle(this.hideClass, t === "none"));
76
90
  }
77
91
  destroy() {
78
- this.element.remove(), this.container.style.cursor = this.originalContainerCursor, this.container.classList.remove("supermouse-scope", this.scopeClass, this.hideClass), this.container !== document.body && this.originalContainerPosition === "static" && (this.container.style.position = "");
92
+ this._detach();
79
93
  }
80
94
  }
81
- class L {
95
+ class P {
82
96
  constructor(t, e) {
83
97
  this.config = t, this.name = t.name, this.cursorMode = t.cursor ?? e.cursor, this.hoverSelectors = new Set(t.hoverSelectors ?? e.hoverSelectors), this.inheritDataAttributes = t.inheritDataAttributes ?? e.inheritDataAttributes, this.ruleEntries = t.rules ? Object.entries(t.rules) : e.ruleEntries;
84
- const s = t.cursorPolicy ? _(t.cursorPolicy) : e.cursorPolicy, n = A(s);
85
- this.nativeSelectors = n.native, this.hideSelectors = n.hide, this.stage = new O(t.container, t.zIndex ?? e.zIndex);
98
+ const s = t.cursorPolicy ? b(t.cursorPolicy) : e.cursorPolicy;
99
+ this.nativeSelectors = s.native, this.hideSelectors = s.hide;
100
+ let i;
101
+ typeof t.container == "string" ? (this.containerSelector = t.container, this._bound = !1, i = document.createElement("div"), i.setAttribute("data-supermouse-placeholder", "")) : (this.containerSelector = null, this._bound = !0, i = t.container), this.stage = new C(i, t.zIndex ?? e.zIndex);
86
102
  }
87
103
  config;
88
104
  stage;
105
+ /**
106
+ * The CSS selector used for lazy resolution, or null for eager scopes.
107
+ * Derived from `config.container` at construction: a string means lazy,
108
+ * an element means eager.
109
+ */
110
+ containerSelector;
89
111
  hoverSelectors;
90
112
  plugins = [];
91
113
  nativeSelectors;
@@ -94,13 +116,42 @@ class L {
94
116
  ruleEntries;
95
117
  name;
96
118
  cursorMode;
97
- disabled = !1;
98
- contains(t) {
99
- return this.stage.containerElement.contains(t);
100
- }
119
+ active = !0;
120
+ _bound;
101
121
  get container() {
102
122
  return this.stage.containerElement;
103
123
  }
124
+ /**
125
+ * True for eager scopes, and for selector scopes that have matched a
126
+ * live element at least once.
127
+ */
128
+ get resolved() {
129
+ return this._bound;
130
+ }
131
+ /**
132
+ * True if this scope owns the given element. Element equality for eager
133
+ * scopes; `Element.matches` for selector scopes. Invalid selectors are
134
+ * treated as non-matching; validation happens once at scope creation.
135
+ */
136
+ match(t) {
137
+ if (this.containerSelector === null)
138
+ return this.stage.containerElement === t;
139
+ try {
140
+ return t.matches(this.containerSelector);
141
+ } catch {
142
+ return !1;
143
+ }
144
+ }
145
+ /**
146
+ * Rebinds this scope's stage to a matched element. No-op for eager
147
+ * scopes, and no-op if the stage is already attached to `el`.
148
+ */
149
+ bind(t) {
150
+ this.containerSelector !== null && (this._bound && this.stage.containerElement === t || (this.stage.attach(t), this._bound = !0));
151
+ }
152
+ contains(t) {
153
+ return this._bound && this.stage.containerElement.contains(t);
154
+ }
104
155
  get hoverSelectorString() {
105
156
  return Array.from(this.hoverSelectors).join(", ");
106
157
  }
@@ -108,20 +159,20 @@ class L {
108
159
  return this.nativeSelectors.join(", ");
109
160
  }
110
161
  buildRules() {
111
- const t = this.stage.getRulePrefix(), e = this.stage.getExclusion(), s = [
112
- `${t}${e} { cursor: none !important; }`,
113
- `${t} *${e} { cursor: none !important; }`
162
+ const t = this.stage.getRulePrefix(), e = this.stage.getExclusion(), s = ":not([data-sm-probe])", i = [
163
+ `${t}${e}${s} { cursor: none !important; }`,
164
+ `${t} *${e}${s} { cursor: none !important; }`
114
165
  ];
115
- for (const n of this.hideSelectors)
116
- s.push(`${t} ${n}${e} { cursor: none !important; }`);
117
- return s.push(`${t} label${e} { cursor: none !important; }`), s.push(`${t} select${e} { cursor: none !important; }`), s.push(
166
+ for (const h of this.hideSelectors)
167
+ i.push(`${t} ${h}${e}${s} { cursor: none !important; }`);
168
+ return i.push(
118
169
  `${t} input[type="range"]${e}::-webkit-slider-thumb { cursor: none !important; }`
119
- ), s.push(
170
+ ), i.push(
120
171
  `${t} input[type="range"]${e}::-moz-range-thumb { cursor: none !important; }`
121
- ), s;
172
+ ), i;
122
173
  }
123
174
  }
124
- const f = { x: -100, y: -100 }, I = /* @__PURE__ */ new Set([
175
+ const d = { x: -100, y: -100 }, E = /* @__PURE__ */ new Set([
125
176
  "default",
126
177
  "auto",
127
178
  "pointer",
@@ -129,60 +180,24 @@ const f = { x: -100, y: -100 }, I = /* @__PURE__ */ new Set([
129
180
  "inherit",
130
181
  "grab",
131
182
  "grabbing"
132
- ]), R = [
183
+ ]), _ = [
133
184
  "a",
134
185
  "button",
135
186
  "input",
136
187
  "textarea",
137
188
  "[data-hover]",
138
189
  "[data-cursor]"
139
- ], u = /* @__PURE__ */ new Map(), M = /* @__PURE__ */ new Map();
140
- let v = null, g = !1, m = !1, C = 0;
141
- function E(i) {
142
- const t = i.getBoundingClientRect();
143
- return { left: t.left, top: t.top, width: t.width, height: t.height };
144
- }
145
- function T(i) {
146
- u.set(i, E(i));
147
- const t = M.get(i);
148
- if (t) for (const e of t) e();
149
- }
150
- function b() {
151
- for (const i of u.keys()) T(i);
152
- }
153
- function $() {
154
- v || typeof ResizeObserver > "u" || (v = new ResizeObserver((i) => {
155
- for (const t of i) {
156
- const e = t.target;
157
- u.has(e) && T(e);
158
- }
159
- }));
160
- }
161
- function B() {
162
- typeof window > "u" || (g || (window.addEventListener("scroll", b, { passive: !0, capture: !0 }), g = !0), m || (window.addEventListener("resize", b, { passive: !0 }), m = !0));
163
- }
164
- function H(i, t) {
165
- return C++, u.has(i) || (u.set(i, E(i)), $(), v?.observe(i), B()), () => {
166
- C--, C === 0 && (v?.disconnect(), v = null, u.clear(), M.clear(), g && (window.removeEventListener("scroll", b, { capture: !0 }), g = !1), m && (window.removeEventListener("resize", b), m = !1));
167
- };
168
- }
169
- function N(i) {
170
- let t = u.get(i);
171
- return t || (t = E(i), u.set(i, t)), t;
172
- }
173
- function z(i, t, e) {
174
- if (i === document.body) return { x: t, y: e };
175
- const s = N(i);
176
- return { x: t - s.left, y: e - s.top };
177
- }
178
- class k {
179
- constructor(t, e, s, n) {
180
- this.state = t, this.options = e, this.onEnableChange = s, this.onActiveScopeChange = n, this.dataPrefix = e.dataPrefix ?? "supermouse", this.normalizedDataPrefix = this.dataPrefix.toLowerCase(), this.ignoreAttribute = `data-${this.dataPrefix}-ignore`, this.checkDeviceCapability(), this.checkMotionPreference(), this.bindEvents();
190
+ ];
191
+ class w {
192
+ constructor(t, e, s, i, h, r) {
193
+ this.state = t, this.options = e, this.onEnableChange = s, this.onActiveScopeChange = i, this.resolveScope = h, this.onHoverSettled = r, this.dataPrefix = e.dataPrefix ?? "supermouse", this.normalizedDataPrefix = this.dataPrefix.toLowerCase(), this.ignoreAttribute = `data-${this.dataPrefix}-ignore`, this.checkDeviceCapability(), this.checkMotionPreference(), this.bindEvents();
181
194
  }
182
195
  state;
183
196
  options;
184
197
  onEnableChange;
185
198
  onActiveScopeChange;
199
+ resolveScope;
200
+ onHoverSettled;
186
201
  abortController = new AbortController();
187
202
  mediaQueryList;
188
203
  motionQuery;
@@ -190,36 +205,26 @@ class k {
190
205
  normalizedDataPrefix;
191
206
  ignoreAttribute;
192
207
  activeScope = null;
193
- scopeByContainer = /* @__PURE__ */ new Map();
194
208
  nativeTarget = null;
195
209
  currentTarget = null;
196
210
  lastParsedTarget = null;
197
- releaseViewport = null;
198
211
  hasSeenPointer = !1;
199
212
  isEnabled = !0;
200
213
  viewportX = 0;
201
214
  viewportY = 0;
202
215
  /** Cached matched rules per ancestor. Recomputed only when the hover target changes. */
203
216
  cachedChain = [];
204
- setScopes(t) {
205
- this.scopeByContainer.clear();
206
- for (const e of t) this.scopeByContainer.set(e.container, e);
207
- }
208
217
  setActiveScope(t) {
209
- t !== this.activeScope && (this.activeScope = t, this.lastParsedTarget = null, this.cachedChain = [], this.releaseViewport?.(), this.releaseViewport = t && t.container !== document.body ? H(t.container) : null, this.hasSeenPointer && (this.applyPointerToState(), this.state.target.x = this.state.smooth.x = this.state.pointer.x, this.state.target.y = this.state.smooth.y = this.state.pointer.y), this.onActiveScopeChange(t));
210
- }
211
- findScope(t) {
212
- let e = t;
213
- for (; e; ) {
214
- const s = this.scopeByContainer.get(e);
215
- if (s && !s.disabled) return s;
216
- e = e.parentElement;
217
- }
218
- return null;
218
+ t !== this.activeScope && (this.activeScope = t, this.lastParsedTarget = null, this.cachedChain = [], this.hasSeenPointer && (this.applyPointerToState(), this.state.target.x = this.state.smooth.x = this.state.pointer.x, this.state.target.y = this.state.smooth.y = this.state.pointer.y), this.onActiveScopeChange(t));
219
219
  }
220
220
  applyPointerToState() {
221
- const t = this.activeScope?.container ?? document.body, e = z(t, this.viewportX, this.viewportY);
222
- this.state.pointer.x = e.x, this.state.pointer.y = e.y;
221
+ const t = this.activeScope?.container ?? document.body;
222
+ if (t === document.body) {
223
+ this.state.pointer.x = this.viewportX, this.state.pointer.y = this.viewportY;
224
+ return;
225
+ }
226
+ const e = t.getBoundingClientRect();
227
+ this.state.pointer.x = this.viewportX - e.left, this.state.pointer.y = this.viewportY - e.top;
223
228
  }
224
229
  checkDeviceCapability() {
225
230
  this.options.autoDisableOnMobile && (this.mediaQueryList = window.matchMedia("(pointer: fine)"), this.updateEnabledState(this.mediaQueryList.matches), this.mediaQueryList.addEventListener("change", (t) => this.updateEnabledState(t.matches), {
@@ -240,42 +245,43 @@ class k {
240
245
  }
241
246
  parseDOMInteraction(t) {
242
247
  if (!this.activeScope) return;
243
- const e = this.activeScope.container, s = this.activeScope.inheritDataAttributes, n = this.normalizedDataPrefix, o = this.activeScope.ruleEntries;
248
+ const e = this.activeScope.container, s = this.activeScope.inheritDataAttributes, i = this.normalizedDataPrefix, h = this.activeScope.ruleEntries;
244
249
  if (t !== this.lastParsedTarget) {
245
250
  this.lastParsedTarget = t, this.cachedChain = [];
246
- let r = t;
247
- for (; r; ) {
251
+ let o = t;
252
+ for (; o; ) {
248
253
  const p = [];
249
- for (const [a, l] of o)
250
- this.matchesSelector(r, a) && p.push({ selector: a, rules: l });
251
- if (this.cachedChain.push({ element: r, matchedRules: p }), !s || r === e) break;
252
- const c = r.parentElement;
254
+ for (const [a, l] of h)
255
+ this.matchesSelector(o, a) && p.push({ selector: a, rules: l });
256
+ if (this.cachedChain.push({ element: o, matchedRules: p }), !s || o === e) break;
257
+ const c = o.parentElement;
253
258
  if (!c || !e.contains(c)) break;
254
- r = c;
259
+ o = c;
255
260
  }
256
261
  }
257
- const h = {};
258
- for (const { element: r, matchedRules: p } of this.cachedChain) {
262
+ const r = {};
263
+ for (const { element: o, matchedRules: p } of this.cachedChain) {
259
264
  const c = {};
260
265
  for (const { rules: a } of p)
261
266
  try {
262
- const l = typeof a == "function" ? a(r) : a;
267
+ const l = typeof a == "function" ? a(o) : a;
263
268
  if (!l || typeof l != "object") continue;
264
- for (const [S, d] of Object.entries(l))
265
- c[S] = typeof d == "function" ? d(r) : d;
266
- } catch {
269
+ for (const [v, u] of Object.entries(l))
270
+ c[v] = typeof u == "function" ? u(o) : u;
271
+ } catch (l) {
272
+ console.error("[Supermouse] Rule threw during evaluation:", l);
267
273
  }
268
- for (const a in r.dataset) {
269
- if (!a.toLowerCase().startsWith(n)) continue;
270
- const l = a.slice(n.length);
274
+ for (const a in o.dataset) {
275
+ if (!a.toLowerCase().startsWith(i)) continue;
276
+ const l = a.slice(i.length);
271
277
  if (!l) continue;
272
- const S = l[0].toLowerCase() + l.slice(1), d = r.dataset[a];
273
- c[S] = d == null || d === "" ? !0 : d;
278
+ const v = l[0].toLowerCase() + l.slice(1), u = o.dataset[a];
279
+ c[v] = u == null || u === "" ? !0 : u;
274
280
  }
275
281
  for (const [a, l] of Object.entries(c))
276
- a in h || (h[a] = l);
282
+ a in r || (r[a] = l);
277
283
  }
278
- this.state.interaction = h;
284
+ this.state.interaction = r;
279
285
  }
280
286
  matchesSelector(t, e) {
281
287
  try {
@@ -284,8 +290,17 @@ class k {
284
290
  return !1;
285
291
  }
286
292
  }
287
- resolveComputedCursor(t) {
288
- return window.getComputedStyle(t).cursor;
293
+ /**
294
+ * Reads the element's authored cursor value without our own suppression
295
+ * interfering.
296
+ */
297
+ resolveAuthoredCursor(t) {
298
+ t.setAttribute("data-sm-probe", "");
299
+ try {
300
+ return window.getComputedStyle(t).cursor;
301
+ } finally {
302
+ t.removeAttribute("data-sm-probe");
303
+ }
289
304
  }
290
305
  handleMove = (t) => {
291
306
  this.options.autoDisableOnMobile && t.pointerType === "touch" && !this.options.enableTouch || (this.viewportX = t.clientX, this.viewportY = t.clientY, this.hasSeenPointer = !0, this.applyPointerToState(), this.isEnabled && (this.state.hasReceivedInput || (this.state.hasReceivedInput = !0, this.state.target.x = this.state.smooth.x = this.state.pointer.x, this.state.target.y = this.state.smooth.y = this.state.pointer.y)));
@@ -298,29 +313,38 @@ class k {
298
313
  };
299
314
  handleMouseOver = (t) => {
300
315
  if (!this.isEnabled) return;
301
- const e = t.target, s = this.findScope(e);
302
- if (s && s !== this.activeScope && this.setActiveScope(s), !this.activeScope) return;
303
- if (this.state.cursorMode === "auto" && e.closest(`[${this.ignoreAttribute}]`)) {
304
- this.clearHover(), this.state.isNative = !0, this.nativeTarget = e;
316
+ const e = t.target, s = this.resolveScope(e);
317
+ s && s !== this.activeScope && this.setActiveScope(s), this.activeScope && (this.settleHoverState(e), this.onHoverSettled());
318
+ };
319
+ isPointerInside(t) {
320
+ if (!this.hasSeenPointer) return !1;
321
+ const e = t.getBoundingClientRect();
322
+ return this.viewportX >= e.left && this.viewportX <= e.right && this.viewportY >= e.top && this.viewportY <= e.bottom;
323
+ }
324
+ settleHoverState(t) {
325
+ if (this.state.cursorMode === "auto" && t.closest(`[${this.ignoreAttribute}]`)) {
326
+ this.clearHover(), this.state.isNative = !0, this.nativeTarget = t;
305
327
  return;
306
328
  }
307
- this.state.isNative = !1, this.nativeTarget = null, this.currentTarget = e, this.parseDOMInteraction(e);
308
- const n = e.closest(this.activeScope.hoverSelectorString);
309
- if (n && (this.state.isHover = !0, this.state.hoverTarget = n), this.state.cursorMode === "auto") {
310
- if (this.matchesSelector(e, this.activeScope.nativeSelectorString)) {
311
- this.state.isNative = !0, this.nativeTarget = e;
329
+ this.state.isNative = !1, this.nativeTarget = null, this.currentTarget = t, this.state.pointerTarget = t;
330
+ const e = this.resolveAuthoredCursor(t);
331
+ this.state.authoredCursor = e, this.parseDOMInteraction(t);
332
+ const s = t.closest(this.activeScope.hoverSelectorString);
333
+ if (s && (this.state.isHover = !0, this.state.hoverTarget = s), this.state.cursorMode === "auto") {
334
+ if (this.matchesSelector(t, this.activeScope.nativeSelectorString)) {
335
+ this.state.isNative = !0, this.nativeTarget = t;
312
336
  return;
313
337
  }
314
- (e.isContentEditable || !I.has(this.resolveComputedCursor(e))) && (this.state.isNative = !0, this.nativeTarget = e);
338
+ (t.isContentEditable || !E.has(e)) && (this.state.isNative = !0, this.nativeTarget = t);
315
339
  }
316
- };
340
+ }
317
341
  handleMouseOut = (t) => {
318
342
  if (!this.isEnabled) return;
319
343
  const e = t.target, s = t.relatedTarget;
320
- (e === this.state.hoverTarget || e.contains(this.state.hoverTarget)) && (!s || !this.state.hoverTarget?.contains(s)) && (this.state.isHover = !1, this.state.hoverTarget = null), this.nativeTarget && (e === this.nativeTarget || e.contains(this.nativeTarget)) && (!s || !this.nativeTarget.contains(s)) && (this.state.isNative = !1, this.nativeTarget = null), e === this.currentTarget && (this.currentTarget = null, this.lastParsedTarget = null, this.cachedChain = []), !s && this.options.hideOnLeave && (this.state.hasReceivedInput = !1, this.state.pointer = { ...f });
344
+ (e === this.state.hoverTarget || e.contains(this.state.hoverTarget)) && (!s || !this.state.hoverTarget?.contains(s)) && (this.state.isHover = !1, this.state.hoverTarget = null), this.nativeTarget && (e === this.nativeTarget || e.contains(this.nativeTarget)) && (!s || !this.nativeTarget.contains(s)) && (this.state.isNative = !1, this.nativeTarget = null), e === this.currentTarget && (this.currentTarget = null, this.state.pointerTarget = null, this.state.authoredCursor = null, this.lastParsedTarget = null, this.cachedChain = []), !s && this.options.hideOnLeave && (this.state.hasReceivedInput = !1, this.state.pointer = { ...d });
321
345
  };
322
346
  clearHover() {
323
- this.state.isHover = !1, this.state.hoverTarget = null, this.state.isNative = !1, this.nativeTarget = null, this.state.interaction = {}, this.currentTarget = null, this.lastParsedTarget = null, this.cachedChain = [];
347
+ this.state.isHover = !1, this.state.hoverTarget = null, this.state.isNative = !1, this.nativeTarget = null, this.state.interaction = {}, this.currentTarget = null, this.state.pointerTarget = null, this.state.authoredCursor = null, this.lastParsedTarget = null, this.cachedChain = [];
324
348
  }
325
349
  getCurrentTarget() {
326
350
  return this.currentTarget;
@@ -330,38 +354,37 @@ class k {
330
354
  window.addEventListener("pointermove", this.handleMove, { passive: !0, signal: t }), window.addEventListener("pointerdown", this.handleDown, { passive: !0, signal: t }), window.addEventListener("pointerup", this.handleUp, { signal: t }), document.addEventListener("mouseover", this.handleMouseOver, { signal: t }), document.addEventListener("mouseout", this.handleMouseOut, { signal: t });
331
355
  }
332
356
  destroy() {
333
- this.abortController.abort(), this.releaseViewport?.(), this.cachedChain = [];
357
+ this.abortController.abort(), this.cachedChain = [];
334
358
  }
335
359
  }
336
- let V = 0;
337
- const y = /* @__PURE__ */ new Map();
338
- function F() {
339
- return V++;
360
+ let x = 0;
361
+ const f = /* @__PURE__ */ new Map();
362
+ function T() {
363
+ return x++;
340
364
  }
341
- function j(i, t) {
342
- let e = y.get(i);
343
- e || (e = document.createElement("style"), e.id = `supermouse-styles-${i}`, document.head.appendChild(e), y.set(i, e)), e.textContent = t.join(`
365
+ function M(n, t) {
366
+ let e = f.get(n);
367
+ e || (e = document.createElement("style"), e.id = `supermouse-styles-${n}`, document.head.appendChild(e), f.set(n, e)), e.textContent = t.join(`
344
368
  `);
345
369
  }
346
- function Q(i) {
347
- y.get(i)?.remove(), y.delete(i);
370
+ function A(n) {
371
+ f.get(n)?.remove(), f.delete(n);
348
372
  }
349
- const P = "2.5.0-beta.2";
350
- function U(i, t, e) {
351
- return i + (t - i) * e;
373
+ const g = "2.5.0-beta.4";
374
+ function D(n, t, e) {
375
+ return n + (t - n) * e;
352
376
  }
353
- function w(i, t, e, s) {
354
- return U(i, t, 1 - Math.exp(-e * s));
377
+ function m(n, t, e, s) {
378
+ return D(n, t, 1 - Math.exp(-e * s));
355
379
  }
356
- class Y {
357
- static version = P;
358
- version = P;
380
+ class I {
381
+ static version = g;
382
+ version = g;
359
383
  state;
360
384
  options;
361
385
  _scopes = [];
362
386
  _activeScope = null;
363
387
  _installingScope = null;
364
- scopeByContainer = /* @__PURE__ */ new Map();
365
388
  scopeByName = /* @__PURE__ */ new Map();
366
389
  scopeHandles = /* @__PURE__ */ new Map();
367
390
  input;
@@ -383,10 +406,10 @@ class Y {
383
406
  zIndex: 9999,
384
407
  inheritDataAttributes: !0,
385
408
  ...t
386
- }, this.styleOwner = F(), this.state = {
387
- pointer: { ...f },
388
- target: { ...f },
389
- smooth: { ...f },
409
+ }, this.styleOwner = T(), this.state = {
410
+ pointer: { ...d },
411
+ target: { ...d },
412
+ smooth: { ...d },
390
413
  velocity: { x: 0, y: 0 },
391
414
  displacement: { x: 0, y: 0 },
392
415
  angle: 0,
@@ -394,7 +417,9 @@ class Y {
394
417
  isHover: !1,
395
418
  isNative: !1,
396
419
  cursorMode: this.options.cursor,
420
+ pointerTarget: null,
397
421
  hoverTarget: null,
422
+ authoredCursor: null,
398
423
  reducedMotion: !1,
399
424
  hasReceivedInput: !1,
400
425
  shape: null,
@@ -410,14 +435,16 @@ class Y {
410
435
  rules: this.options.rules,
411
436
  zIndex: this.options.zIndex
412
437
  });
413
- if (this.input = new k(
438
+ if (this.input = new w(
414
439
  this.state,
415
440
  this.options,
416
441
  (s) => {
417
442
  s || this.reset();
418
443
  },
419
- (s) => this.handleActiveScopeChange(s)
420
- ), this.input.setScopes(this._scopes), this.input.setActiveScope(e), this.installPlugins(e), this.options.scopes)
444
+ (s) => this.handleActiveScopeChange(s),
445
+ (s) => this.resolveScopeForNode(s),
446
+ () => this.applyCursorNow()
447
+ ), this.input.setActiveScope(e), this.installPlugins(e), this.options.scopes)
421
448
  for (const s of this.options.scopes) this.addScope(s);
422
449
  this.rebuildStylesheet(), this.bindVisibilityHandling(), this.options.autoStart && this.startLoop();
423
450
  }
@@ -434,12 +461,23 @@ class Y {
434
461
  get isRunning() {
435
462
  return this._running;
436
463
  }
464
+ /**
465
+ * Installs a plugin into the primary scope.
466
+ *
467
+ * In multi-scope mode, prefer `handle.use(plugin)` to target a specific
468
+ * scope. This method always installs to the primary scope, regardless of
469
+ * which scope is currently active.
470
+ */
437
471
  use(t) {
438
472
  return this.installPlugin(this._scopes[0], t), this;
439
473
  }
474
+ /**
475
+ * Searches every scope and returns the first plugin matching `name`.
476
+ * Scopes are searched in registration order (primary first).
477
+ */
440
478
  getPlugin(t) {
441
479
  for (const e of this._scopes) {
442
- const s = e.plugins.find((n) => n.name === t);
480
+ const s = e.plugins.find((i) => i.name === t);
443
481
  if (s) return s;
444
482
  }
445
483
  }
@@ -447,27 +485,48 @@ class Y {
447
485
  const e = this.scopeByName.get(t);
448
486
  return e ? this.scopeHandles.get(e) : void 0;
449
487
  }
488
+ /**
489
+ * Enables a plugin by name, wherever it lives.
490
+ *
491
+ * If the plugin's scope is currently active, the activation lifecycle
492
+ * runs immediately. If the scope is inactive, `isEnabled` is set but
493
+ * hooks do not fire until the scope next activates.
494
+ */
450
495
  enablePlugin(t) {
451
496
  const e = this.getPlugin(t);
452
497
  if (!e || e.isEnabled !== !1) return;
453
498
  e.isEnabled = !0;
454
- const s = this._activeScope;
455
- s && !s.disabled && s.plugins.includes(e) && this.scopeActivatePlugin(e);
499
+ const s = this.findScopeForPlugin(e);
500
+ s && s === this._activeScope && s.active && this.scopeActivatePlugin(e);
456
501
  }
502
+ /**
503
+ * Disables a plugin by name, wherever it lives.
504
+ *
505
+ * If the plugin's scope is currently active, the deactivation lifecycle
506
+ * runs immediately. If the scope is inactive, `isEnabled` is set but
507
+ * hooks do not fire — they already ran when the scope went inactive.
508
+ */
457
509
  disablePlugin(t) {
458
510
  const e = this.getPlugin(t);
459
- e && e.isEnabled !== !1 && this.deactivatePlugin(e);
511
+ if (!e || e.isEnabled === !1) return;
512
+ const s = this.findScopeForPlugin(e);
513
+ s !== null && s === this._activeScope && s.active ? this.deactivatePlugin(e) : e.isEnabled = !1;
460
514
  }
461
515
  togglePlugin(t) {
462
516
  const e = this.getPlugin(t);
463
517
  e && (e.isEnabled === !1 ? this.enablePlugin(t) : this.disablePlugin(t));
464
518
  }
519
+ /**
520
+ * Sets the cursor mode on the *active* scope.
521
+ *
522
+ * To set the mode on a specific scope, use `handle.setCursor(mode)`.
523
+ */
465
524
  setCursor(t) {
466
- this._activeScope && (this._activeScope.cursorMode = t, this.state.cursorMode = t);
525
+ this._activeScope && this.setScopeCursor(this._activeScope, t);
467
526
  }
468
527
  addScope(t) {
469
528
  const e = this.createScope(t);
470
- return this.input.setScopes(this._scopes), this.installPlugins(e), this.rebuildStylesheet(), this.scopeHandles.get(e);
529
+ return this.installPlugins(e), this.rebuildStylesheet(), this.scopeHandles.get(e);
471
530
  }
472
531
  enable() {
473
532
  this.input.isEnabled = !0, this.input.hasSeenPointer && (this.state.target.x = this.state.smooth.x = this.state.pointer.x, this.state.target.y = this.state.smooth.y = this.state.pointer.y, this.resetMotion(), this.state.hasReceivedInput = !0), this._activeScope && this._activeScope.stage.setNativeCursor(this.resolveCursorState());
@@ -476,7 +535,7 @@ class Y {
476
535
  this.input.isEnabled = !1, this._activeScope && (this._activeScope.stage.setNativeCursor("auto"), this._activeScope.stage.setVisibility(!1)), t?.reset && this.reset();
477
536
  }
478
537
  reset() {
479
- this.state.target = { ...f }, this.state.smooth = { ...f }, this.resetMotion(), this.state.angle = 0, this.state.hasReceivedInput = !1, this.state.shape = null, this.state.interaction = {};
538
+ this.state.target = { ...d }, this.state.smooth = { ...d }, this.resetMotion(), this.state.angle = 0, this.state.hasReceivedInput = !1, this.state.shape = null, this.state.interaction = {};
480
539
  }
481
540
  start() {
482
541
  this.startLoop();
@@ -490,25 +549,35 @@ class Y {
490
549
  for (const e of t.plugins)
491
550
  try {
492
551
  e.destroy?.(this);
493
- } catch {
552
+ } catch (s) {
553
+ console.error(s);
494
554
  }
495
555
  t.stage.destroy();
496
556
  }
497
- this._scopes = [], this.scopeByContainer.clear(), this.scopeByName.clear(), this.scopeHandles.clear(), this._activeScope = null, this.state.scope = null, Q(this.styleOwner);
557
+ this._scopes = [], this.scopeByName.clear(), this.scopeHandles.clear(), this._activeScope = null, this.state.scope = null, A(this.styleOwner);
498
558
  }
499
559
  // ─── Internal ───
500
560
  _running = !1;
501
561
  createScope(t) {
502
- this.scopeByContainer.has(t.container);
503
- const e = new L(t, {
562
+ if (typeof t.container != "string") {
563
+ const s = t.container;
564
+ for (const i of this._scopes)
565
+ if (i.containerSelector === null && i.container === s) {
566
+ console.warn(
567
+ "[Supermouse] A scope is already registered for this container. The previous scope will no longer activate."
568
+ );
569
+ break;
570
+ }
571
+ }
572
+ const e = new P(t, {
504
573
  cursor: this.options.cursor,
505
- hoverSelectors: this.options.hoverSelectors ?? R,
506
- cursorPolicy: this.options.cursorPolicy ? _(this.options.cursorPolicy) : x,
574
+ hoverSelectors: this.options.hoverSelectors ?? _,
575
+ cursorPolicy: this.options.cursorPolicy ? b(this.options.cursorPolicy) : S,
507
576
  zIndex: this.options.zIndex,
508
577
  inheritDataAttributes: this.options.inheritDataAttributes,
509
578
  ruleEntries: this.options.rules ? Object.entries(this.options.rules) : []
510
579
  });
511
- return this._scopes.push(e), this.scopeByContainer.set(e.container, e), e.name && this.scopeByName.set(e.name, e), this.scopeHandles.set(e, this.buildScopeHandle(e)), e;
580
+ return this._scopes.push(e), e.name && this.scopeByName.set(e.name, e), this.scopeHandles.set(e, this.buildScopeHandle(e)), e;
512
581
  }
513
582
  buildScopeHandle(t) {
514
583
  const e = {
@@ -516,55 +585,105 @@ class Y {
516
585
  return t.name;
517
586
  },
518
587
  get container() {
519
- return t.container;
588
+ return t.resolved ? t.container : null;
589
+ },
590
+ get active() {
591
+ return t.active;
520
592
  },
521
- get disabled() {
522
- return t.disabled;
593
+ get resolved() {
594
+ return t.resolved;
523
595
  },
524
- remove: () => this.removeScope(t),
596
+ destroy: () => this.destroyScope(t),
525
597
  setCursor: (s) => this.setScopeCursor(t, s),
526
- disable: () => this.disableScope(t),
527
- enable: () => this.enableScope(t),
598
+ deactivate: () => this.deactivateScope(t),
599
+ activate: () => this.activateScope(t),
528
600
  use: (s) => (this.installPlugin(t, s), e),
529
601
  removePlugin: (s) => this.removePluginFromScope(t, s),
530
- getPlugin: (s) => t.plugins.find((n) => n.name === s)
602
+ getPlugin: (s) => t.plugins.find((i) => i.name === s)
531
603
  };
532
604
  return e;
533
605
  }
534
- removeScope(t) {
606
+ destroyScope(t) {
535
607
  const e = this._scopes.indexOf(t);
536
608
  if (e !== -1) {
537
609
  for (const s of t.plugins)
538
610
  try {
539
611
  s.destroy?.(this);
540
- } catch {
612
+ } catch (i) {
613
+ console.error(i);
541
614
  }
542
- if (t.plugins.length = 0, t.stage.destroy(), this._scopes.splice(e, 1), this.scopeByContainer.delete(t.container), t.name && this.scopeByName.delete(t.name), this.scopeHandles.delete(t), this.input.setScopes(this._scopes), this._activeScope === t) {
543
- const s = this.findScopeAbove(t.container.parentElement) ?? this._scopes.find((n) => !n.disabled) ?? null;
544
- this.input.setActiveScope(s);
615
+ if (t.plugins.length = 0, t.stage.destroy(), this._scopes.splice(e, 1), t.name && this.scopeByName.delete(t.name), this.scopeHandles.delete(t), this._activeScope === t) {
616
+ const s = this.resolveScopeForNode(t.container.parentElement) ?? this._scopes.find((i) => i.active) ?? null;
617
+ this.input.setActiveScope(s), this.input.clearHover(), this.applyCursorNow();
545
618
  }
546
619
  this.rebuildStylesheet();
547
620
  }
548
621
  }
549
622
  setScopeCursor(t, e) {
550
- t.cursorMode = e, t === this._activeScope && (this.state.cursorMode = e);
623
+ t.cursorMode = e, t === this._activeScope && (this.state.cursorMode = e, this.applyCursorNow());
551
624
  }
552
- disableScope(t) {
553
- if (!t.disabled && (t.disabled = !0, this._activeScope === t)) {
554
- const e = this.findScopeAbove(t.container.parentElement) ?? this._scopes.find((s) => !s.disabled) ?? null;
555
- this.input.setActiveScope(e);
625
+ /**
626
+ * Marks the scope ineligible for activation and, if it was active, yields
627
+ * immediately to the nearest active ancestor scope (or nothing).
628
+ */
629
+ deactivateScope(t) {
630
+ if (t.active && (t.active = !1, this._activeScope === t)) {
631
+ const e = this.resolveScopeForNode(t.container.parentElement) ?? this._scopes.find((s) => s.active) ?? null;
632
+ this.input.setActiveScope(e), this.input.clearHover(), this.applyCursorNow();
556
633
  }
557
634
  }
558
- enableScope(t) {
559
- t.disabled = !1;
560
- }
561
- findScopeAbove(t) {
562
- let e = t;
563
- for (; e; ) {
564
- const s = this.scopeByContainer.get(e);
565
- if (s && !s.disabled) return s;
566
- e = e.parentElement;
635
+ /**
636
+ * Marks the scope eligible for activation.
637
+ *
638
+ * If the pointer is already inside the scope's container, the scope
639
+ * becomes active immediately. Otherwise it activates on the next
640
+ * `mouseover` inside the container. Deactivation is always eager.
641
+ */
642
+ activateScope(t) {
643
+ if (t.active = !0, this._activeScope !== t && this.input.hasSeenPointer) {
644
+ if (t.containerSelector !== null && !t.resolved) {
645
+ const e = document.querySelectorAll(t.containerSelector);
646
+ for (const s of e)
647
+ if (this.input.isPointerInside(s)) {
648
+ t.bind(s);
649
+ break;
650
+ }
651
+ }
652
+ t.resolved && this.input.isPointerInside(t.container) && (this.input.setActiveScope(t), this.applyCursorNow());
567
653
  }
654
+ }
655
+ /**
656
+ * Called by `Input` on every `mouseover`, and internally when the active
657
+ * scope is removed or deactivated. Walks from `node` up the ancestor
658
+ * chain, returning the innermost active scope whose `match` succeeds
659
+ * for an ancestor. The matched scope is bound to that ancestor before
660
+ * return.
661
+ *
662
+ * The walk order is what enforces "innermost wins": the first ancestor
663
+ * matching any active scope is, by construction, the closest one to the
664
+ * event target. Detached containers can never be ancestors of a live
665
+ * event target, so no cleanup of stale bindings is required here.
666
+ */
667
+ resolveScopeForNode(t) {
668
+ for (let e = t; e; e = e.parentElement)
669
+ for (const s of this._scopes)
670
+ if (s.active && s.match(e))
671
+ return s.bind(e), s;
672
+ return null;
673
+ }
674
+ /**
675
+ * Synchronously writes the current cursor and stage visibility for the
676
+ * active scope. Called after hover state settles, on cursor mode changes,
677
+ * and on programmatic scope transitions. The `update()` rAF path calls
678
+ * the same writers as a backstop.
679
+ */
680
+ applyCursorNow() {
681
+ const t = this._activeScope;
682
+ t && (t.stage.setVisibility(this.resolveStageVisibility()), this.input.isEnabled && t.stage.setNativeCursor(this.resolveCursorState()));
683
+ }
684
+ findScopeForPlugin(t) {
685
+ for (const e of this._scopes)
686
+ if (e.plugins.includes(t)) return e;
568
687
  return null;
569
688
  }
570
689
  installPlugins(t) {
@@ -572,32 +691,35 @@ class Y {
572
691
  for (const e of t.config.plugins) this.installPlugin(t, e);
573
692
  }
574
693
  installPlugin(t, e) {
575
- if (!t.plugins.some((s) => s.name === e.name)) {
576
- e.isEnabled ??= !0, this._installingScope = t;
577
- try {
578
- e.install?.(this);
579
- } catch {
580
- this._installingScope = null;
581
- return;
582
- }
583
- this._installingScope = null, t.plugins.push(e), t.plugins.sort((s, n) => (s.priority ?? 0) - (n.priority ?? 0)), (t !== this._activeScope || t.disabled) && e.element && (e.element.style.display = "none");
694
+ if (t.plugins.some((s) => s.name === e.name)) {
695
+ console.warn(`[Supermouse] Plugin "${e.name}" already installed.`);
696
+ return;
697
+ }
698
+ e.isEnabled ??= !0, this._installingScope = t;
699
+ try {
700
+ e.install?.(this);
701
+ } catch (s) {
702
+ console.error(`[Supermouse] Failed to install plugin '${e.name}'.`, s), this._installingScope = null;
703
+ return;
584
704
  }
705
+ this._installingScope = null, t.plugins.push(e), t.plugins.sort((s, i) => (s.priority ?? 0) - (i.priority ?? 0)), (t !== this._activeScope || !t.active) && e.element && (e.element.style.display = "none");
585
706
  }
586
707
  removePluginFromScope(t, e) {
587
- const s = t.plugins.findIndex((r) => r.name === e);
708
+ const s = t.plugins.findIndex((o) => o.name === e);
588
709
  if (s === -1) return;
589
- const n = t.plugins[s];
710
+ const i = t.plugins[s];
590
711
  t.plugins.splice(s, 1);
591
- const o = () => {
712
+ const h = () => {
592
713
  try {
593
- n.onDisable?.(this), n.destroy?.(this);
594
- } catch {
714
+ i.onDisable?.(this), i.destroy?.(this);
715
+ } catch (o) {
716
+ console.error(`[Supermouse] Plugin '${e}' cleanup threw:`, o);
595
717
  }
596
- n.element?.remove();
597
- }, h = n.onBeforeDisable?.(this);
598
- h && typeof h.then == "function" ? Promise.resolve(h).then(o).catch((r) => {
599
- o();
600
- }) : o();
718
+ i.element?.remove();
719
+ }, r = i.onBeforeDisable?.(this);
720
+ r && typeof r.then == "function" ? Promise.resolve(r).then(h).catch((o) => {
721
+ console.error(`[Supermouse] Plugin '${e}' onBeforeDisable threw:`, o), h();
722
+ }) : h();
601
723
  }
602
724
  handleActiveScopeChange(t) {
603
725
  const e = this._activeScope;
@@ -619,8 +741,8 @@ class Y {
619
741
  const e = () => {
620
742
  t.element && (t.element.style.display = "none"), t.onDisable?.(this);
621
743
  }, s = t.onBeforeDisable?.(this);
622
- s && typeof s.then == "function" ? Promise.resolve(s).then(e).catch((n) => {
623
- e();
744
+ s && typeof s.then == "function" ? Promise.resolve(s).then(e).catch((i) => {
745
+ console.error(`[Supermouse] Plugin '${t.name}' onBeforeDisable threw:`, i), e();
624
746
  }) : e();
625
747
  }
626
748
  /**
@@ -632,24 +754,24 @@ class Y {
632
754
  const e = () => {
633
755
  t.element && (t.element.style.display = "none"), t.onDisable?.(this);
634
756
  }, s = t.onBeforeDisable?.(this);
635
- s && typeof s.then == "function" ? Promise.resolve(s).then(e).catch((n) => {
636
- e();
757
+ s && typeof s.then == "function" ? Promise.resolve(s).then(e).catch((i) => {
758
+ console.error(`[Supermouse] Plugin '${t.name}' onBeforeDisable threw:`, i), e();
637
759
  }) : e();
638
760
  }
639
761
  scopeActivatePlugin(t) {
640
762
  t.element && (t.element.style.display = ""), t.onEnable?.(this);
641
763
  }
642
764
  rebuildStylesheet() {
643
- const t = [];
765
+ const t = [":where(.supermouse-scope .supermouse-scope) { cursor: auto }"];
644
766
  for (const e of this._scopes) t.push(...e.buildRules());
645
- j(this.styleOwner, t);
767
+ M(this.styleOwner, t);
646
768
  }
647
769
  runPluginSafe(t, e) {
648
770
  if (t.isEnabled !== !1)
649
771
  try {
650
772
  t.update?.(this, e);
651
- } catch {
652
- t.isEnabled = !1, this.crashedPlugins.push(t);
773
+ } catch (s) {
774
+ console.error(`[Supermouse] Plugin '${t.name}' crashed and has been disabled.`, s), t.isEnabled = !1, this.crashedPlugins.push(t);
653
775
  }
654
776
  }
655
777
  cleanupCrashedPlugins() {
@@ -664,7 +786,8 @@ class Y {
664
786
  }
665
787
  try {
666
788
  t.onDisable?.(this), t.destroy?.(this);
667
- } catch {
789
+ } catch (e) {
790
+ console.error(`[Supermouse] Failed to cleanup crashed plugin '${t.name}'.`, e);
668
791
  }
669
792
  t.element?.remove();
670
793
  }
@@ -683,17 +806,17 @@ class Y {
683
806
  update(t) {
684
807
  const e = t - this.lastTime, s = Math.min(e / 1e3, 0.1);
685
808
  this.lastTime = t;
686
- const n = this.input.getCurrentTarget();
687
- n && !n.isConnected ? this.input.clearHover() : n && this.input.parseDOMInteraction(n), this.input.isEnabled && this.state.hasReceivedInput && (this.state.target.x = this.state.pointer.x, this.state.target.y = this.state.pointer.y);
688
- const o = this._activeScope;
689
- if (o) {
690
- o.stage.setVisibility(this.resolveStageVisibility()), this.input.isEnabled && o.stage.setNativeCursor(this.resolveCursorState());
691
- for (let h = 0; h < o.plugins.length; h++)
692
- this.runPluginSafe(o.plugins[h], e);
809
+ const i = this.input.getCurrentTarget();
810
+ i && !i.isConnected ? this.input.clearHover() : i && this.input.parseDOMInteraction(i), this.input.isEnabled && this.state.hasReceivedInput && (this.state.target.x = this.state.pointer.x, this.state.target.y = this.state.pointer.y);
811
+ const h = this._activeScope;
812
+ if (h) {
813
+ h.stage.setVisibility(this.resolveStageVisibility()), this.input.isEnabled && h.stage.setNativeCursor(this.resolveCursorState());
814
+ for (let r = 0; r < h.plugins.length; r++)
815
+ this.runPluginSafe(h.plugins[r], e);
693
816
  }
694
817
  if (this.cleanupCrashedPlugins(), this.input.isEnabled) {
695
- const h = this.state.reducedMotion ? 1e3 : 1 / this.options.smoothness * 2, r = this.state.smooth.x, p = this.state.smooth.y;
696
- this.state.smooth.x = w(this.state.smooth.x, this.state.target.x, h, s), this.state.smooth.y = w(this.state.smooth.y, this.state.target.y, h, s), this.state.displacement.x = this.state.target.x - this.state.smooth.x, this.state.displacement.y = this.state.target.y - this.state.smooth.y, s > 0 ? (this.state.velocity.x = (this.state.smooth.x - r) / s, this.state.velocity.y = (this.state.smooth.y - p) / s) : (this.state.velocity.x = 0, this.state.velocity.y = 0);
818
+ const r = this.state.reducedMotion ? 1e3 : 1 / this.options.smoothness * 2, o = this.state.smooth.x, p = this.state.smooth.y;
819
+ this.state.smooth.x = m(this.state.smooth.x, this.state.target.x, r, s), this.state.smooth.y = m(this.state.smooth.y, this.state.target.y, r, s), this.state.displacement.x = this.state.target.x - this.state.smooth.x, this.state.displacement.y = this.state.target.y - this.state.smooth.y, s > 0 ? (this.state.velocity.x = (this.state.smooth.x - o) / s, this.state.velocity.y = (this.state.smooth.y - p) / s) : (this.state.velocity.x = 0, this.state.velocity.y = 0);
697
820
  const { x: c, y: a } = this.state.velocity;
698
821
  (Math.abs(c) > 0.1 || Math.abs(a) > 0.1) && (this.state.angle = Math.atan2(a, c) * (180 / Math.PI));
699
822
  }
@@ -713,22 +836,6 @@ class Y {
713
836
  startLoop() {
714
837
  this._running || (this._running = !0, !document.hidden && (this.lastTime = performance.now(), this.rafId = requestAnimationFrame(this.tick)));
715
838
  }
716
- /**
717
- * @deprecated Read from the active scope instead.
718
- * Exposed for tests and debugging.
719
- */
720
- get hoverSelectors() {
721
- const t = this._activeScope ?? this._scopes[0];
722
- return t ? t.hoverSelectors : /* @__PURE__ */ new Set();
723
- }
724
- /**
725
- * @deprecated Read from the active scope instead.
726
- * Exposed for tests and debugging.
727
- */
728
- get plugins() {
729
- const t = this._activeScope ?? this._scopes[0];
730
- return t ? t.plugins : [];
731
- }
732
839
  /**
733
840
  * Adds one or more hover selectors to the current scope. Intended for
734
841
  * raw-object plugins during `install`. Plugins written with `definePlugin`
@@ -739,13 +846,13 @@ class Y {
739
846
  const e = this._installingScope ?? this._activeScope ?? this._scopes[0];
740
847
  if (e)
741
848
  for (const s of t.split(",")) {
742
- const n = s.trim();
743
- n && e.hoverSelectors.add(n);
849
+ const i = s.trim();
850
+ i && e.hoverSelectors.add(i);
744
851
  }
745
852
  }
746
853
  }
747
854
  export {
748
- x as DEFAULT_CURSOR_POLICY,
749
- R as DEFAULT_HOVER_SELECTORS,
750
- Y as Supermouse
855
+ S as DEFAULT_CURSOR_POLICY,
856
+ _ as DEFAULT_HOVER_SELECTORS,
857
+ I as Supermouse
751
858
  };