@supermousejs/core 2.4.3 → 2.5.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/README.md +220 -158
- package/dist/index.d.ts +137 -55
- package/dist/index.mjs +467 -312
- package/dist/index.umd.js +2 -10
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# @supermousejs/core
|
|
2
2
|
|
|
3
|
+
## 2.5.0-beta.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 5d5ec21: Updated README to document cursor policy and scopes
|
|
8
|
+
|
|
9
|
+
## 2.5.0-beta.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 0af4732: Architecture rewrite for v2.5. This is a beta, therefore expect API surface churn before the stable release.
|
|
14
|
+
|
|
15
|
+
**Scopes.** A single instance can now own multiple scopes. Pass them at construction or add them at runtime:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
const mouse = new Supermouse({
|
|
19
|
+
scopes: [{ name: "sidebar", container: sidebarEl, cursor: "native" }]
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const handle = mouse.addScope({ container: modalEl, cursor: "custom" });
|
|
23
|
+
handle.setCursor("auto");
|
|
24
|
+
handle.remove();
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The innermost scope whose container contains the pointer is the active one. Plugin installation, cursor mode, hover selectors, and native-cursor state are all managed per scope.
|
|
28
|
+
|
|
29
|
+
**Cursor policy.** `NATIVE_TAGS` and the old `Stage.selectors` are unified into a single `CursorPolicy`. Pass a custom policy via `cursorPolicy` at the top level or per scope. `DEFAULT_CURSOR_POLICY` is exported for spreading.
|
|
30
|
+
|
|
31
|
+
**Ancestor-chain interaction.** `data-supermouse-*` attributes and `rules` now cascade from ancestors to the hovered element, ensuring the closest ancestor wins. This fixes the tag-inside-a-tag class of bugs. Disable with `inheritDataAttributes: false`.
|
|
32
|
+
|
|
33
|
+
**Lifecycle.** `onBeforeDisable` (and its `definePlugin` equivalent, `beforeDisable`) is now scope-aware: when a scope deactivates, each of its plugins runs `onBeforeDisable`, and the core waits for any returned Promise before hiding the element and calling `onDisable`.
|
|
34
|
+
|
|
35
|
+
**Changed.**
|
|
36
|
+
- `disable()` no longer resets physics. Call `disable({ reset: true })` for the old behavior.
|
|
37
|
+
- `suspend()` and `resume()` are removed. Use scopes.
|
|
38
|
+
- `registerHoverTarget` now mutates the active scope's selector set. It's still available for raw-object plugins, but `definePlugin`'s `selector` option is preferred.
|
|
39
|
+
- Stage no longer owns an individual `<style>` tag. All scopes share a single engine-level stylesheet.
|
|
40
|
+
|
|
41
|
+
**Removed.**
|
|
42
|
+
- `NATIVE_TAGS`, `SUPERMOUSE_CURSORS` internal constants (moved into policy).
|
|
43
|
+
- `Stage.addSelector` / `Stage.addSelectors` no-ops.
|
|
44
|
+
|
|
45
|
+
### Patch Changes
|
|
46
|
+
|
|
47
|
+
- 1325a9c: Reorganized Supermouse core for better tree-shaking and module isolation
|
|
48
|
+
|
|
3
49
|
## 2.4.3
|
|
4
50
|
|
|
5
51
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,158 +1,220 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/@supermousejs/core)
|
|
4
|
-
[](https://www.npmjs.com/package/@supermousejs/core)
|
|
5
|
-
[](https://opensource.org/licenses/MIT)
|
|
6
|
-

|
|
7
|
-
|
|
8
|
-
Supermouse is a headless, physics
|
|
9
|
-
|
|
10
|
-
**Documentation:** [supermouse.js.org](https://supermouse.js.org)
|
|
11
|
-
|
|
12
|
-
## Installation
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
pnpm add @supermousejs/core
|
|
16
|
-
npm install @supermousejs/core
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Install plugins you need:
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
pnpm add @supermousejs/dot @supermousejs/ring
|
|
23
|
-
npm install @supermousejs/dot @supermousejs/ring
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Quick Start
|
|
27
|
-
|
|
28
|
-
```ts
|
|
29
|
-
import { Supermouse } from "@supermousejs/core";
|
|
30
|
-
import { Dot } from "@supermousejs/dot";
|
|
31
|
-
|
|
32
|
-
const mouse = new Supermouse({
|
|
33
|
-
plugins: [Dot({ size: 8 })]
|
|
34
|
-
});
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Or
|
|
38
|
-
|
|
39
|
-
```ts
|
|
40
|
-
import { Supermouse } from "@supermousejs/core";
|
|
41
|
-
|
|
42
|
-
const dot = document.createElement("div");
|
|
43
|
-
// ... style dot ...
|
|
44
|
-
|
|
45
|
-
const redDot = {
|
|
46
|
-
name: "red-dot",
|
|
47
|
-
install(app) {
|
|
48
|
-
app.stage.appendChild(dot);
|
|
49
|
-
},
|
|
50
|
-
update(app) {
|
|
51
|
-
const { smooth } = app.state;
|
|
52
|
-
dot.style.transform = `translate3d(${smooth.x}px, ${smooth.y}px, 0)`;
|
|
53
|
-
},
|
|
54
|
-
destroy() {
|
|
55
|
-
dot.remove();
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const mouse = new Supermouse({ plugins: [redDot] });
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
mouse
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
mouse.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
1
|
+
# @supermousejs/core
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@supermousejs/core)
|
|
4
|
+
[](https://www.npmjs.com/package/@supermousejs/core)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
Supermouse is a headless, physics-based cursor engine for the web, written in TypeScript. It provides pointer tracking, state, physics, and a plugin lifecycle. You install plugins (or write your own) to render custom cursors and effects. Zero runtime dependencies.
|
|
9
|
+
|
|
10
|
+
**Documentation:** [supermouse.js.org](https://supermouse.js.org)
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add @supermousejs/core
|
|
16
|
+
npm install @supermousejs/core
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Install plugins you need:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm add @supermousejs/dot @supermousejs/ring
|
|
23
|
+
npm install @supermousejs/dot @supermousejs/ring
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { Supermouse } from "@supermousejs/core";
|
|
30
|
+
import { Dot } from "@supermousejs/dot";
|
|
31
|
+
|
|
32
|
+
const mouse = new Supermouse({
|
|
33
|
+
plugins: [Dot({ size: 8 })]
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or write a plugin directly:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { Supermouse } from "@supermousejs/core";
|
|
41
|
+
|
|
42
|
+
const dot = document.createElement("div");
|
|
43
|
+
// ... style dot ...
|
|
44
|
+
|
|
45
|
+
const redDot = {
|
|
46
|
+
name: "red-dot",
|
|
47
|
+
install(app) {
|
|
48
|
+
app.stage.appendChild(dot);
|
|
49
|
+
},
|
|
50
|
+
update(app) {
|
|
51
|
+
const { smooth } = app.state;
|
|
52
|
+
dot.style.transform = `translate3d(${smooth.x}px, ${smooth.y}px, 0)`;
|
|
53
|
+
},
|
|
54
|
+
destroy() {
|
|
55
|
+
dot.remove();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const mouse = new Supermouse({ plugins: [redDot] });
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> Mount plugin elements to `app.stage`, not to `document.body`, so cursor suppression, scope switching, and cleanup work automatically.
|
|
63
|
+
|
|
64
|
+
## Options
|
|
65
|
+
|
|
66
|
+
| Option | Default | Description |
|
|
67
|
+
| ----------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------- |
|
|
68
|
+
| `smoothness` | `0.15` | Lower = smoother cursor follow |
|
|
69
|
+
| `hoverSelectors` | `["a", "button", "input", "textarea", "[data-hover]", "[data-cursor]"]` | Selectors that set `state.isHover` |
|
|
70
|
+
| `enableTouch` | `false` | Allow touch events to move the cursor |
|
|
71
|
+
| `autoDisableOnMobile` | `true` | Disable on coarse-pointer devices |
|
|
72
|
+
| `cursor` | `"auto"` | `"auto"`, `"custom"`, `"native"`, or `"both"` |
|
|
73
|
+
| `cursorPolicy` | `DEFAULT_CURSOR_POLICY` | Rules for native-cursor fallback and CSS suppression |
|
|
74
|
+
| `inheritDataAttributes` | `true` | Cascade `data-*` attributes and `rules` from ancestors |
|
|
75
|
+
| `hideOnLeave` | `true` | Hide when the pointer leaves the window |
|
|
76
|
+
| `container` | `document.body` | Primary scope's container |
|
|
77
|
+
| `scopes` | — | Additional scopes registered at construction |
|
|
78
|
+
| `zIndex` | `9999` | Stage stacking order |
|
|
79
|
+
| `dataPrefix` | `"supermouse"` | Prefix for data attributes |
|
|
80
|
+
| `rules` | — | Map of selectors to interaction data |
|
|
81
|
+
| `plugins` | — | Plugins to install at creation |
|
|
82
|
+
| `autoStart` | `true` | Set `false` and call `.start()` manually |
|
|
83
|
+
|
|
84
|
+
## Cursor Modes
|
|
85
|
+
|
|
86
|
+
The `cursor` option decides which cursor(s) to show:
|
|
87
|
+
|
|
88
|
+
- `"auto"` — native cursor on elements that should own it (inputs, links), custom elsewhere.
|
|
89
|
+
- `"custom"` — always custom, hide native.
|
|
90
|
+
- `"native"` — always native, hide custom.
|
|
91
|
+
- `"both"` — show both native and custom together.
|
|
92
|
+
|
|
93
|
+
Change at runtime with `mouse.setCursor("both")`.
|
|
94
|
+
|
|
95
|
+
The [Cursor Policy](#cursor-policy) decides which elements are considered native in `"auto"` mode.
|
|
96
|
+
|
|
97
|
+
## Cursor Policy
|
|
98
|
+
|
|
99
|
+
A single object maps selectors to two independent flags:
|
|
100
|
+
|
|
101
|
+
- `native` — in `"auto"` mode, matching elements yield to the OS cursor.
|
|
102
|
+
- `hide` — when the custom cursor is active, matching elements get `cursor: none !important`.
|
|
103
|
+
|
|
104
|
+
Extend the default policy:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import { Supermouse, DEFAULT_CURSOR_POLICY } from "@supermousejs/core";
|
|
108
|
+
|
|
109
|
+
const mouse = new Supermouse({
|
|
110
|
+
cursorPolicy: {
|
|
111
|
+
rules: [
|
|
112
|
+
...DEFAULT_CURSOR_POLICY.rules,
|
|
113
|
+
{ selector: "[data-native]", native: true }
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Or shorthand:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
const mouse = new Supermouse({
|
|
123
|
+
cursorPolicy: {
|
|
124
|
+
native: ["input", "textarea", "select", "[data-native]"],
|
|
125
|
+
hide: ["a", "button", "[role='button']"]
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Scopes
|
|
131
|
+
|
|
132
|
+
A single Supermouse instance can own multiple scopes. Each scope has its own container, cursor mode, hover selectors, cursor policy, and plugins. The innermost scope containing the pointer is the active one.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const mouse = new Supermouse({
|
|
136
|
+
scopes: [
|
|
137
|
+
{ name: "main", container: document.body, plugins: [Dot({ color: "red" })] },
|
|
138
|
+
{ name: "sidebar", container: sidebarEl, cursor: "custom" }
|
|
139
|
+
]
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Or add at runtime:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
const handle = mouse.addScope({ container: modalEl, cursor: "both" });
|
|
147
|
+
handle.setCursor("auto");
|
|
148
|
+
handle.remove();
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The single-container form is shorthand for one scope:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
const mouse = new Supermouse({ container: modalEl, cursor: "custom" });
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Native Cursor Fallback
|
|
158
|
+
|
|
159
|
+
In `"auto"` mode, add `data-supermouse-ignore` to force the native cursor on an element and its descendants:
|
|
160
|
+
|
|
161
|
+
```html
|
|
162
|
+
<div data-supermouse-ignore>Native cursor here</div>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Data Attributes
|
|
166
|
+
|
|
167
|
+
Plugins can react to `data-*` attributes (e.g. `data-supermouse-color`). Attributes cascade from ancestors to the hovered element when `inheritDataAttributes` is `true`. Change the prefix with `dataPrefix`.
|
|
168
|
+
|
|
169
|
+
## Rules
|
|
170
|
+
|
|
171
|
+
Define interaction data without writing many attributes:
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
const mouse = new Supermouse({
|
|
175
|
+
rules: {
|
|
176
|
+
".primary-action": { magnetic: true, color: "red" }
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Rules match ancestors as well as the hovered element. HTML `data-*` attributes override rule values per property.
|
|
182
|
+
|
|
183
|
+
## API
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
mouse.state; // current MouseState
|
|
187
|
+
mouse.options; // resolved options
|
|
188
|
+
mouse.stage; // DOM element plugins render into
|
|
189
|
+
mouse.container; // container element (active scope)
|
|
190
|
+
mouse.isEnabled; // input processing flag
|
|
191
|
+
mouse.isRunning; // animation loop flag
|
|
192
|
+
|
|
193
|
+
mouse.enable(); // start input, apply cursor state
|
|
194
|
+
mouse.disable(); // stop input, restore native cursor
|
|
195
|
+
mouse.disable({ reset: true }); // also reset physics and hover state
|
|
196
|
+
mouse.reset(); // reset state only
|
|
197
|
+
|
|
198
|
+
mouse.setCursor(mode); // "auto" | "custom" | "native" | "both"
|
|
199
|
+
|
|
200
|
+
mouse.addScope(config); // -> { name, container, setCursor, remove }
|
|
201
|
+
|
|
202
|
+
mouse.use(plugin); // install plugin
|
|
203
|
+
mouse.getPlugin(name); // retrieve plugin
|
|
204
|
+
mouse.enablePlugin(name); // enable plugin
|
|
205
|
+
mouse.disablePlugin(name); // disable plugin
|
|
206
|
+
mouse.togglePlugin(name); // toggle plugin
|
|
207
|
+
|
|
208
|
+
mouse.registerHoverTarget(sel); // add hover selector at runtime
|
|
209
|
+
mouse.start(); // start animation loop
|
|
210
|
+
mouse.step(time); // advance one frame manually
|
|
211
|
+
mouse.destroy(); // destroy instance and plugins
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Browser Support
|
|
215
|
+
|
|
216
|
+
All modern browsers.
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
|
|
220
|
+
MIT
|