@supermousejs/core 2.5.0-beta.2 → 2.5.0-beta.3
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 +34 -0
- package/dist/index.d.ts +112 -47
- package/dist/index.mjs +373 -279
- package/dist/index.umd.js +2 -2
- package/package.json +8 -3
package/dist/index.mjs
CHANGED
|
@@ -1,62 +1,76 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
|
32
|
-
class
|
|
21
|
+
let y = 0;
|
|
22
|
+
class P {
|
|
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 (
|
|
35
|
-
throw new Error(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
}),
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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")
|
|
89
|
+
t !== this.currentCursorState && (this.currentCursorState = t, this.container.classList.toggle(this.hideClass, t === "none"));
|
|
76
90
|
}
|
|
77
91
|
destroy() {
|
|
78
|
-
this.
|
|
92
|
+
this._detach();
|
|
79
93
|
}
|
|
80
94
|
}
|
|
81
|
-
class
|
|
95
|
+
class C {
|
|
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 ?
|
|
85
|
-
this.nativeSelectors =
|
|
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 P(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
|
-
|
|
98
|
-
|
|
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
|
}
|
|
@@ -112,16 +163,16 @@ class L {
|
|
|
112
163
|
`${t}${e} { cursor: none !important; }`,
|
|
113
164
|
`${t} *${e} { cursor: none !important; }`
|
|
114
165
|
];
|
|
115
|
-
for (const
|
|
116
|
-
s.push(`${t} ${
|
|
117
|
-
return s.push(
|
|
166
|
+
for (const i of this.hideSelectors)
|
|
167
|
+
s.push(`${t} ${i}${e} { cursor: none !important; }`);
|
|
168
|
+
return s.push(
|
|
118
169
|
`${t} input[type="range"]${e}::-webkit-slider-thumb { cursor: none !important; }`
|
|
119
170
|
), s.push(
|
|
120
171
|
`${t} input[type="range"]${e}::-moz-range-thumb { cursor: none !important; }`
|
|
121
172
|
), s;
|
|
122
173
|
}
|
|
123
174
|
}
|
|
124
|
-
const
|
|
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
|
-
]),
|
|
183
|
+
]), _ = [
|
|
133
184
|
"a",
|
|
134
185
|
"button",
|
|
135
186
|
"input",
|
|
136
187
|
"textarea",
|
|
137
188
|
"[data-hover]",
|
|
138
189
|
"[data-cursor]"
|
|
139
|
-
]
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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.
|
|
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
|
|
222
|
-
|
|
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,
|
|
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
|
|
247
|
-
for (;
|
|
251
|
+
let o = t;
|
|
252
|
+
for (; o; ) {
|
|
248
253
|
const p = [];
|
|
249
|
-
for (const [a, l] of
|
|
250
|
-
this.matchesSelector(
|
|
251
|
-
if (this.cachedChain.push({ element:
|
|
252
|
-
const c =
|
|
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
|
-
|
|
259
|
+
o = c;
|
|
255
260
|
}
|
|
256
261
|
}
|
|
257
|
-
const
|
|
258
|
-
for (const { element:
|
|
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(
|
|
267
|
+
const l = typeof a == "function" ? a(o) : a;
|
|
263
268
|
if (!l || typeof l != "object") continue;
|
|
264
|
-
for (const [
|
|
265
|
-
c[
|
|
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
|
|
269
|
-
if (!a.toLowerCase().startsWith(
|
|
270
|
-
const l = a.slice(
|
|
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
|
|
273
|
-
c[
|
|
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
|
|
282
|
+
a in r || (r[a] = l);
|
|
277
283
|
}
|
|
278
|
-
this.state.interaction =
|
|
284
|
+
this.state.interaction = r;
|
|
279
285
|
}
|
|
280
286
|
matchesSelector(t, e) {
|
|
281
287
|
try {
|
|
@@ -298,26 +304,33 @@ class k {
|
|
|
298
304
|
};
|
|
299
305
|
handleMouseOver = (t) => {
|
|
300
306
|
if (!this.isEnabled) return;
|
|
301
|
-
const e = t.target, s = this.
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
307
|
+
const e = t.target, s = this.resolveScope(e);
|
|
308
|
+
s && s !== this.activeScope && this.setActiveScope(s), this.activeScope && (this.settleHoverState(e), this.onHoverSettled());
|
|
309
|
+
};
|
|
310
|
+
isPointerInside(t) {
|
|
311
|
+
if (!this.hasSeenPointer) return !1;
|
|
312
|
+
const e = t.getBoundingClientRect();
|
|
313
|
+
return this.viewportX >= e.left && this.viewportX <= e.right && this.viewportY >= e.top && this.viewportY <= e.bottom;
|
|
314
|
+
}
|
|
315
|
+
settleHoverState(t) {
|
|
316
|
+
if (this.state.cursorMode === "auto" && t.closest(`[${this.ignoreAttribute}]`)) {
|
|
317
|
+
this.clearHover(), this.state.isNative = !0, this.nativeTarget = t;
|
|
305
318
|
return;
|
|
306
319
|
}
|
|
307
|
-
this.state.isNative = !1, this.nativeTarget = null, this.currentTarget =
|
|
308
|
-
const
|
|
309
|
-
if (
|
|
310
|
-
if (this.matchesSelector(
|
|
311
|
-
this.state.isNative = !0, this.nativeTarget =
|
|
320
|
+
this.state.isNative = !1, this.nativeTarget = null, this.currentTarget = t, this.parseDOMInteraction(t);
|
|
321
|
+
const e = t.closest(this.activeScope.hoverSelectorString);
|
|
322
|
+
if (e && (this.state.isHover = !0, this.state.hoverTarget = e), this.state.cursorMode === "auto") {
|
|
323
|
+
if (this.matchesSelector(t, this.activeScope.nativeSelectorString)) {
|
|
324
|
+
this.state.isNative = !0, this.nativeTarget = t;
|
|
312
325
|
return;
|
|
313
326
|
}
|
|
314
|
-
(
|
|
327
|
+
(t.isContentEditable || !E.has(this.resolveComputedCursor(t))) && (this.state.isNative = !0, this.nativeTarget = t);
|
|
315
328
|
}
|
|
316
|
-
}
|
|
329
|
+
}
|
|
317
330
|
handleMouseOut = (t) => {
|
|
318
331
|
if (!this.isEnabled) return;
|
|
319
332
|
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 = { ...
|
|
333
|
+
(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 = { ...d });
|
|
321
334
|
};
|
|
322
335
|
clearHover() {
|
|
323
336
|
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 = [];
|
|
@@ -330,38 +343,37 @@ class k {
|
|
|
330
343
|
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
344
|
}
|
|
332
345
|
destroy() {
|
|
333
|
-
this.abortController.abort(), this.
|
|
346
|
+
this.abortController.abort(), this.cachedChain = [];
|
|
334
347
|
}
|
|
335
348
|
}
|
|
336
|
-
let
|
|
337
|
-
const
|
|
338
|
-
function
|
|
339
|
-
return
|
|
349
|
+
let x = 0;
|
|
350
|
+
const f = /* @__PURE__ */ new Map();
|
|
351
|
+
function M() {
|
|
352
|
+
return x++;
|
|
340
353
|
}
|
|
341
|
-
function
|
|
342
|
-
let e =
|
|
343
|
-
e || (e = document.createElement("style"), e.id = `supermouse-styles-${
|
|
354
|
+
function T(n, t) {
|
|
355
|
+
let e = f.get(n);
|
|
356
|
+
e || (e = document.createElement("style"), e.id = `supermouse-styles-${n}`, document.head.appendChild(e), f.set(n, e)), e.textContent = t.join(`
|
|
344
357
|
`);
|
|
345
358
|
}
|
|
346
|
-
function
|
|
347
|
-
|
|
359
|
+
function A(n) {
|
|
360
|
+
f.get(n)?.remove(), f.delete(n);
|
|
348
361
|
}
|
|
349
|
-
const
|
|
350
|
-
function
|
|
351
|
-
return
|
|
362
|
+
const g = "2.5.0-beta.3";
|
|
363
|
+
function D(n, t, e) {
|
|
364
|
+
return n + (t - n) * e;
|
|
352
365
|
}
|
|
353
|
-
function
|
|
354
|
-
return
|
|
366
|
+
function m(n, t, e, s) {
|
|
367
|
+
return D(n, t, 1 - Math.exp(-e * s));
|
|
355
368
|
}
|
|
356
|
-
class
|
|
357
|
-
static version =
|
|
358
|
-
version =
|
|
369
|
+
class I {
|
|
370
|
+
static version = g;
|
|
371
|
+
version = g;
|
|
359
372
|
state;
|
|
360
373
|
options;
|
|
361
374
|
_scopes = [];
|
|
362
375
|
_activeScope = null;
|
|
363
376
|
_installingScope = null;
|
|
364
|
-
scopeByContainer = /* @__PURE__ */ new Map();
|
|
365
377
|
scopeByName = /* @__PURE__ */ new Map();
|
|
366
378
|
scopeHandles = /* @__PURE__ */ new Map();
|
|
367
379
|
input;
|
|
@@ -383,10 +395,10 @@ class Y {
|
|
|
383
395
|
zIndex: 9999,
|
|
384
396
|
inheritDataAttributes: !0,
|
|
385
397
|
...t
|
|
386
|
-
}, this.styleOwner =
|
|
387
|
-
pointer: { ...
|
|
388
|
-
target: { ...
|
|
389
|
-
smooth: { ...
|
|
398
|
+
}, this.styleOwner = M(), this.state = {
|
|
399
|
+
pointer: { ...d },
|
|
400
|
+
target: { ...d },
|
|
401
|
+
smooth: { ...d },
|
|
390
402
|
velocity: { x: 0, y: 0 },
|
|
391
403
|
displacement: { x: 0, y: 0 },
|
|
392
404
|
angle: 0,
|
|
@@ -410,14 +422,16 @@ class Y {
|
|
|
410
422
|
rules: this.options.rules,
|
|
411
423
|
zIndex: this.options.zIndex
|
|
412
424
|
});
|
|
413
|
-
if (this.input = new
|
|
425
|
+
if (this.input = new w(
|
|
414
426
|
this.state,
|
|
415
427
|
this.options,
|
|
416
428
|
(s) => {
|
|
417
429
|
s || this.reset();
|
|
418
430
|
},
|
|
419
|
-
(s) => this.handleActiveScopeChange(s)
|
|
420
|
-
|
|
431
|
+
(s) => this.handleActiveScopeChange(s),
|
|
432
|
+
(s) => this.resolveScopeForNode(s),
|
|
433
|
+
() => this.applyCursorNow()
|
|
434
|
+
), this.input.setActiveScope(e), this.installPlugins(e), this.options.scopes)
|
|
421
435
|
for (const s of this.options.scopes) this.addScope(s);
|
|
422
436
|
this.rebuildStylesheet(), this.bindVisibilityHandling(), this.options.autoStart && this.startLoop();
|
|
423
437
|
}
|
|
@@ -434,12 +448,23 @@ class Y {
|
|
|
434
448
|
get isRunning() {
|
|
435
449
|
return this._running;
|
|
436
450
|
}
|
|
451
|
+
/**
|
|
452
|
+
* Installs a plugin into the primary scope.
|
|
453
|
+
*
|
|
454
|
+
* In multi-scope mode, prefer `handle.use(plugin)` to target a specific
|
|
455
|
+
* scope. This method always installs to the primary scope, regardless of
|
|
456
|
+
* which scope is currently active.
|
|
457
|
+
*/
|
|
437
458
|
use(t) {
|
|
438
459
|
return this.installPlugin(this._scopes[0], t), this;
|
|
439
460
|
}
|
|
461
|
+
/**
|
|
462
|
+
* Searches every scope and returns the first plugin matching `name`.
|
|
463
|
+
* Scopes are searched in registration order (primary first).
|
|
464
|
+
*/
|
|
440
465
|
getPlugin(t) {
|
|
441
466
|
for (const e of this._scopes) {
|
|
442
|
-
const s = e.plugins.find((
|
|
467
|
+
const s = e.plugins.find((i) => i.name === t);
|
|
443
468
|
if (s) return s;
|
|
444
469
|
}
|
|
445
470
|
}
|
|
@@ -447,27 +472,48 @@ class Y {
|
|
|
447
472
|
const e = this.scopeByName.get(t);
|
|
448
473
|
return e ? this.scopeHandles.get(e) : void 0;
|
|
449
474
|
}
|
|
475
|
+
/**
|
|
476
|
+
* Enables a plugin by name, wherever it lives.
|
|
477
|
+
*
|
|
478
|
+
* If the plugin's scope is currently active, the activation lifecycle
|
|
479
|
+
* runs immediately. If the scope is inactive, `isEnabled` is set but
|
|
480
|
+
* hooks do not fire until the scope next activates.
|
|
481
|
+
*/
|
|
450
482
|
enablePlugin(t) {
|
|
451
483
|
const e = this.getPlugin(t);
|
|
452
484
|
if (!e || e.isEnabled !== !1) return;
|
|
453
485
|
e.isEnabled = !0;
|
|
454
|
-
const s = this.
|
|
455
|
-
s &&
|
|
486
|
+
const s = this.findScopeForPlugin(e);
|
|
487
|
+
s && s === this._activeScope && s.active && this.scopeActivatePlugin(e);
|
|
456
488
|
}
|
|
489
|
+
/**
|
|
490
|
+
* Disables a plugin by name, wherever it lives.
|
|
491
|
+
*
|
|
492
|
+
* If the plugin's scope is currently active, the deactivation lifecycle
|
|
493
|
+
* runs immediately. If the scope is inactive, `isEnabled` is set but
|
|
494
|
+
* hooks do not fire — they already ran when the scope went inactive.
|
|
495
|
+
*/
|
|
457
496
|
disablePlugin(t) {
|
|
458
497
|
const e = this.getPlugin(t);
|
|
459
|
-
e
|
|
498
|
+
if (!e || e.isEnabled === !1) return;
|
|
499
|
+
const s = this.findScopeForPlugin(e);
|
|
500
|
+
s !== null && s === this._activeScope && s.active ? this.deactivatePlugin(e) : e.isEnabled = !1;
|
|
460
501
|
}
|
|
461
502
|
togglePlugin(t) {
|
|
462
503
|
const e = this.getPlugin(t);
|
|
463
504
|
e && (e.isEnabled === !1 ? this.enablePlugin(t) : this.disablePlugin(t));
|
|
464
505
|
}
|
|
506
|
+
/**
|
|
507
|
+
* Sets the cursor mode on the *active* scope.
|
|
508
|
+
*
|
|
509
|
+
* To set the mode on a specific scope, use `handle.setCursor(mode)`.
|
|
510
|
+
*/
|
|
465
511
|
setCursor(t) {
|
|
466
|
-
this._activeScope && (this._activeScope
|
|
512
|
+
this._activeScope && this.setScopeCursor(this._activeScope, t);
|
|
467
513
|
}
|
|
468
514
|
addScope(t) {
|
|
469
515
|
const e = this.createScope(t);
|
|
470
|
-
return this.
|
|
516
|
+
return this.installPlugins(e), this.rebuildStylesheet(), this.scopeHandles.get(e);
|
|
471
517
|
}
|
|
472
518
|
enable() {
|
|
473
519
|
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 +522,7 @@ class Y {
|
|
|
476
522
|
this.input.isEnabled = !1, this._activeScope && (this._activeScope.stage.setNativeCursor("auto"), this._activeScope.stage.setVisibility(!1)), t?.reset && this.reset();
|
|
477
523
|
}
|
|
478
524
|
reset() {
|
|
479
|
-
this.state.target = { ...
|
|
525
|
+
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
526
|
}
|
|
481
527
|
start() {
|
|
482
528
|
this.startLoop();
|
|
@@ -490,25 +536,35 @@ class Y {
|
|
|
490
536
|
for (const e of t.plugins)
|
|
491
537
|
try {
|
|
492
538
|
e.destroy?.(this);
|
|
493
|
-
} catch {
|
|
539
|
+
} catch (s) {
|
|
540
|
+
console.error(s);
|
|
494
541
|
}
|
|
495
542
|
t.stage.destroy();
|
|
496
543
|
}
|
|
497
|
-
this._scopes = [], this.
|
|
544
|
+
this._scopes = [], this.scopeByName.clear(), this.scopeHandles.clear(), this._activeScope = null, this.state.scope = null, A(this.styleOwner);
|
|
498
545
|
}
|
|
499
546
|
// ─── Internal ───
|
|
500
547
|
_running = !1;
|
|
501
548
|
createScope(t) {
|
|
502
|
-
|
|
503
|
-
|
|
549
|
+
if (typeof t.container != "string") {
|
|
550
|
+
const s = t.container;
|
|
551
|
+
for (const i of this._scopes)
|
|
552
|
+
if (i.containerSelector === null && i.container === s) {
|
|
553
|
+
console.warn(
|
|
554
|
+
"[Supermouse] A scope is already registered for this container. The previous scope will no longer activate."
|
|
555
|
+
);
|
|
556
|
+
break;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
const e = new C(t, {
|
|
504
560
|
cursor: this.options.cursor,
|
|
505
|
-
hoverSelectors: this.options.hoverSelectors ??
|
|
506
|
-
cursorPolicy: this.options.cursorPolicy ?
|
|
561
|
+
hoverSelectors: this.options.hoverSelectors ?? _,
|
|
562
|
+
cursorPolicy: this.options.cursorPolicy ? b(this.options.cursorPolicy) : S,
|
|
507
563
|
zIndex: this.options.zIndex,
|
|
508
564
|
inheritDataAttributes: this.options.inheritDataAttributes,
|
|
509
565
|
ruleEntries: this.options.rules ? Object.entries(this.options.rules) : []
|
|
510
566
|
});
|
|
511
|
-
return this._scopes.push(e),
|
|
567
|
+
return this._scopes.push(e), e.name && this.scopeByName.set(e.name, e), this.scopeHandles.set(e, this.buildScopeHandle(e)), e;
|
|
512
568
|
}
|
|
513
569
|
buildScopeHandle(t) {
|
|
514
570
|
const e = {
|
|
@@ -516,55 +572,105 @@ class Y {
|
|
|
516
572
|
return t.name;
|
|
517
573
|
},
|
|
518
574
|
get container() {
|
|
519
|
-
return t.container;
|
|
575
|
+
return t.resolved ? t.container : null;
|
|
576
|
+
},
|
|
577
|
+
get active() {
|
|
578
|
+
return t.active;
|
|
520
579
|
},
|
|
521
|
-
get
|
|
522
|
-
return t.
|
|
580
|
+
get resolved() {
|
|
581
|
+
return t.resolved;
|
|
523
582
|
},
|
|
524
|
-
|
|
583
|
+
destroy: () => this.destroyScope(t),
|
|
525
584
|
setCursor: (s) => this.setScopeCursor(t, s),
|
|
526
|
-
|
|
527
|
-
|
|
585
|
+
deactivate: () => this.deactivateScope(t),
|
|
586
|
+
activate: () => this.activateScope(t),
|
|
528
587
|
use: (s) => (this.installPlugin(t, s), e),
|
|
529
588
|
removePlugin: (s) => this.removePluginFromScope(t, s),
|
|
530
|
-
getPlugin: (s) => t.plugins.find((
|
|
589
|
+
getPlugin: (s) => t.plugins.find((i) => i.name === s)
|
|
531
590
|
};
|
|
532
591
|
return e;
|
|
533
592
|
}
|
|
534
|
-
|
|
593
|
+
destroyScope(t) {
|
|
535
594
|
const e = this._scopes.indexOf(t);
|
|
536
595
|
if (e !== -1) {
|
|
537
596
|
for (const s of t.plugins)
|
|
538
597
|
try {
|
|
539
598
|
s.destroy?.(this);
|
|
540
|
-
} catch {
|
|
599
|
+
} catch (i) {
|
|
600
|
+
console.error(i);
|
|
541
601
|
}
|
|
542
|
-
if (t.plugins.length = 0, t.stage.destroy(), this._scopes.splice(e, 1),
|
|
543
|
-
const s = this.
|
|
544
|
-
this.input.setActiveScope(s);
|
|
602
|
+
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) {
|
|
603
|
+
const s = this.resolveScopeForNode(t.container.parentElement) ?? this._scopes.find((i) => i.active) ?? null;
|
|
604
|
+
this.input.setActiveScope(s), this.input.clearHover(), this.applyCursorNow();
|
|
545
605
|
}
|
|
546
606
|
this.rebuildStylesheet();
|
|
547
607
|
}
|
|
548
608
|
}
|
|
549
609
|
setScopeCursor(t, e) {
|
|
550
|
-
t.cursorMode = e, t === this._activeScope && (this.state.cursorMode = e);
|
|
610
|
+
t.cursorMode = e, t === this._activeScope && (this.state.cursorMode = e, this.applyCursorNow());
|
|
551
611
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
612
|
+
/**
|
|
613
|
+
* Marks the scope ineligible for activation and, if it was active, yields
|
|
614
|
+
* immediately to the nearest active ancestor scope (or nothing).
|
|
615
|
+
*/
|
|
616
|
+
deactivateScope(t) {
|
|
617
|
+
if (t.active && (t.active = !1, this._activeScope === t)) {
|
|
618
|
+
const e = this.resolveScopeForNode(t.container.parentElement) ?? this._scopes.find((s) => s.active) ?? null;
|
|
619
|
+
this.input.setActiveScope(e), this.input.clearHover(), this.applyCursorNow();
|
|
556
620
|
}
|
|
557
621
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
622
|
+
/**
|
|
623
|
+
* Marks the scope eligible for activation.
|
|
624
|
+
*
|
|
625
|
+
* If the pointer is already inside the scope's container, the scope
|
|
626
|
+
* becomes active immediately. Otherwise it activates on the next
|
|
627
|
+
* `mouseover` inside the container. Deactivation is always eager.
|
|
628
|
+
*/
|
|
629
|
+
activateScope(t) {
|
|
630
|
+
if (t.active = !0, this._activeScope !== t && this.input.hasSeenPointer) {
|
|
631
|
+
if (t.containerSelector !== null && !t.resolved) {
|
|
632
|
+
const e = document.querySelectorAll(t.containerSelector);
|
|
633
|
+
for (const s of e)
|
|
634
|
+
if (this.input.isPointerInside(s)) {
|
|
635
|
+
t.bind(s);
|
|
636
|
+
break;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
t.resolved && this.input.isPointerInside(t.container) && (this.input.setActiveScope(t), this.applyCursorNow());
|
|
567
640
|
}
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Called by `Input` on every `mouseover`, and internally when the active
|
|
644
|
+
* scope is removed or deactivated. Walks from `node` up the ancestor
|
|
645
|
+
* chain, returning the innermost active scope whose `match` succeeds
|
|
646
|
+
* for an ancestor. The matched scope is bound to that ancestor before
|
|
647
|
+
* return.
|
|
648
|
+
*
|
|
649
|
+
* The walk order is what enforces "innermost wins": the first ancestor
|
|
650
|
+
* matching any active scope is, by construction, the closest one to the
|
|
651
|
+
* event target. Detached containers can never be ancestors of a live
|
|
652
|
+
* event target, so no cleanup of stale bindings is required here.
|
|
653
|
+
*/
|
|
654
|
+
resolveScopeForNode(t) {
|
|
655
|
+
for (let e = t; e; e = e.parentElement)
|
|
656
|
+
for (const s of this._scopes)
|
|
657
|
+
if (s.active && s.match(e))
|
|
658
|
+
return s.bind(e), s;
|
|
659
|
+
return null;
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Synchronously writes the current cursor and stage visibility for the
|
|
663
|
+
* active scope. Called after hover state settles, on cursor mode changes,
|
|
664
|
+
* and on programmatic scope transitions. The `update()` rAF path calls
|
|
665
|
+
* the same writers as a backstop.
|
|
666
|
+
*/
|
|
667
|
+
applyCursorNow() {
|
|
668
|
+
const t = this._activeScope;
|
|
669
|
+
t && (t.stage.setVisibility(this.resolveStageVisibility()), this.input.isEnabled && t.stage.setNativeCursor(this.resolveCursorState()));
|
|
670
|
+
}
|
|
671
|
+
findScopeForPlugin(t) {
|
|
672
|
+
for (const e of this._scopes)
|
|
673
|
+
if (e.plugins.includes(t)) return e;
|
|
568
674
|
return null;
|
|
569
675
|
}
|
|
570
676
|
installPlugins(t) {
|
|
@@ -572,32 +678,35 @@ class Y {
|
|
|
572
678
|
for (const e of t.config.plugins) this.installPlugin(t, e);
|
|
573
679
|
}
|
|
574
680
|
installPlugin(t, e) {
|
|
575
|
-
if (
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
681
|
+
if (t.plugins.some((s) => s.name === e.name)) {
|
|
682
|
+
console.warn(`[Supermouse] Plugin "${e.name}" already installed.`);
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
e.isEnabled ??= !0, this._installingScope = t;
|
|
686
|
+
try {
|
|
687
|
+
e.install?.(this);
|
|
688
|
+
} catch (s) {
|
|
689
|
+
console.error(`[Supermouse] Failed to install plugin '${e.name}'.`, s), this._installingScope = null;
|
|
690
|
+
return;
|
|
584
691
|
}
|
|
692
|
+
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
693
|
}
|
|
586
694
|
removePluginFromScope(t, e) {
|
|
587
|
-
const s = t.plugins.findIndex((
|
|
695
|
+
const s = t.plugins.findIndex((o) => o.name === e);
|
|
588
696
|
if (s === -1) return;
|
|
589
|
-
const
|
|
697
|
+
const i = t.plugins[s];
|
|
590
698
|
t.plugins.splice(s, 1);
|
|
591
|
-
const
|
|
699
|
+
const h = () => {
|
|
592
700
|
try {
|
|
593
|
-
|
|
594
|
-
} catch {
|
|
701
|
+
i.onDisable?.(this), i.destroy?.(this);
|
|
702
|
+
} catch (o) {
|
|
703
|
+
console.error(`[Supermouse] Plugin '${e}' cleanup threw:`, o);
|
|
595
704
|
}
|
|
596
|
-
|
|
597
|
-
},
|
|
598
|
-
|
|
599
|
-
o();
|
|
600
|
-
}) :
|
|
705
|
+
i.element?.remove();
|
|
706
|
+
}, r = i.onBeforeDisable?.(this);
|
|
707
|
+
r && typeof r.then == "function" ? Promise.resolve(r).then(h).catch((o) => {
|
|
708
|
+
console.error(`[Supermouse] Plugin '${e}' onBeforeDisable threw:`, o), h();
|
|
709
|
+
}) : h();
|
|
601
710
|
}
|
|
602
711
|
handleActiveScopeChange(t) {
|
|
603
712
|
const e = this._activeScope;
|
|
@@ -619,8 +728,8 @@ class Y {
|
|
|
619
728
|
const e = () => {
|
|
620
729
|
t.element && (t.element.style.display = "none"), t.onDisable?.(this);
|
|
621
730
|
}, s = t.onBeforeDisable?.(this);
|
|
622
|
-
s && typeof s.then == "function" ? Promise.resolve(s).then(e).catch((
|
|
623
|
-
e();
|
|
731
|
+
s && typeof s.then == "function" ? Promise.resolve(s).then(e).catch((i) => {
|
|
732
|
+
console.error(`[Supermouse] Plugin '${t.name}' onBeforeDisable threw:`, i), e();
|
|
624
733
|
}) : e();
|
|
625
734
|
}
|
|
626
735
|
/**
|
|
@@ -632,24 +741,24 @@ class Y {
|
|
|
632
741
|
const e = () => {
|
|
633
742
|
t.element && (t.element.style.display = "none"), t.onDisable?.(this);
|
|
634
743
|
}, s = t.onBeforeDisable?.(this);
|
|
635
|
-
s && typeof s.then == "function" ? Promise.resolve(s).then(e).catch((
|
|
636
|
-
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();
|
|
637
746
|
}) : e();
|
|
638
747
|
}
|
|
639
748
|
scopeActivatePlugin(t) {
|
|
640
749
|
t.element && (t.element.style.display = ""), t.onEnable?.(this);
|
|
641
750
|
}
|
|
642
751
|
rebuildStylesheet() {
|
|
643
|
-
const t = [];
|
|
752
|
+
const t = [":where(.supermouse-scope .supermouse-scope) { cursor: auto }"];
|
|
644
753
|
for (const e of this._scopes) t.push(...e.buildRules());
|
|
645
|
-
|
|
754
|
+
T(this.styleOwner, t);
|
|
646
755
|
}
|
|
647
756
|
runPluginSafe(t, e) {
|
|
648
757
|
if (t.isEnabled !== !1)
|
|
649
758
|
try {
|
|
650
759
|
t.update?.(this, e);
|
|
651
|
-
} catch {
|
|
652
|
-
t.isEnabled = !1, this.crashedPlugins.push(t);
|
|
760
|
+
} catch (s) {
|
|
761
|
+
console.error(`[Supermouse] Plugin '${t.name}' crashed and has been disabled.`, s), t.isEnabled = !1, this.crashedPlugins.push(t);
|
|
653
762
|
}
|
|
654
763
|
}
|
|
655
764
|
cleanupCrashedPlugins() {
|
|
@@ -664,7 +773,8 @@ class Y {
|
|
|
664
773
|
}
|
|
665
774
|
try {
|
|
666
775
|
t.onDisable?.(this), t.destroy?.(this);
|
|
667
|
-
} catch {
|
|
776
|
+
} catch (e) {
|
|
777
|
+
console.error(`[Supermouse] Failed to cleanup crashed plugin '${t.name}'.`, e);
|
|
668
778
|
}
|
|
669
779
|
t.element?.remove();
|
|
670
780
|
}
|
|
@@ -683,17 +793,17 @@ class Y {
|
|
|
683
793
|
update(t) {
|
|
684
794
|
const e = t - this.lastTime, s = Math.min(e / 1e3, 0.1);
|
|
685
795
|
this.lastTime = t;
|
|
686
|
-
const
|
|
687
|
-
|
|
688
|
-
const
|
|
689
|
-
if (
|
|
690
|
-
|
|
691
|
-
for (let
|
|
692
|
-
this.runPluginSafe(
|
|
796
|
+
const i = this.input.getCurrentTarget();
|
|
797
|
+
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);
|
|
798
|
+
const h = this._activeScope;
|
|
799
|
+
if (h) {
|
|
800
|
+
h.stage.setVisibility(this.resolveStageVisibility()), this.input.isEnabled && h.stage.setNativeCursor(this.resolveCursorState());
|
|
801
|
+
for (let r = 0; r < h.plugins.length; r++)
|
|
802
|
+
this.runPluginSafe(h.plugins[r], e);
|
|
693
803
|
}
|
|
694
804
|
if (this.cleanupCrashedPlugins(), this.input.isEnabled) {
|
|
695
|
-
const
|
|
696
|
-
this.state.smooth.x =
|
|
805
|
+
const r = this.state.reducedMotion ? 1e3 : 1 / this.options.smoothness * 2, o = this.state.smooth.x, p = this.state.smooth.y;
|
|
806
|
+
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
807
|
const { x: c, y: a } = this.state.velocity;
|
|
698
808
|
(Math.abs(c) > 0.1 || Math.abs(a) > 0.1) && (this.state.angle = Math.atan2(a, c) * (180 / Math.PI));
|
|
699
809
|
}
|
|
@@ -713,22 +823,6 @@ class Y {
|
|
|
713
823
|
startLoop() {
|
|
714
824
|
this._running || (this._running = !0, !document.hidden && (this.lastTime = performance.now(), this.rafId = requestAnimationFrame(this.tick)));
|
|
715
825
|
}
|
|
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
826
|
/**
|
|
733
827
|
* Adds one or more hover selectors to the current scope. Intended for
|
|
734
828
|
* raw-object plugins during `install`. Plugins written with `definePlugin`
|
|
@@ -739,13 +833,13 @@ class Y {
|
|
|
739
833
|
const e = this._installingScope ?? this._activeScope ?? this._scopes[0];
|
|
740
834
|
if (e)
|
|
741
835
|
for (const s of t.split(",")) {
|
|
742
|
-
const
|
|
743
|
-
|
|
836
|
+
const i = s.trim();
|
|
837
|
+
i && e.hoverSelectors.add(i);
|
|
744
838
|
}
|
|
745
839
|
}
|
|
746
840
|
}
|
|
747
841
|
export {
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
842
|
+
S as DEFAULT_CURSOR_POLICY,
|
|
843
|
+
_ as DEFAULT_HOVER_SELECTORS,
|
|
844
|
+
I as Supermouse
|
|
751
845
|
};
|