@supermousejs/core 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @supermousejs/core
2
+
3
+ ## 2.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - Initial v2.0.0 release
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Sijibomi Olusunmbola
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,304 @@
1
+ export declare const DEFAULT_HOVER_SELECTORS: string[];
2
+
3
+ /**
4
+ * The Interface for interaction state.
5
+ * Plugins should use Module Augmentation to add their specific properties to this interface.
6
+ *
7
+ * @example
8
+ * declare module '@supermousejs/core' {
9
+ * interface InteractionState {
10
+ * magnetic: boolean | number;
11
+ * text: string;
12
+ * }
13
+ * }
14
+ */
15
+ export declare interface InteractionState {
16
+ /**
17
+ * Allow arbitrary keys for rapid prototyping.
18
+ * For type safety, use module augmentation to define expected keys.
19
+ */
20
+ [key: string]: any;
21
+ }
22
+
23
+ export declare interface MousePosition {
24
+ x: number;
25
+ y: number;
26
+ }
27
+
28
+ export declare interface MouseState {
29
+ /** The raw position of the input pointer (mouse/touch). */
30
+ pointer: MousePosition;
31
+ /** The target position the cursor logic wants to reach. */
32
+ target: MousePosition;
33
+ /** The smoothed/interpolated position used for rendering. */
34
+ smooth: MousePosition;
35
+ /** The current velocity vector of the smooth position. */
36
+ velocity: MousePosition;
37
+ /** The angle of movement in degrees. Calculated from velocity. */
38
+ angle: number;
39
+ /** Whether the pointer is currently pressed down. */
40
+ isDown: boolean;
41
+ /** Whether the pointer is currently hovering over a registered interactive element. */
42
+ isHover: boolean;
43
+ /** Whether the native cursor is currently forced visible by internal logic (e.g. input elements). */
44
+ isNative: boolean;
45
+ /**
46
+ * If set, this overrides all auto-detection logic.
47
+ * 'auto' = Force Native Cursor (Show)
48
+ * 'none' = Force Custom Cursor (Hide Native)
49
+ * null = Let the Core decide based on isNative/isHover
50
+ */
51
+ forcedCursor: 'auto' | 'none' | null;
52
+ /** The DOM element currently being hovered, if any. */
53
+ hoverTarget: HTMLElement | null;
54
+ /** Whether the user has `prefers-reduced-motion` enabled. */
55
+ reducedMotion: boolean;
56
+ /** Whether the system has received valid input coordinates at least once. */
57
+ hasReceivedInput: boolean;
58
+ /** Defines a specific geometric shape the cursor should conform to. */
59
+ shape: ShapeState | null;
60
+ /** Centralized store for hover metadata from data attributes. */
61
+ interaction: InteractionState;
62
+ }
63
+
64
+ export declare type NativeIgnoreStrategy = 'auto' | 'tag' | 'css';
65
+
66
+ export declare interface ShapeState {
67
+ width: number;
68
+ height: number;
69
+ borderRadius: number;
70
+ }
71
+
72
+ /**
73
+ * The Central Conductor & Runtime Loop of Supermouse.
74
+ *
75
+ * This class orchestrates the application state, manages the animation loop (`requestAnimationFrame`),
76
+ * and coordinates data flow between the Input system, the Stage system, and the Plugins.
77
+ *
78
+ * ## Architecture
79
+ * 1. **Input System**: Captures raw events and writes to `state.pointer`.
80
+ * 2. **Logic Plugins**: (Priority < 0) Read `pointer`, modify `state.target` (e.g. Magnetic, Stick).
81
+ * 3. **Physics**: Core interpolates `state.smooth` towards `state.target`.
82
+ * 4. **Visual Plugins**: (Priority >= 0) Read `state.smooth`, update DOM transforms.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * const app = new Supermouse({ smoothness: 0.15 });
87
+ * app.use(Dot({ color: 'red' }));
88
+ * ```
89
+ */
90
+ export declare class Supermouse {
91
+ /** The current version of Supermouse.js */
92
+ static readonly version: string;
93
+ readonly version: string;
94
+ /**
95
+ * The Single Source of Truth.
96
+ *
97
+ * This object is shared by reference. `Input` writes to it; `Supermouse` physics reads/writes to it;
98
+ * Plugins read/write to it.
99
+ */
100
+ state: MouseState;
101
+ /**
102
+ * Configuration options.
103
+ */
104
+ options: SupermouseOptions;
105
+ /* Excluded from this release type: plugins */
106
+ /* Excluded from this release type: stage */
107
+ /* Excluded from this release type: input */
108
+ private rafId;
109
+ private lastTime;
110
+ private isRunning;
111
+ private hoverSelectors;
112
+ /**
113
+ * Creates a new Supermouse instance.
114
+ *
115
+ * @param options - Global configuration options.
116
+ * @throws Will throw if running in a non-browser environment (window/document undefined).
117
+ */
118
+ constructor(options?: SupermouseOptions);
119
+ /**
120
+ * Retrieves a registered plugin instance by its unique name.
121
+ */
122
+ getPlugin(name: string): SupermousePlugin | undefined;
123
+ /**
124
+ * Returns whether the cursor system is currently enabled (processing input).
125
+ */
126
+ get isEnabled(): boolean;
127
+ /**
128
+ * Enables a specific plugin by name.
129
+ * Triggers the `onEnable` lifecycle hook of the plugin.
130
+ */
131
+ enablePlugin(name: string): void;
132
+ /**
133
+ * Disables a specific plugin by name.
134
+ * Triggers the `onDisable` lifecycle hook.
135
+ */
136
+ disablePlugin(name: string): void;
137
+ /**
138
+ * Toggles the enabled state of a plugin.
139
+ */
140
+ togglePlugin(name: string): void;
141
+ /**
142
+ * Registers a CSS selector as an "Interactive Target".
143
+ *
144
+ * When the mouse hovers over an element matching this selector:
145
+ * 1. `state.isHover` becomes `true`.
146
+ * 2. `state.hoverTarget` is set to the element.
147
+ * 3. The `Stage` system injects CSS to hide the native cursor for this element (if `hideCursor: true`).
148
+ *
149
+ * @param selector - A valid CSS selector string (e.g., `.my-button`, `[data-trigger]`).
150
+ */
151
+ registerHoverTarget(selector: string): void;
152
+ /**
153
+ * The fixed container element where plugins should append their DOM nodes.
154
+ */
155
+ get container(): HTMLDivElement;
156
+ /**
157
+ * Manually override the native cursor visibility.
158
+ * Useful for drag-and-drop operations, modals, or special UI states.
159
+ *
160
+ * @param type 'auto' (Show Native), 'none' (Hide Native), or null (Resume Auto-detection)
161
+ */
162
+ setCursor(type: 'auto' | 'none' | null): void;
163
+ private init;
164
+ /**
165
+ * Starts the update loop and enables input listeners.
166
+ * Hides the native cursor if configured.
167
+ */
168
+ enable(): void;
169
+ /**
170
+ * Stops the update loop, disables listeners, and restores the native cursor.
171
+ * Resets internal state positions to off-screen.
172
+ */
173
+ disable(): void;
174
+ /**
175
+ * Registers a new plugin.
176
+ *
177
+ * @remarks
178
+ * Plugins are sorted by `priority` immediately after registration.
179
+ * - **Negative Priority (< 0)**: Logic plugins (run before physics).
180
+ * - **Positive Priority (>= 0)**: Visual plugins (run after physics).
181
+ *
182
+ * @param plugin - The plugin object to install.
183
+ */
184
+ use(plugin: SupermousePlugin): this;
185
+ private resetPosition;
186
+ private startLoop;
187
+ /**
188
+ * Manually steps the animation loop.
189
+ * Useful when integrating with external game loops (e.g., Three.js, PixiJS) where
190
+ * you want to disable the internal RAF and drive `Supermouse` from your own ticker.
191
+ *
192
+ * @param time Current timestamp in milliseconds.
193
+ */
194
+ step(time: number): void;
195
+ private runPluginSafe;
196
+ /**
197
+ * The Heartbeat.
198
+ * Runs on every animation frame.
199
+ */
200
+ private tick;
201
+ /**
202
+ * Destroys the instance.
203
+ * Stops the loop, removes all DOM elements, removes all event listeners, and calls destroy on all plugins.
204
+ */
205
+ destroy(): void;
206
+ }
207
+
208
+ /**
209
+ * Configuration options passed to the Supermouse constructor.
210
+ */
211
+ export declare interface SupermouseOptions {
212
+ /**
213
+ * The interpolation factor (0 to 1). Lower is smoother/slower.
214
+ * @default 0.15
215
+ */
216
+ smoothness?: number;
217
+ /**
218
+ * List of CSS selectors that trigger the "Hover" state.
219
+ * Overrides the default set if provided.
220
+ */
221
+ hoverSelectors?: string[];
222
+ /**
223
+ * Whether to enable custom cursor effects on touch devices.
224
+ * @default false
225
+ */
226
+ enableTouch?: boolean;
227
+ /**
228
+ * Whether to automatically disable the custom cursor on devices with coarse pointers.
229
+ * @default true
230
+ */
231
+ autoDisableOnMobile?: boolean;
232
+ /**
233
+ * Strategy for detecting when to fallback to the native cursor.
234
+ * - `true` / `'auto'`: Checks both HTML tags and CSS cursor styles (Accurate but slower).
235
+ * - `'tag'`: Checks only semantic tags like <input>, <textarea> (Fastest, prevents layout thrashing).
236
+ * - `'css'`: Checks only computed CSS cursor styles (Slow, triggers reflow).
237
+ * - `false`: Never fallback to native cursor.
238
+ * @default 'auto'
239
+ */
240
+ ignoreOnNative?: boolean | NativeIgnoreStrategy;
241
+ /**
242
+ * Whether to hide the native cursor via global CSS injection.
243
+ * @default true
244
+ */
245
+ hideCursor?: boolean;
246
+ /**
247
+ * Whether to hide the custom cursor when the mouse leaves the browser window.
248
+ * @default true
249
+ */
250
+ hideOnLeave?: boolean;
251
+ /**
252
+ * List of plugins to initialize with the instance.
253
+ */
254
+ plugins?: SupermousePlugin[];
255
+ /**
256
+ * The DOM element to append the cursor stage to.
257
+ * @default document.body
258
+ */
259
+ container?: HTMLElement;
260
+ /**
261
+ * Whether to start the internal animation loop automatically.
262
+ * @default true
263
+ */
264
+ autoStart?: boolean;
265
+ /**
266
+ * Semantic rules mapping CSS selectors to interaction state.
267
+ * @example { 'button': { icon: 'pointer' } }
268
+ */
269
+ rules?: Record<string, InteractionState>;
270
+ /**
271
+ * Custom strategy to resolve interaction state from a hovered element.
272
+ * Overrides the default data-attribute scraping.
273
+ */
274
+ resolveInteraction?: (target: HTMLElement) => InteractionState;
275
+ }
276
+
277
+ /**
278
+ * Interface for defining a Supermouse Plugin.
279
+ */
280
+ export declare interface SupermousePlugin {
281
+ /** Unique name for the plugin. Used for toggling/retrieval. */
282
+ name: string;
283
+ /** Execution priority. Lower numbers run first. */
284
+ priority?: number;
285
+ /** If false, update() will not be called. */
286
+ isEnabled?: boolean;
287
+ /** Called when `app.use()` is executed. */
288
+ install?: (instance: Supermouse) => void;
289
+ /** Called on every animation frame. */
290
+ update?: (instance: Supermouse, deltaTime: number) => void;
291
+ /** Called when the plugin is removed or the app is destroyed. */
292
+ destroy?: (instance: Supermouse) => void;
293
+ /** Called when the plugin is enabled via .enablePlugin() */
294
+ onEnable?: (instance: Supermouse) => void;
295
+ /** Called when the plugin is disabled via .disablePlugin() */
296
+ onDisable?: (instance: Supermouse) => void;
297
+ }
298
+
299
+ /**
300
+ * Helper type: Allows a property to be a static value OR a function that returns the value based on state.
301
+ */
302
+ export declare type ValueOrGetter<T> = T | ((state: MouseState) => T);
303
+
304
+ export { }