@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/CHANGELOG.md +54 -0
- package/dist/index.d.ts +122 -47
- package/dist/index.mjs +394 -287
- 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 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 (
|
|
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 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 ?
|
|
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 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
|
-
|
|
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
|
}
|
|
@@ -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
|
|
116
|
-
|
|
117
|
-
return
|
|
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
|
-
),
|
|
170
|
+
), i.push(
|
|
120
171
|
`${t} input[type="range"]${e}::-moz-range-thumb { cursor: none !important; }`
|
|
121
|
-
),
|
|
172
|
+
), i;
|
|
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 {
|
|
@@ -284,8 +290,17 @@ class k {
|
|
|
284
290
|
return !1;
|
|
285
291
|
}
|
|
286
292
|
}
|
|
287
|
-
|
|
288
|
-
|
|
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.
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
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 =
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
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
|
-
(
|
|
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 = { ...
|
|
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.
|
|
357
|
+
this.abortController.abort(), this.cachedChain = [];
|
|
334
358
|
}
|
|
335
359
|
}
|
|
336
|
-
let
|
|
337
|
-
const
|
|
338
|
-
function
|
|
339
|
-
return
|
|
360
|
+
let x = 0;
|
|
361
|
+
const f = /* @__PURE__ */ new Map();
|
|
362
|
+
function T() {
|
|
363
|
+
return x++;
|
|
340
364
|
}
|
|
341
|
-
function
|
|
342
|
-
let e =
|
|
343
|
-
e || (e = document.createElement("style"), e.id = `supermouse-styles-${
|
|
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
|
|
347
|
-
|
|
370
|
+
function A(n) {
|
|
371
|
+
f.get(n)?.remove(), f.delete(n);
|
|
348
372
|
}
|
|
349
|
-
const
|
|
350
|
-
function
|
|
351
|
-
return
|
|
373
|
+
const g = "2.5.0-beta.4";
|
|
374
|
+
function D(n, t, e) {
|
|
375
|
+
return n + (t - n) * e;
|
|
352
376
|
}
|
|
353
|
-
function
|
|
354
|
-
return
|
|
377
|
+
function m(n, t, e, s) {
|
|
378
|
+
return D(n, t, 1 - Math.exp(-e * s));
|
|
355
379
|
}
|
|
356
|
-
class
|
|
357
|
-
static version =
|
|
358
|
-
version =
|
|
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 =
|
|
387
|
-
pointer: { ...
|
|
388
|
-
target: { ...
|
|
389
|
-
smooth: { ...
|
|
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
|
|
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
|
-
|
|
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((
|
|
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.
|
|
455
|
-
s &&
|
|
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
|
|
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
|
|
525
|
+
this._activeScope && this.setScopeCursor(this._activeScope, t);
|
|
467
526
|
}
|
|
468
527
|
addScope(t) {
|
|
469
528
|
const e = this.createScope(t);
|
|
470
|
-
return this.
|
|
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 = { ...
|
|
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.
|
|
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
|
-
|
|
503
|
-
|
|
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 ??
|
|
506
|
-
cursorPolicy: this.options.cursorPolicy ?
|
|
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),
|
|
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
|
|
522
|
-
return t.
|
|
593
|
+
get resolved() {
|
|
594
|
+
return t.resolved;
|
|
523
595
|
},
|
|
524
|
-
|
|
596
|
+
destroy: () => this.destroyScope(t),
|
|
525
597
|
setCursor: (s) => this.setScopeCursor(t, s),
|
|
526
|
-
|
|
527
|
-
|
|
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((
|
|
602
|
+
getPlugin: (s) => t.plugins.find((i) => i.name === s)
|
|
531
603
|
};
|
|
532
604
|
return e;
|
|
533
605
|
}
|
|
534
|
-
|
|
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),
|
|
543
|
-
const s = this.
|
|
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
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
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
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
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 (
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
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((
|
|
708
|
+
const s = t.plugins.findIndex((o) => o.name === e);
|
|
588
709
|
if (s === -1) return;
|
|
589
|
-
const
|
|
710
|
+
const i = t.plugins[s];
|
|
590
711
|
t.plugins.splice(s, 1);
|
|
591
|
-
const
|
|
712
|
+
const h = () => {
|
|
592
713
|
try {
|
|
593
|
-
|
|
594
|
-
} catch {
|
|
714
|
+
i.onDisable?.(this), i.destroy?.(this);
|
|
715
|
+
} catch (o) {
|
|
716
|
+
console.error(`[Supermouse] Plugin '${e}' cleanup threw:`, o);
|
|
595
717
|
}
|
|
596
|
-
|
|
597
|
-
},
|
|
598
|
-
|
|
599
|
-
o();
|
|
600
|
-
}) :
|
|
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((
|
|
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((
|
|
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
|
-
|
|
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
|
|
687
|
-
|
|
688
|
-
const
|
|
689
|
-
if (
|
|
690
|
-
|
|
691
|
-
for (let
|
|
692
|
-
this.runPluginSafe(
|
|
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
|
|
696
|
-
this.state.smooth.x =
|
|
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
|
|
743
|
-
|
|
849
|
+
const i = s.trim();
|
|
850
|
+
i && e.hoverSelectors.add(i);
|
|
744
851
|
}
|
|
745
852
|
}
|
|
746
853
|
}
|
|
747
854
|
export {
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
855
|
+
S as DEFAULT_CURSOR_POLICY,
|
|
856
|
+
_ as DEFAULT_HOVER_SELECTORS,
|
|
857
|
+
I as Supermouse
|
|
751
858
|
};
|