@buildwithdarsh/mousepadjs 1.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/README.md ADDED
@@ -0,0 +1,122 @@
1
+ > This project is made with the help of Claude (1M context).
2
+
3
+ <div align="center">
4
+
5
+ <br />
6
+
7
+ <img src="https://img.shields.io/badge/mousepadjs-v1.0.0-2997ff?style=for-the-badge&labelColor=000000" alt="version" />
8
+ <img src="https://img.shields.io/badge/gzip-~2.9KB-30d158?style=for-the-badge&labelColor=000000" alt="gzip" />
9
+ <img src="https://img.shields.io/badge/dependencies-0-bf5af2?style=for-the-badge&labelColor=000000" alt="deps" />
10
+ <img src="https://img.shields.io/badge/license-MIT-ff9f0a?style=for-the-badge&labelColor=000000" alt="license" />
11
+
12
+ <br /><br />
13
+
14
+ # MousePadJS
15
+
16
+ **Pointer intelligence for the web.**
17
+
18
+ Gestures, cursor effects, and trackpad smarts — unified across mouse, touch, pen, and trackpad. Tiny, TypeScript-first.
19
+
20
+ </div>
21
+
22
+ ---
23
+
24
+ ## Why MousePadJS?
25
+
26
+ Hammer.js is abandoned. interact.js is heavy. use-gesture is React-only. Modern apps need a tiny, framework-agnostic library built on Pointer Events that just handles the full input picture — including trackpad nuance like pinch-to-zoom and mouse-vs-trackpad detection.
27
+
28
+ `MousePadJS` does that in 2.9KB, zero deps.
29
+
30
+ ---
31
+
32
+ ## Quick Start
33
+
34
+ ```bash
35
+ npm install @buildwithdarsh/mousepadjs
36
+ ```
37
+
38
+ ```ts
39
+ import MousePad from '@buildwithdarsh/mousepadjs';
40
+
41
+ MousePad.init();
42
+
43
+ // Gestures — works on mouse, trackpad, touch, and pen
44
+ const g = MousePad.gesture(card);
45
+ g.on('tap', (e) => console.log(e.x, e.y));
46
+ g.on('doubletap', (e) => zoomIn(e));
47
+ g.on('longpress', (e) => showMenu(e));
48
+ g.on('swipe', (e) => console.log(e.direction));
49
+ g.on('pan', (e) => translate(e.dx, e.dy));
50
+ g.on('pinch', (e) => setScale(e.scale));
51
+ g.on('rotate', (e) => setAngle(e.angle));
52
+
53
+ // Cursor effects
54
+ MousePad.magnet(btn, { range: 120, strength: 0.4 });
55
+ MousePad.tilt(card, { max: 15, scale: 1.04 });
56
+ MousePad.follow(cursor, { ease: 0.15 });
57
+
58
+ // Global cursor tracker
59
+ MousePad.cursor.on('move', ({ x, y, speed }) => ...);
60
+ MousePad.cursor.on('idle', () => hideChrome());
61
+ MousePad.cursor.on('active', () => showChrome());
62
+
63
+ // Trackpad detection
64
+ MousePad.trackpad.on('pinch', ({ dy }) => zoom(dy));
65
+ if (MousePad.trackpad.isTrackpad) enableSmoothScroll();
66
+ ```
67
+
68
+ ---
69
+
70
+ ## API
71
+
72
+ ### Gestures — `MousePad.gesture(el, opts?)`
73
+
74
+ Unified recognizer for a single element. Returns a `Gesture` instance with an event emitter.
75
+
76
+ | Event | Fires when | Payload |
77
+ |---|---|---|
78
+ | `tap` | Quick press & release | `{ x, y, pointerType }` |
79
+ | `doubletap` | Two taps within 300ms | same as tap |
80
+ | `longpress` | Held still ≥ 500ms | `{ x, y, duration, pointerType }` |
81
+ | `pan` | Drag movement | `{ dx, dy, tx, ty, vx, vy, speed }` |
82
+ | `swipe` | Fast pan + release | `{ direction, distance, velocity, duration }` |
83
+ | `pinch` | Two-finger zoom | `{ scale, center }` |
84
+ | `rotate` | Two-finger rotate | `{ angle, center }` |
85
+
86
+ Options: `tapMaxDistance`, `tapMaxDuration`, `doubleTapMaxGap`, `longPressDuration`, `swipeMinVelocity`, `swipeMinDistance`.
87
+
88
+ ### Cursor tracker — `MousePad.cursor`
89
+
90
+ | Event | Payload |
91
+ |---|---|
92
+ | `move` | `{ x, y, vx, vy, speed }` |
93
+ | `idle` | — |
94
+ | `active` | — |
95
+
96
+ Properties: `x`, `y`, `vx`, `vy`, `speed`, `idle`. Method: `setIdleTimeout(ms)`.
97
+
98
+ ### Cursor effects
99
+
100
+ | Helper | What it does |
101
+ |---|---|
102
+ | `MousePad.magnet(el, opts)` | Pulls element toward cursor when within `range`. |
103
+ | `MousePad.follow(el, opts)` | Element follows cursor with easing. |
104
+ | `MousePad.tilt(el, opts)` | 3D tilt-on-hover inside the element's own box. |
105
+
106
+ All helpers return a destroy function.
107
+
108
+ ### Trackpad — `MousePad.trackpad`
109
+
110
+ | Event | Payload |
111
+ |---|---|
112
+ | `wheel` | `{ dx, dy, kind, pinch: false }` |
113
+ | `pinch` | `{ dx, dy, kind, pinch: true }` (ctrl+wheel = trackpad pinch) |
114
+ | `kind` | `'mouse' \| 'trackpad' \| 'touch' \| 'unknown'` |
115
+
116
+ Properties: `kind`, `isTrackpad`, `isMouse`.
117
+
118
+ ---
119
+
120
+ ## License
121
+
122
+ MIT © Darsh Gupta
@@ -0,0 +1,204 @@
1
+ interface GestureOptions {
2
+ tapMaxDistance?: number;
3
+ tapMaxDuration?: number;
4
+ doubleTapMaxGap?: number;
5
+ longPressDuration?: number;
6
+ swipeMinVelocity?: number;
7
+ swipeMinDistance?: number;
8
+ }
9
+ type GestureEventName = 'tap' | 'doubletap' | 'longpress' | 'panstart' | 'pan' | 'panend' | 'swipe' | 'pinchstart' | 'pinch' | 'pinchend' | 'rotatestart' | 'rotate' | 'rotateend';
10
+ interface TapEvent {
11
+ x: number;
12
+ y: number;
13
+ pointerType: string;
14
+ }
15
+ interface DoubleTapEvent extends TapEvent {
16
+ }
17
+ interface LongPressEvent extends TapEvent {
18
+ duration: number;
19
+ }
20
+ interface PanEvent {
21
+ x: number;
22
+ y: number;
23
+ dx: number;
24
+ dy: number;
25
+ tx: number;
26
+ ty: number;
27
+ vx: number;
28
+ vy: number;
29
+ speed: number;
30
+ pointerType: string;
31
+ }
32
+ interface SwipeEvent {
33
+ direction: 'left' | 'right' | 'up' | 'down';
34
+ distance: number;
35
+ velocity: number;
36
+ duration: number;
37
+ pointerType: string;
38
+ }
39
+ interface PinchEvent {
40
+ scale: number;
41
+ delta: number;
42
+ center: {
43
+ x: number;
44
+ y: number;
45
+ };
46
+ }
47
+ interface RotateEvent {
48
+ angle: number;
49
+ delta: number;
50
+ center: {
51
+ x: number;
52
+ y: number;
53
+ };
54
+ }
55
+ /**
56
+ * Unified gesture recognizer for an element. Backed by Pointer Events —
57
+ * one API across mouse, trackpad, touch, and pen.
58
+ */
59
+ declare class Gesture {
60
+ private _el;
61
+ private _ev;
62
+ private _pointers;
63
+ private _opts;
64
+ private _longPressTimer;
65
+ private _lastTapAt;
66
+ private _lastTapX;
67
+ private _lastTapY;
68
+ private _panActive;
69
+ private _pinchStart;
70
+ private _rotateStart;
71
+ private _pinchActive;
72
+ private _rotateActive;
73
+ private _onDown;
74
+ private _onMove;
75
+ private _onUp;
76
+ constructor(_el: Element, opts?: GestureOptions);
77
+ on(event: GestureEventName, fn: (e: any) => void): () => void;
78
+ destroy(): void;
79
+ private _handleDown;
80
+ private _handleMove;
81
+ private _handleUp;
82
+ }
83
+
84
+ /**
85
+ * Global cursor tracker — tracks last known position, velocity, and idle state.
86
+ * One instance per page; emits 'move', 'idle', 'active' events.
87
+ */
88
+ declare class Cursor {
89
+ private _ev;
90
+ private _x;
91
+ private _y;
92
+ private _vx;
93
+ private _vy;
94
+ private _lastX;
95
+ private _lastY;
96
+ private _lastT;
97
+ private _idle;
98
+ private _idleTimer;
99
+ private _idleDuration;
100
+ private _started;
101
+ private _onMove;
102
+ constructor();
103
+ start(): void;
104
+ stop(): void;
105
+ get x(): number;
106
+ get y(): number;
107
+ get vx(): number;
108
+ get vy(): number;
109
+ get speed(): number;
110
+ get idle(): boolean;
111
+ on(event: 'move' | 'idle' | 'active', fn: (...args: any[]) => void): () => void;
112
+ /** Set idle threshold in ms. Default 2000. */
113
+ setIdleTimeout(ms: number): void;
114
+ private _handle;
115
+ private _resetIdle;
116
+ }
117
+
118
+ interface MagnetOptions {
119
+ /** Max distance (px) at which the magnet engages. Default 120. */
120
+ range?: number;
121
+ /** How strongly the element is pulled toward the cursor. 0–1. Default 0.35. */
122
+ strength?: number;
123
+ /** Easing factor per frame. Lower = smoother. Default 0.18. */
124
+ ease?: number;
125
+ }
126
+
127
+ interface FollowOptions {
128
+ /** Easing factor (0–1). Lower = smoother lag. Default 0.18. */
129
+ ease?: number;
130
+ /** Lock to cursor with no lag. Default false. */
131
+ instant?: boolean;
132
+ /** Offset from cursor position. */
133
+ offset?: {
134
+ x: number;
135
+ y: number;
136
+ };
137
+ }
138
+
139
+ interface TiltOptions {
140
+ /** Max rotation in degrees. Default 12. */
141
+ max?: number;
142
+ /** Scale factor while tilted. Default 1.03. */
143
+ scale?: number;
144
+ /** Perspective distance in px. Default 800. */
145
+ perspective?: number;
146
+ /** Easing on entering tilt. Lower = smoother. Default 0.18. */
147
+ ease?: number;
148
+ }
149
+
150
+ type InputKind = 'mouse' | 'trackpad' | 'touch' | 'unknown';
151
+ interface WheelInfo {
152
+ dx: number;
153
+ dy: number;
154
+ kind: InputKind;
155
+ /** True if the user is pinch-zooming on a trackpad (ctrlKey + wheel). */
156
+ pinch: boolean;
157
+ }
158
+ /**
159
+ * Heuristic trackpad detection + normalized wheel stream.
160
+ *
161
+ * Detection heuristic:
162
+ * - `deltaMode === 0` (pixel) with small non-integer deltas → trackpad
163
+ * - `deltaMode === 1` (line) → mouse wheel
164
+ * - `ctrlKey + wheel` → trackpad pinch-to-zoom (Safari/Chrome)
165
+ */
166
+ declare class Trackpad {
167
+ private _ev;
168
+ private _kind;
169
+ private _started;
170
+ private _onWheel;
171
+ constructor();
172
+ start(target?: EventTarget): void;
173
+ stop(target?: EventTarget): void;
174
+ get kind(): InputKind;
175
+ get isTrackpad(): boolean;
176
+ get isMouse(): boolean;
177
+ on(event: 'wheel' | 'pinch' | 'kind', fn: (...args: any[]) => void): () => void;
178
+ private _handle;
179
+ }
180
+
181
+ declare class MousePad {
182
+ private _cursor;
183
+ private _trackpad;
184
+ private _initialized;
185
+ /** Start tracking the cursor and trackpad globally. */
186
+ init(): void;
187
+ destroy(): void;
188
+ /** Attach a gesture recognizer to an element. */
189
+ gesture(el: Element, opts?: GestureOptions): Gesture;
190
+ /** Global cursor tracker (position, velocity, idle). */
191
+ get cursor(): Cursor;
192
+ /** Trackpad detector + wheel stream. */
193
+ get trackpad(): Trackpad;
194
+ /** Make an element magnetically attracted to the cursor. */
195
+ magnet(el: HTMLElement, opts?: MagnetOptions): () => void;
196
+ /** Make an element follow the cursor with optional easing. */
197
+ follow(el: HTMLElement, opts?: FollowOptions): () => void;
198
+ /** Add a 3D tilt-on-hover effect to an element. */
199
+ tilt(el: HTMLElement, opts?: TiltOptions): () => void;
200
+ }
201
+ declare const mousepad: MousePad;
202
+
203
+ export { Cursor, Gesture, Trackpad, mousepad as default };
204
+ export type { DoubleTapEvent, FollowOptions, GestureEventName, GestureOptions, InputKind, LongPressEvent, MagnetOptions, PanEvent, PinchEvent, RotateEvent, SwipeEvent, TapEvent, TiltOptions, WheelInfo };
@@ -0,0 +1,2 @@
1
+ class t{t=new Map;on(t,i){let s=this.t.get(t);return s||(s=new Set,this.t.set(t,s)),s.add(i),()=>this.off(t,i)}off(t,i){i?this.t.get(t)?.delete(i):this.t.delete(t)}emit(t,...i){const s=this.t.get(t);if(s)for(const t of s)try{t(...i)}catch(t){console.error("[mousepad.js]",t)}}}function i(t,i){return Math.hypot(t.x-i.x,t.y-i.y)}const s={tapMaxDistance:10,tapMaxDuration:250,doubleTapMaxGap:300,longPressDuration:500,swipeMinVelocity:300,swipeMinDistance:30};class e{i;h=new t;o=new Map;p;l=0;u=0;m=0;_=0;v=!1;M=0;T=0;A=!1;k=!1;F;$;D;constructor(t,i){this.i=t,this.p={...s,...i},this.F=t=>this.q(t),this.$=t=>this.X(t),this.D=t=>this.Y(t),t.addEventListener("pointerdown",this.F),t.addEventListener("pointermove",this.$),t.addEventListener("pointerup",this.D),t.addEventListener("pointercancel",this.D)}on(t,i){return this.h.on(t,i)}destroy(){this.i.removeEventListener("pointerdown",this.F),this.i.removeEventListener("pointermove",this.$),this.i.removeEventListener("pointerup",this.D),this.i.removeEventListener("pointercancel",this.D),this.l&&clearTimeout(this.l),this.o.clear()}q(t){t.target.setPointerCapture?.(t.pointerId);const s={id:t.pointerId,startX:t.clientX,startY:t.clientY,startTime:performance.now(),lastX:t.clientX,lastY:t.clientY,lastTime:performance.now(),pointerType:t.pointerType};if(this.o.set(t.pointerId,s),1===this.o.size&&(this.l=window.setTimeout(()=>{const s=this.o.get(t.pointerId);s&&i({x:s.startX,y:s.startY},{x:s.lastX,y:s.lastY})<=this.p.tapMaxDistance&&this.h.emit("longpress",{x:s.startX,y:s.startY,duration:performance.now()-s.startTime,pointerType:s.pointerType})},this.p.longPressDuration)),2===this.o.size){const[t,s]=Array.from(this.o.values());this.M=i({x:t.startX,y:t.startY},{x:s.startX,y:s.startY}),this.T=Math.atan2(s.startY-t.startY,s.startX-t.startX),this.A=!0,this.k=!0;const e={x:(t.startX+s.startX)/2,y:(t.startY+s.startY)/2};this.h.emit("pinchstart",{scale:1,delta:0,center:e}),this.h.emit("rotatestart",{angle:0,delta:0,center:e})}}X(t){const s=this.o.get(t.pointerId);if(!s)return;const e=performance.now(),n=(e-s.lastTime)/1e3,h=t.clientX-s.lastX,r=t.clientY-s.lastY;if(s.lastX=t.clientX,s.lastY=t.clientY,s.lastTime=e,1===this.o.size){const i=t.clientX-s.startX,e=t.clientY-s.startY;if(Math.hypot(i,e)>this.p.tapMaxDistance&&!this.v&&(this.v=!0,this.l&&(clearTimeout(this.l),this.l=0),this.h.emit("panstart",{x:t.clientX,y:t.clientY,dx:0,dy:0,tx:i,ty:e,vx:0,vy:0,speed:0,pointerType:s.pointerType})),this.v){const o=n>0?h/n:0,a=n>0?r/n:0;this.h.emit("pan",{x:t.clientX,y:t.clientY,dx:h,dy:r,tx:i,ty:e,vx:o,vy:a,speed:Math.hypot(o,a),pointerType:s.pointerType})}return}if(2===this.o.size){const[t,s]=Array.from(this.o.values()),e=i({x:t.lastX,y:t.lastY},{x:s.lastX,y:s.lastY}),n=Math.atan2(s.lastY-t.lastY,s.lastX-t.lastX),h={x:(t.lastX+s.lastX)/2,y:(t.lastY+s.lastY)/2};this.h.emit("pinch",{scale:this.M>0?e/this.M:1,delta:0,center:h}),this.h.emit("rotate",{angle:n-this.T,delta:0,center:h})}}Y(t){const s=this.o.get(t.pointerId);if(!s)return;this.o.delete(t.pointerId),this.l&&(clearTimeout(this.l),this.l=0);const e=performance.now(),n=e-s.startTime,h=s.lastX-s.startX,r=s.lastY-s.startY,o=Math.hypot(h,r);if(this.v){this.v=!1;const t=n/1e3,i=t>0?h/t:0,e=t>0?r/t:0;this.h.emit("panend",{x:s.lastX,y:s.lastY,dx:0,dy:0,tx:h,ty:r,vx:i,vy:e,speed:Math.hypot(i,e),pointerType:s.pointerType});const a=Math.hypot(i,e);if(a>=this.p.swipeMinVelocity&&o>=this.p.swipeMinDistance){const t=function(t,i,s=10){return Math.hypot(t,i)<s?"":Math.abs(t)>Math.abs(i)?t>0?"right":"left":i>0?"down":"up"}(h,r,this.p.swipeMinDistance);t&&this.h.emit("swipe",{direction:t,distance:o,velocity:a,duration:n,pointerType:s.pointerType})}}else if(o<=this.p.tapMaxDistance&&n<=this.p.tapMaxDuration){const t=e-this.u,n=i({x:s.startX,y:s.startY},{x:this.m,y:this._})<=3*this.p.tapMaxDistance;t<=this.p.doubleTapMaxGap&&n?(this.h.emit("doubletap",{x:s.startX,y:s.startY,pointerType:s.pointerType}),this.u=0):(this.h.emit("tap",{x:s.startX,y:s.startY,pointerType:s.pointerType}),this.u=e,this.m=s.startX,this._=s.startY)}this.o.size<2&&(this.A&&(this.A=!1,this.h.emit("pinchend",{scale:1,delta:0,center:{x:s.lastX,y:s.lastY}})),this.k&&(this.k=!1,this.h.emit("rotateend",{angle:0,delta:0,center:{x:s.lastX,y:s.lastY}})))}}class n{h=new t;S=0;I=0;P=0;U=0;j=0;G=0;K=0;V=!1;W=0;B=2e3;C=!1;$;constructor(){this.$=t=>this.H(t)}start(){this.C||(this.C=!0,window.addEventListener("pointermove",this.$,{passive:!0}))}stop(){window.removeEventListener("pointermove",this.$),this.C=!1}get x(){return this.S}get y(){return this.I}get vx(){return this.P}get vy(){return this.U}get speed(){return Math.hypot(this.P,this.U)}get idle(){return this.V}on(t,i){return this.h.on(t,i)}setIdleTimeout(t){this.B=t,this.J()}H(t){const i=performance.now(),s=(i-this.K)/1e3;this.S=t.clientX,this.I=t.clientY,s>0&&s<.2?(this.P=(this.S-this.j)/s,this.U=(this.I-this.G)/s):(this.P=0,this.U=0),this.j=this.S,this.G=this.I,this.K=i,this.h.emit("move",{x:this.S,y:this.I,vx:this.P,vy:this.U,speed:this.speed}),this.V&&(this.V=!1,this.h.emit("active")),this.J()}J(){this.W&&clearTimeout(this.W),this.W=window.setTimeout(()=>{this.V=!0,this.h.emit("idle")},this.B)}}const h={range:120,strength:.35,ease:.18};class r{h=new t;L="unknown";C=!1;N;constructor(){this.N=t=>this.H(t)}start(t=window){this.C||(this.C=!0,t.addEventListener("wheel",this.N,{passive:!1}))}stop(t=window){t.removeEventListener("wheel",this.N),this.C=!1}get kind(){return this.L}get isTrackpad(){return"trackpad"===this.L}get isMouse(){return"mouse"===this.L}on(t,i){return this.h.on(t,i)}H(t){const{deltaX:i,deltaY:s,deltaMode:e,ctrlKey:n}=t,h=n;let r=this.L;if(1===e)r="mouse";else if(0===e){const t=Math.max(Math.abs(i),Math.abs(s));t>0&&t<50&&t!==Math.floor(t)||t>0&&t<20?r="trackpad":t>=100&&t%100==0&&(r="mouse")}r!==this.L&&"unknown"!==r&&(this.L=r,this.h.emit("kind",r));this.h.emit(h?"pinch":"wheel",{dx:i,dy:s,kind:this.L,pinch:h})}}const o=new class{O=new n;R=new r;Z=!1;init(){this.Z||(this.O.start(),this.R.start(),this.Z=!0)}destroy(){this.O.stop(),this.R.stop(),this.Z=!1}gesture(t,i){return new e(t,i)}get cursor(){return this.O}get trackpad(){return this.R}magnet(t,i){return this.Z||this.init(),function(t,i,s){const e={...h,...s};let n=0,r=0,o=0,a=0,c=0,p=!1;return c=requestAnimationFrame(function s(){if(p)return;const h=t.getBoundingClientRect(),l=i.x-(h.left+h.width/2),u=i.y-(h.top+h.height/2),d=Math.hypot(l,u);if(d<e.range){const t=(1-d/e.range)*e.strength;n=l*t,r=u*t}else n=0,r=0;o+=(n-o)*e.ease,a+=(r-a)*e.ease,t.style.transform=`translate(${o.toFixed(2)}px, ${a.toFixed(2)}px)`,c=requestAnimationFrame(s)}),()=>{p=!0,c&&cancelAnimationFrame(c),t.style.transform=""}}(t,this.O,i)}follow(t,i){return this.Z||this.init(),function(t,i,s){const e=s?.ease??.18,n=s?.instant??!1,h=s?.offset?.x??0,r=s?.offset?.y??0;let o=i.x,a=i.y,c=0,p=!1;return c=requestAnimationFrame(function s(){p||(n?(o=i.x,a=i.y):(o+=(i.x-o)*e,a+=(i.y-a)*e),t.style.transform=`translate(${(o+h).toFixed(2)}px, ${(a+r).toFixed(2)}px)`,c=requestAnimationFrame(s))}),()=>{p=!0,c&&cancelAnimationFrame(c)}}(t,this.O,i)}tilt(t,i){return function(t,i){const s=i?.max??12,e=i?.scale??1.03,n=i?.perspective??800,h=i?.ease??.18;let r=0,o=0,a=1,c=0,p=0,l=1,u=!1,d=0,y=!1;function m(){u=!0,a=e}function x(){u=!1,r=0,o=0,a=1}function _(i){if(!u)return;const e=t.getBoundingClientRect();r=-((i.clientY-e.top)/e.height-.5)*s*2,o=((i.clientX-e.left)/e.width-.5)*s*2}return t.addEventListener("pointerenter",m),t.addEventListener("pointerleave",x),t.addEventListener("pointermove",_),t.style.transformStyle="preserve-3d",t.style.willChange="transform",d=requestAnimationFrame(function i(){y||(c+=(r-c)*h,p+=(o-p)*h,l+=(a-l)*h,t.style.transform=`perspective(${n}px) rotateX(${c.toFixed(2)}deg) rotateY(${p.toFixed(2)}deg) scale(${l.toFixed(3)})`,d=requestAnimationFrame(i))}),()=>{y=!0,d&&cancelAnimationFrame(d),t.removeEventListener("pointerenter",m),t.removeEventListener("pointerleave",x),t.removeEventListener("pointermove",_),t.style.transform=""}}(t,i)}};export{o as default};
2
+ //# sourceMappingURL=mousepad.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mousepad.esm.js","sources":["../src/events/events.ts","../src/utils/vector.ts","../src/gestures/gesture.ts","../src/cursor/cursor.ts","../src/cursor/magnet.ts","../src/trackpad/trackpad.ts","../src/index.ts","../src/cursor/follow.ts","../src/cursor/tilt.ts"],"sourcesContent":["type Listener = (...args: any[]) => void;\n\nexport class Emitter {\n private _map = new Map<string, Set<Listener>>();\n\n on(event: string, fn: Listener): () => void {\n let set = this._map.get(event);\n if (!set) { set = new Set(); this._map.set(event, set); }\n set.add(fn);\n return () => this.off(event, fn);\n }\n\n off(event: string, fn?: Listener): void {\n if (!fn) { this._map.delete(event); return; }\n this._map.get(event)?.delete(fn);\n }\n\n emit(event: string, ...args: any[]): void {\n const set = this._map.get(event);\n if (!set) return;\n for (const fn of set) {\n try { fn(...args); } catch (e) { console.error('[mousepad.js]', e); }\n }\n }\n}\n","export interface Vec2 {\n x: number;\n y: number;\n}\n\nexport function sub(a: Vec2, b: Vec2): Vec2 {\n return { x: a.x - b.x, y: a.y - b.y };\n}\n\nexport function length(a: Vec2): number {\n return Math.hypot(a.x, a.y);\n}\n\nexport function distance(a: Vec2, b: Vec2): number {\n return Math.hypot(a.x - b.x, a.y - b.y);\n}\n\nexport function angle(from: Vec2, to: Vec2): number {\n return Math.atan2(to.y - from.y, to.x - from.x);\n}\n\n/** Cardinal direction for a delta vector. Returns '' for small movement. */\nexport function direction(dx: number, dy: number, threshold = 10): '' | 'left' | 'right' | 'up' | 'down' {\n if (Math.hypot(dx, dy) < threshold) return '';\n if (Math.abs(dx) > Math.abs(dy)) return dx > 0 ? 'right' : 'left';\n return dy > 0 ? 'down' : 'up';\n}\n\nexport function lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t;\n}\n\nexport function clamp(v: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, v));\n}\n","import { Emitter } from '../events/events';\nimport { direction as dirOf, distance } from '../utils/vector';\n\nexport interface GestureOptions {\n tapMaxDistance?: number;\n tapMaxDuration?: number;\n doubleTapMaxGap?: number;\n longPressDuration?: number;\n swipeMinVelocity?: number;\n swipeMinDistance?: number;\n}\n\nexport type GestureEventName =\n | 'tap'\n | 'doubletap'\n | 'longpress'\n | 'panstart'\n | 'pan'\n | 'panend'\n | 'swipe'\n | 'pinchstart'\n | 'pinch'\n | 'pinchend'\n | 'rotatestart'\n | 'rotate'\n | 'rotateend';\n\nexport interface TapEvent { x: number; y: number; pointerType: string }\nexport interface DoubleTapEvent extends TapEvent {}\nexport interface LongPressEvent extends TapEvent { duration: number }\nexport interface PanEvent {\n x: number; y: number;\n dx: number; dy: number; // delta since last event\n tx: number; ty: number; // total delta since panstart\n vx: number; vy: number; // velocity px/sec\n speed: number;\n pointerType: string;\n}\nexport interface SwipeEvent {\n direction: 'left' | 'right' | 'up' | 'down';\n distance: number;\n velocity: number;\n duration: number;\n pointerType: string;\n}\nexport interface PinchEvent {\n scale: number; // relative to gesture start\n delta: number; // relative to last event\n center: { x: number; y: number };\n}\nexport interface RotateEvent {\n angle: number; // total radians since rotatestart\n delta: number; // radians since last event\n center: { x: number; y: number };\n}\n\nconst DEFAULTS: Required<GestureOptions> = {\n tapMaxDistance: 10,\n tapMaxDuration: 250,\n doubleTapMaxGap: 300,\n longPressDuration: 500,\n swipeMinVelocity: 300,\n swipeMinDistance: 30,\n};\n\ninterface Tracker {\n id: number;\n startX: number;\n startY: number;\n startTime: number;\n lastX: number;\n lastY: number;\n lastTime: number;\n pointerType: string;\n}\n\n/**\n * Unified gesture recognizer for an element. Backed by Pointer Events —\n * one API across mouse, trackpad, touch, and pen.\n */\nexport class Gesture {\n private _ev = new Emitter();\n private _pointers = new Map<number, Tracker>();\n private _opts: Required<GestureOptions>;\n\n private _longPressTimer = 0;\n private _lastTapAt = 0;\n private _lastTapX = 0;\n private _lastTapY = 0;\n\n private _panActive = false;\n private _pinchStart = 0;\n private _rotateStart = 0;\n private _pinchActive = false;\n private _rotateActive = false;\n\n private _onDown: (e: Event) => void;\n private _onMove: (e: Event) => void;\n private _onUp: (e: Event) => void;\n\n constructor(private _el: Element, opts?: GestureOptions) {\n this._opts = { ...DEFAULTS, ...opts };\n this._onDown = (e) => this._handleDown(e as PointerEvent);\n this._onMove = (e) => this._handleMove(e as PointerEvent);\n this._onUp = (e) => this._handleUp(e as PointerEvent);\n _el.addEventListener('pointerdown', this._onDown);\n _el.addEventListener('pointermove', this._onMove);\n _el.addEventListener('pointerup', this._onUp);\n _el.addEventListener('pointercancel', this._onUp);\n }\n\n on(event: GestureEventName, fn: (e: any) => void): () => void {\n return this._ev.on(event, fn);\n }\n\n destroy(): void {\n this._el.removeEventListener('pointerdown', this._onDown);\n this._el.removeEventListener('pointermove', this._onMove);\n this._el.removeEventListener('pointerup', this._onUp);\n this._el.removeEventListener('pointercancel', this._onUp);\n if (this._longPressTimer) clearTimeout(this._longPressTimer);\n this._pointers.clear();\n }\n\n private _handleDown(e: PointerEvent): void {\n (e.target as Element).setPointerCapture?.(e.pointerId);\n const t: Tracker = {\n id: e.pointerId,\n startX: e.clientX, startY: e.clientY,\n startTime: performance.now(),\n lastX: e.clientX, lastY: e.clientY,\n lastTime: performance.now(),\n pointerType: e.pointerType,\n };\n this._pointers.set(e.pointerId, t);\n\n // Long press fires if the pointer stays still for longPressDuration\n if (this._pointers.size === 1) {\n this._longPressTimer = window.setTimeout(() => {\n const tr = this._pointers.get(e.pointerId);\n if (!tr) return;\n const d = distance({ x: tr.startX, y: tr.startY }, { x: tr.lastX, y: tr.lastY });\n if (d <= this._opts.tapMaxDistance) {\n this._ev.emit('longpress', {\n x: tr.startX, y: tr.startY,\n duration: performance.now() - tr.startTime,\n pointerType: tr.pointerType,\n });\n }\n }, this._opts.longPressDuration);\n }\n\n // Two-finger gestures start\n if (this._pointers.size === 2) {\n const [a, b] = Array.from(this._pointers.values());\n this._pinchStart = distance({ x: a!.startX, y: a!.startY }, { x: b!.startX, y: b!.startY });\n this._rotateStart = Math.atan2(b!.startY - a!.startY, b!.startX - a!.startX);\n this._pinchActive = true; this._rotateActive = true;\n const center = { x: (a!.startX + b!.startX) / 2, y: (a!.startY + b!.startY) / 2 };\n this._ev.emit('pinchstart', { scale: 1, delta: 0, center });\n this._ev.emit('rotatestart', { angle: 0, delta: 0, center });\n }\n }\n\n private _handleMove(e: PointerEvent): void {\n const t = this._pointers.get(e.pointerId);\n if (!t) return;\n const now = performance.now();\n const dt = (now - t.lastTime) / 1000;\n const dx = e.clientX - t.lastX;\n const dy = e.clientY - t.lastY;\n t.lastX = e.clientX; t.lastY = e.clientY; t.lastTime = now;\n\n // Single pointer → pan\n if (this._pointers.size === 1) {\n const tx = e.clientX - t.startX;\n const ty = e.clientY - t.startY;\n const movedEnough = Math.hypot(tx, ty) > this._opts.tapMaxDistance;\n if (movedEnough && !this._panActive) {\n this._panActive = true;\n if (this._longPressTimer) { clearTimeout(this._longPressTimer); this._longPressTimer = 0; }\n this._ev.emit('panstart', {\n x: e.clientX, y: e.clientY,\n dx: 0, dy: 0, tx, ty, vx: 0, vy: 0, speed: 0,\n pointerType: t.pointerType,\n });\n }\n if (this._panActive) {\n const vx = dt > 0 ? dx / dt : 0;\n const vy = dt > 0 ? dy / dt : 0;\n this._ev.emit('pan', {\n x: e.clientX, y: e.clientY,\n dx, dy, tx, ty, vx, vy, speed: Math.hypot(vx, vy),\n pointerType: t.pointerType,\n });\n }\n return;\n }\n\n // Two pointers → pinch + rotate\n if (this._pointers.size === 2) {\n const [a, b] = Array.from(this._pointers.values());\n const curDist = distance({ x: a!.lastX, y: a!.lastY }, { x: b!.lastX, y: b!.lastY });\n const curAngle = Math.atan2(b!.lastY - a!.lastY, b!.lastX - a!.lastX);\n const scale = this._pinchStart > 0 ? curDist / this._pinchStart : 1;\n const center = { x: (a!.lastX + b!.lastX) / 2, y: (a!.lastY + b!.lastY) / 2 };\n this._ev.emit('pinch', { scale, delta: 0, center });\n this._ev.emit('rotate', { angle: curAngle - this._rotateStart, delta: 0, center });\n }\n }\n\n private _handleUp(e: PointerEvent): void {\n const t = this._pointers.get(e.pointerId);\n if (!t) return;\n this._pointers.delete(e.pointerId);\n if (this._longPressTimer) { clearTimeout(this._longPressTimer); this._longPressTimer = 0; }\n\n const now = performance.now();\n const duration = now - t.startTime;\n const tx = t.lastX - t.startX;\n const ty = t.lastY - t.startY;\n const totalDist = Math.hypot(tx, ty);\n\n // Pan end\n if (this._panActive) {\n this._panActive = false;\n const dt = duration / 1000;\n const vx = dt > 0 ? tx / dt : 0;\n const vy = dt > 0 ? ty / dt : 0;\n this._ev.emit('panend', {\n x: t.lastX, y: t.lastY,\n dx: 0, dy: 0, tx, ty, vx, vy, speed: Math.hypot(vx, vy),\n pointerType: t.pointerType,\n });\n\n // Swipe check\n const velocity = Math.hypot(vx, vy);\n if (velocity >= this._opts.swipeMinVelocity && totalDist >= this._opts.swipeMinDistance) {\n const dir = dirOf(tx, ty, this._opts.swipeMinDistance);\n if (dir) {\n this._ev.emit('swipe', {\n direction: dir, distance: totalDist, velocity, duration,\n pointerType: t.pointerType,\n });\n }\n }\n } else if (totalDist <= this._opts.tapMaxDistance && duration <= this._opts.tapMaxDuration) {\n // Tap\n const gap = now - this._lastTapAt;\n const near = distance({ x: t.startX, y: t.startY }, { x: this._lastTapX, y: this._lastTapY }) <= this._opts.tapMaxDistance * 3;\n if (gap <= this._opts.doubleTapMaxGap && near) {\n this._ev.emit('doubletap', { x: t.startX, y: t.startY, pointerType: t.pointerType });\n this._lastTapAt = 0;\n } else {\n this._ev.emit('tap', { x: t.startX, y: t.startY, pointerType: t.pointerType });\n this._lastTapAt = now;\n this._lastTapX = t.startX;\n this._lastTapY = t.startY;\n }\n }\n\n // Pinch/rotate end when second finger lifts\n if (this._pointers.size < 2) {\n if (this._pinchActive) { this._pinchActive = false; this._ev.emit('pinchend', { scale: 1, delta: 0, center: { x: t.lastX, y: t.lastY } }); }\n if (this._rotateActive) { this._rotateActive = false; this._ev.emit('rotateend', { angle: 0, delta: 0, center: { x: t.lastX, y: t.lastY } }); }\n }\n }\n}\n","import { Emitter } from '../events/events';\n\n/**\n * Global cursor tracker — tracks last known position, velocity, and idle state.\n * One instance per page; emits 'move', 'idle', 'active' events.\n */\nexport class Cursor {\n private _ev = new Emitter();\n private _x = 0;\n private _y = 0;\n private _vx = 0;\n private _vy = 0;\n private _lastX = 0;\n private _lastY = 0;\n private _lastT = 0;\n private _idle = false;\n private _idleTimer = 0;\n private _idleDuration = 2000;\n private _started = false;\n\n private _onMove: (e: Event) => void;\n\n constructor() {\n this._onMove = (e) => this._handle(e as PointerEvent);\n }\n\n start(): void {\n if (this._started) return;\n this._started = true;\n window.addEventListener('pointermove', this._onMove, { passive: true });\n }\n\n stop(): void {\n window.removeEventListener('pointermove', this._onMove);\n this._started = false;\n }\n\n get x(): number { return this._x; }\n get y(): number { return this._y; }\n get vx(): number { return this._vx; }\n get vy(): number { return this._vy; }\n get speed(): number { return Math.hypot(this._vx, this._vy); }\n get idle(): boolean { return this._idle; }\n\n on(event: 'move' | 'idle' | 'active', fn: (...args: any[]) => void): () => void {\n return this._ev.on(event, fn);\n }\n\n /** Set idle threshold in ms. Default 2000. */\n setIdleTimeout(ms: number): void {\n this._idleDuration = ms;\n this._resetIdle();\n }\n\n private _handle(e: PointerEvent): void {\n const now = performance.now();\n const dt = (now - this._lastT) / 1000;\n this._x = e.clientX;\n this._y = e.clientY;\n if (dt > 0 && dt < 0.2) {\n this._vx = (this._x - this._lastX) / dt;\n this._vy = (this._y - this._lastY) / dt;\n } else {\n this._vx = 0;\n this._vy = 0;\n }\n this._lastX = this._x; this._lastY = this._y; this._lastT = now;\n this._ev.emit('move', { x: this._x, y: this._y, vx: this._vx, vy: this._vy, speed: this.speed });\n\n if (this._idle) {\n this._idle = false;\n this._ev.emit('active');\n }\n this._resetIdle();\n }\n\n private _resetIdle(): void {\n if (this._idleTimer) clearTimeout(this._idleTimer);\n this._idleTimer = window.setTimeout(() => {\n this._idle = true;\n this._ev.emit('idle');\n }, this._idleDuration);\n }\n}\n","import type { Cursor } from './cursor';\n\nexport interface MagnetOptions {\n /** Max distance (px) at which the magnet engages. Default 120. */\n range?: number;\n /** How strongly the element is pulled toward the cursor. 0–1. Default 0.35. */\n strength?: number;\n /** Easing factor per frame. Lower = smoother. Default 0.18. */\n ease?: number;\n}\n\nconst DEFAULTS: Required<MagnetOptions> = {\n range: 120,\n strength: 0.35,\n ease: 0.18,\n};\n\n/**\n * Make an element magnetically attracted to the cursor when nearby.\n * Returns a destroy function.\n */\nexport function magnet(el: HTMLElement, cursor: Cursor, opts?: MagnetOptions): () => void {\n const cfg = { ...DEFAULTS, ...opts };\n let tx = 0, ty = 0; // target\n let cx = 0, cy = 0; // current\n let rafId = 0;\n let destroyed = false;\n\n function tick(): void {\n if (destroyed) return;\n const rect = el.getBoundingClientRect();\n const eCx = rect.left + rect.width / 2;\n const eCy = rect.top + rect.height / 2;\n const dx = cursor.x - eCx;\n const dy = cursor.y - eCy;\n const d = Math.hypot(dx, dy);\n\n if (d < cfg.range) {\n const pull = (1 - d / cfg.range) * cfg.strength;\n tx = dx * pull;\n ty = dy * pull;\n } else {\n tx = 0;\n ty = 0;\n }\n\n cx += (tx - cx) * cfg.ease;\n cy += (ty - cy) * cfg.ease;\n el.style.transform = `translate(${cx.toFixed(2)}px, ${cy.toFixed(2)}px)`;\n rafId = requestAnimationFrame(tick);\n }\n\n rafId = requestAnimationFrame(tick);\n return () => {\n destroyed = true;\n if (rafId) cancelAnimationFrame(rafId);\n el.style.transform = '';\n };\n}\n","import { Emitter } from '../events/events';\n\nexport type InputKind = 'mouse' | 'trackpad' | 'touch' | 'unknown';\n\nexport interface WheelInfo {\n dx: number;\n dy: number;\n kind: InputKind;\n /** True if the user is pinch-zooming on a trackpad (ctrlKey + wheel). */\n pinch: boolean;\n}\n\n/**\n * Heuristic trackpad detection + normalized wheel stream.\n *\n * Detection heuristic:\n * - `deltaMode === 0` (pixel) with small non-integer deltas → trackpad\n * - `deltaMode === 1` (line) → mouse wheel\n * - `ctrlKey + wheel` → trackpad pinch-to-zoom (Safari/Chrome)\n */\nexport class Trackpad {\n private _ev = new Emitter();\n private _kind: InputKind = 'unknown';\n private _started = false;\n private _onWheel: (e: Event) => void;\n\n constructor() {\n this._onWheel = (e) => this._handle(e as WheelEvent);\n }\n\n start(target: EventTarget = window): void {\n if (this._started) return;\n this._started = true;\n target.addEventListener('wheel', this._onWheel, { passive: false });\n }\n\n stop(target: EventTarget = window): void {\n target.removeEventListener('wheel', this._onWheel);\n this._started = false;\n }\n\n get kind(): InputKind { return this._kind; }\n get isTrackpad(): boolean { return this._kind === 'trackpad'; }\n get isMouse(): boolean { return this._kind === 'mouse'; }\n\n on(event: 'wheel' | 'pinch' | 'kind', fn: (...args: any[]) => void): () => void {\n return this._ev.on(event, fn);\n }\n\n private _handle(e: WheelEvent): void {\n const { deltaX, deltaY, deltaMode, ctrlKey } = e;\n\n // Trackpad pinch-zoom comes through as wheel with ctrlKey=true.\n // The browser intercepts it before user code unless we preventDefault.\n const pinch = ctrlKey;\n\n // Detect kind. Mouse wheels typically use deltaMode=1 (line) with larger\n // integer steps. Trackpads use deltaMode=0 (pixel) with small/fractional\n // deltas. Some mice also send deltaMode=0 but with multiples of 100.\n let kind: InputKind = this._kind;\n if (deltaMode === 1) {\n kind = 'mouse';\n } else if (deltaMode === 0) {\n const absMax = Math.max(Math.abs(deltaX), Math.abs(deltaY));\n if (absMax > 0 && absMax < 50 && absMax !== Math.floor(absMax)) kind = 'trackpad';\n else if (absMax > 0 && absMax < 20) kind = 'trackpad';\n else if (absMax >= 100 && absMax % 100 === 0) kind = 'mouse';\n }\n\n if (kind !== this._kind && kind !== 'unknown') {\n this._kind = kind;\n this._ev.emit('kind', kind);\n }\n\n const info: WheelInfo = { dx: deltaX, dy: deltaY, kind: this._kind, pinch };\n if (pinch) this._ev.emit('pinch', info);\n else this._ev.emit('wheel', info);\n }\n}\n","import { Gesture } from './gestures/gesture';\nimport type {\n GestureOptions, GestureEventName,\n TapEvent, DoubleTapEvent, LongPressEvent,\n PanEvent, SwipeEvent, PinchEvent, RotateEvent,\n} from './gestures/gesture';\nimport { Cursor } from './cursor/cursor';\nimport { magnet as magnetFn } from './cursor/magnet';\nimport type { MagnetOptions } from './cursor/magnet';\nimport { follow as followFn } from './cursor/follow';\nimport type { FollowOptions } from './cursor/follow';\nimport { tilt as tiltFn } from './cursor/tilt';\nimport type { TiltOptions } from './cursor/tilt';\nimport { Trackpad } from './trackpad/trackpad';\nimport type { InputKind, WheelInfo } from './trackpad/trackpad';\n\nclass MousePad {\n private _cursor = new Cursor();\n private _trackpad = new Trackpad();\n private _initialized = false;\n\n /** Start tracking the cursor and trackpad globally. */\n init(): void {\n if (this._initialized) return;\n this._cursor.start();\n this._trackpad.start();\n this._initialized = true;\n }\n\n destroy(): void {\n this._cursor.stop();\n this._trackpad.stop();\n this._initialized = false;\n }\n\n /** Attach a gesture recognizer to an element. */\n gesture(el: Element, opts?: GestureOptions): Gesture {\n return new Gesture(el, opts);\n }\n\n /** Global cursor tracker (position, velocity, idle). */\n get cursor(): Cursor { return this._cursor; }\n\n /** Trackpad detector + wheel stream. */\n get trackpad(): Trackpad { return this._trackpad; }\n\n /** Make an element magnetically attracted to the cursor. */\n magnet(el: HTMLElement, opts?: MagnetOptions): () => void {\n if (!this._initialized) this.init();\n return magnetFn(el, this._cursor, opts);\n }\n\n /** Make an element follow the cursor with optional easing. */\n follow(el: HTMLElement, opts?: FollowOptions): () => void {\n if (!this._initialized) this.init();\n return followFn(el, this._cursor, opts);\n }\n\n /** Add a 3D tilt-on-hover effect to an element. */\n tilt(el: HTMLElement, opts?: TiltOptions): () => void {\n return tiltFn(el, opts);\n }\n}\n\nconst mousepad = new MousePad();\nexport default mousepad;\n\nexport type {\n GestureOptions, GestureEventName,\n TapEvent, DoubleTapEvent, LongPressEvent,\n PanEvent, SwipeEvent, PinchEvent, RotateEvent,\n MagnetOptions, FollowOptions, TiltOptions,\n InputKind, WheelInfo,\n Gesture, Cursor, Trackpad,\n};\n","import type { Cursor } from './cursor';\n\nexport interface FollowOptions {\n /** Easing factor (0–1). Lower = smoother lag. Default 0.18. */\n ease?: number;\n /** Lock to cursor with no lag. Default false. */\n instant?: boolean;\n /** Offset from cursor position. */\n offset?: { x: number; y: number };\n}\n\n/**\n * Make an element follow the cursor with optional easing.\n * Element must be positioned (fixed or absolute).\n */\nexport function follow(el: HTMLElement, cursor: Cursor, opts?: FollowOptions): () => void {\n const ease = opts?.ease ?? 0.18;\n const instant = opts?.instant ?? false;\n const offX = opts?.offset?.x ?? 0;\n const offY = opts?.offset?.y ?? 0;\n\n let x = cursor.x, y = cursor.y;\n let rafId = 0;\n let destroyed = false;\n\n function tick(): void {\n if (destroyed) return;\n if (instant) {\n x = cursor.x; y = cursor.y;\n } else {\n x += (cursor.x - x) * ease;\n y += (cursor.y - y) * ease;\n }\n el.style.transform = `translate(${(x + offX).toFixed(2)}px, ${(y + offY).toFixed(2)}px)`;\n rafId = requestAnimationFrame(tick);\n }\n\n rafId = requestAnimationFrame(tick);\n return () => {\n destroyed = true;\n if (rafId) cancelAnimationFrame(rafId);\n };\n}\n","export interface TiltOptions {\n /** Max rotation in degrees. Default 12. */\n max?: number;\n /** Scale factor while tilted. Default 1.03. */\n scale?: number;\n /** Perspective distance in px. Default 800. */\n perspective?: number;\n /** Easing on entering tilt. Lower = smoother. Default 0.18. */\n ease?: number;\n}\n\n/**\n * 3D tilt-on-hover effect — the element tilts toward the cursor position\n * within its own bounding box.\n */\nexport function tilt(el: HTMLElement, opts?: TiltOptions): () => void {\n const max = opts?.max ?? 12;\n const scale = opts?.scale ?? 1.03;\n const perspective = opts?.perspective ?? 800;\n const ease = opts?.ease ?? 0.18;\n\n let tx = 0, ty = 0, sc = 1; // targets\n let cx = 0, cy = 0, cs = 1; // current\n let active = false;\n let rafId = 0;\n let destroyed = false;\n\n function onEnter() { active = true; sc = scale; }\n function onLeave() { active = false; tx = 0; ty = 0; sc = 1; }\n function onMove(e: PointerEvent) {\n if (!active) return;\n const rect = el.getBoundingClientRect();\n const px = (e.clientX - rect.left) / rect.width - 0.5;\n const py = (e.clientY - rect.top) / rect.height - 0.5;\n tx = -py * max * 2; // rotateX\n ty = px * max * 2; // rotateY\n }\n\n function tick(): void {\n if (destroyed) return;\n cx += (tx - cx) * ease;\n cy += (ty - cy) * ease;\n cs += (sc - cs) * ease;\n el.style.transform =\n `perspective(${perspective}px) rotateX(${cx.toFixed(2)}deg) rotateY(${cy.toFixed(2)}deg) scale(${cs.toFixed(3)})`;\n rafId = requestAnimationFrame(tick);\n }\n\n el.addEventListener('pointerenter', onEnter);\n el.addEventListener('pointerleave', onLeave);\n el.addEventListener('pointermove', onMove as EventListener);\n el.style.transformStyle = 'preserve-3d';\n el.style.willChange = 'transform';\n rafId = requestAnimationFrame(tick);\n\n return () => {\n destroyed = true;\n if (rafId) cancelAnimationFrame(rafId);\n el.removeEventListener('pointerenter', onEnter);\n el.removeEventListener('pointerleave', onLeave);\n el.removeEventListener('pointermove', onMove as EventListener);\n el.style.transform = '';\n };\n}\n"],"names":["Emitter","_map","Map","on","event","fn","set","this","get","Set","add","off","delete","emit","args","e","console","error","distance","a","b","Math","hypot","x","y","DEFAULTS","tapMaxDistance","tapMaxDuration","doubleTapMaxGap","longPressDuration","swipeMinVelocity","swipeMinDistance","Gesture","_el","_ev","_pointers","_opts","_longPressTimer","_lastTapAt","_lastTapX","_lastTapY","_panActive","_pinchStart","_rotateStart","_pinchActive","_rotateActive","_onDown","_onMove","_onUp","constructor","opts","_handleDown","_handleMove","_handleUp","addEventListener","destroy","removeEventListener","clearTimeout","clear","target","setPointerCapture","pointerId","t","id","startX","clientX","startY","clientY","startTime","performance","now","lastX","lastY","lastTime","pointerType","size","window","setTimeout","tr","duration","Array","from","values","atan2","center","scale","delta","angle","dt","dx","dy","tx","ty","vx","vy","speed","curDist","curAngle","totalDist","velocity","dir","threshold","abs","dirOf","direction","gap","near","Cursor","_x","_y","_vx","_vy","_lastX","_lastY","_lastT","_idle","_idleTimer","_idleDuration","_started","_handle","start","passive","stop","idle","setIdleTimeout","ms","_resetIdle","range","strength","ease","Trackpad","_kind","_onWheel","kind","isTrackpad","isMouse","deltaX","deltaY","deltaMode","ctrlKey","pinch","absMax","max","floor","mousepad","_cursor","_trackpad","_initialized","init","gesture","el","cursor","trackpad","magnet","cfg","cx","cy","rafId","destroyed","requestAnimationFrame","tick","rect","getBoundingClientRect","left","width","top","height","d","pull","style","transform","toFixed","cancelAnimationFrame","magnetFn","follow","instant","offX","offset","offY","followFn","tilt","perspective","sc","cs","active","onEnter","onLeave","onMove","transformStyle","willChange","tiltFn"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ !function(t,i){"object"==typeof exports&&"undefined"!=typeof module?module.exports=i():"function"==typeof define&&define.amd?define(i):(t="undefined"!=typeof globalThis?globalThis:t||self).MousePad=i()}(this,function(){"use strict";class t{t=new Map;on(t,i){let e=this.t.get(t);return e||(e=new Set,this.t.set(t,e)),e.add(i),()=>this.off(t,i)}off(t,i){i?this.t.get(t)?.delete(i):this.t.delete(t)}emit(t,...i){const e=this.t.get(t);if(e)for(const t of e)try{t(...i)}catch(t){console.error("[mousepad.js]",t)}}}function i(t,i){return Math.hypot(t.x-i.x,t.y-i.y)}const e={tapMaxDistance:10,tapMaxDuration:250,doubleTapMaxGap:300,longPressDuration:500,swipeMinVelocity:300,swipeMinDistance:30};class s{i;h=new t;o=new Map;p;l=0;u=0;m=0;_=0;v=!1;M=0;T=0;A=!1;k=!1;F;$;D;constructor(t,i){this.i=t,this.p={...e,...i},this.F=t=>this.q(t),this.$=t=>this.X(t),this.D=t=>this.Y(t),t.addEventListener("pointerdown",this.F),t.addEventListener("pointermove",this.$),t.addEventListener("pointerup",this.D),t.addEventListener("pointercancel",this.D)}on(t,i){return this.h.on(t,i)}destroy(){this.i.removeEventListener("pointerdown",this.F),this.i.removeEventListener("pointermove",this.$),this.i.removeEventListener("pointerup",this.D),this.i.removeEventListener("pointercancel",this.D),this.l&&clearTimeout(this.l),this.o.clear()}q(t){t.target.setPointerCapture?.(t.pointerId);const e={id:t.pointerId,startX:t.clientX,startY:t.clientY,startTime:performance.now(),lastX:t.clientX,lastY:t.clientY,lastTime:performance.now(),pointerType:t.pointerType};if(this.o.set(t.pointerId,e),1===this.o.size&&(this.l=window.setTimeout(()=>{const e=this.o.get(t.pointerId);e&&i({x:e.startX,y:e.startY},{x:e.lastX,y:e.lastY})<=this.p.tapMaxDistance&&this.h.emit("longpress",{x:e.startX,y:e.startY,duration:performance.now()-e.startTime,pointerType:e.pointerType})},this.p.longPressDuration)),2===this.o.size){const[t,e]=Array.from(this.o.values());this.M=i({x:t.startX,y:t.startY},{x:e.startX,y:e.startY}),this.T=Math.atan2(e.startY-t.startY,e.startX-t.startX),this.A=!0,this.k=!0;const s={x:(t.startX+e.startX)/2,y:(t.startY+e.startY)/2};this.h.emit("pinchstart",{scale:1,delta:0,center:s}),this.h.emit("rotatestart",{angle:0,delta:0,center:s})}}X(t){const e=this.o.get(t.pointerId);if(!e)return;const s=performance.now(),n=(s-e.lastTime)/1e3,h=t.clientX-e.lastX,r=t.clientY-e.lastY;if(e.lastX=t.clientX,e.lastY=t.clientY,e.lastTime=s,1===this.o.size){const i=t.clientX-e.startX,s=t.clientY-e.startY;if(Math.hypot(i,s)>this.p.tapMaxDistance&&!this.v&&(this.v=!0,this.l&&(clearTimeout(this.l),this.l=0),this.h.emit("panstart",{x:t.clientX,y:t.clientY,dx:0,dy:0,tx:i,ty:s,vx:0,vy:0,speed:0,pointerType:e.pointerType})),this.v){const o=n>0?h/n:0,a=n>0?r/n:0;this.h.emit("pan",{x:t.clientX,y:t.clientY,dx:h,dy:r,tx:i,ty:s,vx:o,vy:a,speed:Math.hypot(o,a),pointerType:e.pointerType})}return}if(2===this.o.size){const[t,e]=Array.from(this.o.values()),s=i({x:t.lastX,y:t.lastY},{x:e.lastX,y:e.lastY}),n=Math.atan2(e.lastY-t.lastY,e.lastX-t.lastX),h={x:(t.lastX+e.lastX)/2,y:(t.lastY+e.lastY)/2};this.h.emit("pinch",{scale:this.M>0?s/this.M:1,delta:0,center:h}),this.h.emit("rotate",{angle:n-this.T,delta:0,center:h})}}Y(t){const e=this.o.get(t.pointerId);if(!e)return;this.o.delete(t.pointerId),this.l&&(clearTimeout(this.l),this.l=0);const s=performance.now(),n=s-e.startTime,h=e.lastX-e.startX,r=e.lastY-e.startY,o=Math.hypot(h,r);if(this.v){this.v=!1;const t=n/1e3,i=t>0?h/t:0,s=t>0?r/t:0;this.h.emit("panend",{x:e.lastX,y:e.lastY,dx:0,dy:0,tx:h,ty:r,vx:i,vy:s,speed:Math.hypot(i,s),pointerType:e.pointerType});const a=Math.hypot(i,s);if(a>=this.p.swipeMinVelocity&&o>=this.p.swipeMinDistance){const t=function(t,i,e=10){return Math.hypot(t,i)<e?"":Math.abs(t)>Math.abs(i)?t>0?"right":"left":i>0?"down":"up"}(h,r,this.p.swipeMinDistance);t&&this.h.emit("swipe",{direction:t,distance:o,velocity:a,duration:n,pointerType:e.pointerType})}}else if(o<=this.p.tapMaxDistance&&n<=this.p.tapMaxDuration){const t=s-this.u,n=i({x:e.startX,y:e.startY},{x:this.m,y:this._})<=3*this.p.tapMaxDistance;t<=this.p.doubleTapMaxGap&&n?(this.h.emit("doubletap",{x:e.startX,y:e.startY,pointerType:e.pointerType}),this.u=0):(this.h.emit("tap",{x:e.startX,y:e.startY,pointerType:e.pointerType}),this.u=s,this.m=e.startX,this._=e.startY)}this.o.size<2&&(this.A&&(this.A=!1,this.h.emit("pinchend",{scale:1,delta:0,center:{x:e.lastX,y:e.lastY}})),this.k&&(this.k=!1,this.h.emit("rotateend",{angle:0,delta:0,center:{x:e.lastX,y:e.lastY}})))}}class n{h=new t;S=0;j=0;I=0;P=0;U=0;G=0;K=0;V=!1;W=0;B=2e3;C=!1;$;constructor(){this.$=t=>this.H(t)}start(){this.C||(this.C=!0,window.addEventListener("pointermove",this.$,{passive:!0}))}stop(){window.removeEventListener("pointermove",this.$),this.C=!1}get x(){return this.S}get y(){return this.j}get vx(){return this.I}get vy(){return this.P}get speed(){return Math.hypot(this.I,this.P)}get idle(){return this.V}on(t,i){return this.h.on(t,i)}setIdleTimeout(t){this.B=t,this.J()}H(t){const i=performance.now(),e=(i-this.K)/1e3;this.S=t.clientX,this.j=t.clientY,e>0&&e<.2?(this.I=(this.S-this.U)/e,this.P=(this.j-this.G)/e):(this.I=0,this.P=0),this.U=this.S,this.G=this.j,this.K=i,this.h.emit("move",{x:this.S,y:this.j,vx:this.I,vy:this.P,speed:this.speed}),this.V&&(this.V=!1,this.h.emit("active")),this.J()}J(){this.W&&clearTimeout(this.W),this.W=window.setTimeout(()=>{this.V=!0,this.h.emit("idle")},this.B)}}const h={range:120,strength:.35,ease:.18};class r{h=new t;L="unknown";C=!1;N;constructor(){this.N=t=>this.H(t)}start(t=window){this.C||(this.C=!0,t.addEventListener("wheel",this.N,{passive:!1}))}stop(t=window){t.removeEventListener("wheel",this.N),this.C=!1}get kind(){return this.L}get isTrackpad(){return"trackpad"===this.L}get isMouse(){return"mouse"===this.L}on(t,i){return this.h.on(t,i)}H(t){const{deltaX:i,deltaY:e,deltaMode:s,ctrlKey:n}=t,h=n;let r=this.L;if(1===s)r="mouse";else if(0===s){const t=Math.max(Math.abs(i),Math.abs(e));t>0&&t<50&&t!==Math.floor(t)||t>0&&t<20?r="trackpad":t>=100&&t%100==0&&(r="mouse")}r!==this.L&&"unknown"!==r&&(this.L=r,this.h.emit("kind",r));this.h.emit(h?"pinch":"wheel",{dx:i,dy:e,kind:this.L,pinch:h})}}return new class{O=new n;R=new r;Z=!1;init(){this.Z||(this.O.start(),this.R.start(),this.Z=!0)}destroy(){this.O.stop(),this.R.stop(),this.Z=!1}gesture(t,i){return new s(t,i)}get cursor(){return this.O}get trackpad(){return this.R}magnet(t,i){return this.Z||this.init(),function(t,i,e){const s={...h,...e};let n=0,r=0,o=0,a=0,c=0,p=!1;return c=requestAnimationFrame(function e(){if(p)return;const h=t.getBoundingClientRect(),l=i.x-(h.left+h.width/2),u=i.y-(h.top+h.height/2),d=Math.hypot(l,u);if(d<s.range){const t=(1-d/s.range)*s.strength;n=l*t,r=u*t}else n=0,r=0;o+=(n-o)*s.ease,a+=(r-a)*s.ease,t.style.transform=`translate(${o.toFixed(2)}px, ${a.toFixed(2)}px)`,c=requestAnimationFrame(e)}),()=>{p=!0,c&&cancelAnimationFrame(c),t.style.transform=""}}(t,this.O,i)}follow(t,i){return this.Z||this.init(),function(t,i,e){const s=e?.ease??.18,n=e?.instant??!1,h=e?.offset?.x??0,r=e?.offset?.y??0;let o=i.x,a=i.y,c=0,p=!1;return c=requestAnimationFrame(function e(){p||(n?(o=i.x,a=i.y):(o+=(i.x-o)*s,a+=(i.y-a)*s),t.style.transform=`translate(${(o+h).toFixed(2)}px, ${(a+r).toFixed(2)}px)`,c=requestAnimationFrame(e))}),()=>{p=!0,c&&cancelAnimationFrame(c)}}(t,this.O,i)}tilt(t,i){return function(t,i){const e=i?.max??12,s=i?.scale??1.03,n=i?.perspective??800,h=i?.ease??.18;let r=0,o=0,a=1,c=0,p=0,l=1,u=!1,d=0,y=!1;function f(){u=!0,a=s}function m(){u=!1,r=0,o=0,a=1}function x(i){if(!u)return;const s=t.getBoundingClientRect();r=-((i.clientY-s.top)/s.height-.5)*e*2,o=((i.clientX-s.left)/s.width-.5)*e*2}return t.addEventListener("pointerenter",f),t.addEventListener("pointerleave",m),t.addEventListener("pointermove",x),t.style.transformStyle="preserve-3d",t.style.willChange="transform",d=requestAnimationFrame(function i(){y||(c+=(r-c)*h,p+=(o-p)*h,l+=(a-l)*h,t.style.transform=`perspective(${n}px) rotateX(${c.toFixed(2)}deg) rotateY(${p.toFixed(2)}deg) scale(${l.toFixed(3)})`,d=requestAnimationFrame(i))}),()=>{y=!0,d&&cancelAnimationFrame(d),t.removeEventListener("pointerenter",f),t.removeEventListener("pointerleave",m),t.removeEventListener("pointermove",x),t.style.transform=""}}(t,i)}}});
2
+ //# sourceMappingURL=mousepad.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mousepad.umd.js","sources":["../src/events/events.ts","../src/utils/vector.ts","../src/gestures/gesture.ts","../src/cursor/cursor.ts","../src/cursor/magnet.ts","../src/trackpad/trackpad.ts","../src/index.ts","../src/cursor/follow.ts","../src/cursor/tilt.ts"],"sourcesContent":["type Listener = (...args: any[]) => void;\n\nexport class Emitter {\n private _map = new Map<string, Set<Listener>>();\n\n on(event: string, fn: Listener): () => void {\n let set = this._map.get(event);\n if (!set) { set = new Set(); this._map.set(event, set); }\n set.add(fn);\n return () => this.off(event, fn);\n }\n\n off(event: string, fn?: Listener): void {\n if (!fn) { this._map.delete(event); return; }\n this._map.get(event)?.delete(fn);\n }\n\n emit(event: string, ...args: any[]): void {\n const set = this._map.get(event);\n if (!set) return;\n for (const fn of set) {\n try { fn(...args); } catch (e) { console.error('[mousepad.js]', e); }\n }\n }\n}\n","export interface Vec2 {\n x: number;\n y: number;\n}\n\nexport function sub(a: Vec2, b: Vec2): Vec2 {\n return { x: a.x - b.x, y: a.y - b.y };\n}\n\nexport function length(a: Vec2): number {\n return Math.hypot(a.x, a.y);\n}\n\nexport function distance(a: Vec2, b: Vec2): number {\n return Math.hypot(a.x - b.x, a.y - b.y);\n}\n\nexport function angle(from: Vec2, to: Vec2): number {\n return Math.atan2(to.y - from.y, to.x - from.x);\n}\n\n/** Cardinal direction for a delta vector. Returns '' for small movement. */\nexport function direction(dx: number, dy: number, threshold = 10): '' | 'left' | 'right' | 'up' | 'down' {\n if (Math.hypot(dx, dy) < threshold) return '';\n if (Math.abs(dx) > Math.abs(dy)) return dx > 0 ? 'right' : 'left';\n return dy > 0 ? 'down' : 'up';\n}\n\nexport function lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t;\n}\n\nexport function clamp(v: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, v));\n}\n","import { Emitter } from '../events/events';\nimport { direction as dirOf, distance } from '../utils/vector';\n\nexport interface GestureOptions {\n tapMaxDistance?: number;\n tapMaxDuration?: number;\n doubleTapMaxGap?: number;\n longPressDuration?: number;\n swipeMinVelocity?: number;\n swipeMinDistance?: number;\n}\n\nexport type GestureEventName =\n | 'tap'\n | 'doubletap'\n | 'longpress'\n | 'panstart'\n | 'pan'\n | 'panend'\n | 'swipe'\n | 'pinchstart'\n | 'pinch'\n | 'pinchend'\n | 'rotatestart'\n | 'rotate'\n | 'rotateend';\n\nexport interface TapEvent { x: number; y: number; pointerType: string }\nexport interface DoubleTapEvent extends TapEvent {}\nexport interface LongPressEvent extends TapEvent { duration: number }\nexport interface PanEvent {\n x: number; y: number;\n dx: number; dy: number; // delta since last event\n tx: number; ty: number; // total delta since panstart\n vx: number; vy: number; // velocity px/sec\n speed: number;\n pointerType: string;\n}\nexport interface SwipeEvent {\n direction: 'left' | 'right' | 'up' | 'down';\n distance: number;\n velocity: number;\n duration: number;\n pointerType: string;\n}\nexport interface PinchEvent {\n scale: number; // relative to gesture start\n delta: number; // relative to last event\n center: { x: number; y: number };\n}\nexport interface RotateEvent {\n angle: number; // total radians since rotatestart\n delta: number; // radians since last event\n center: { x: number; y: number };\n}\n\nconst DEFAULTS: Required<GestureOptions> = {\n tapMaxDistance: 10,\n tapMaxDuration: 250,\n doubleTapMaxGap: 300,\n longPressDuration: 500,\n swipeMinVelocity: 300,\n swipeMinDistance: 30,\n};\n\ninterface Tracker {\n id: number;\n startX: number;\n startY: number;\n startTime: number;\n lastX: number;\n lastY: number;\n lastTime: number;\n pointerType: string;\n}\n\n/**\n * Unified gesture recognizer for an element. Backed by Pointer Events —\n * one API across mouse, trackpad, touch, and pen.\n */\nexport class Gesture {\n private _ev = new Emitter();\n private _pointers = new Map<number, Tracker>();\n private _opts: Required<GestureOptions>;\n\n private _longPressTimer = 0;\n private _lastTapAt = 0;\n private _lastTapX = 0;\n private _lastTapY = 0;\n\n private _panActive = false;\n private _pinchStart = 0;\n private _rotateStart = 0;\n private _pinchActive = false;\n private _rotateActive = false;\n\n private _onDown: (e: Event) => void;\n private _onMove: (e: Event) => void;\n private _onUp: (e: Event) => void;\n\n constructor(private _el: Element, opts?: GestureOptions) {\n this._opts = { ...DEFAULTS, ...opts };\n this._onDown = (e) => this._handleDown(e as PointerEvent);\n this._onMove = (e) => this._handleMove(e as PointerEvent);\n this._onUp = (e) => this._handleUp(e as PointerEvent);\n _el.addEventListener('pointerdown', this._onDown);\n _el.addEventListener('pointermove', this._onMove);\n _el.addEventListener('pointerup', this._onUp);\n _el.addEventListener('pointercancel', this._onUp);\n }\n\n on(event: GestureEventName, fn: (e: any) => void): () => void {\n return this._ev.on(event, fn);\n }\n\n destroy(): void {\n this._el.removeEventListener('pointerdown', this._onDown);\n this._el.removeEventListener('pointermove', this._onMove);\n this._el.removeEventListener('pointerup', this._onUp);\n this._el.removeEventListener('pointercancel', this._onUp);\n if (this._longPressTimer) clearTimeout(this._longPressTimer);\n this._pointers.clear();\n }\n\n private _handleDown(e: PointerEvent): void {\n (e.target as Element).setPointerCapture?.(e.pointerId);\n const t: Tracker = {\n id: e.pointerId,\n startX: e.clientX, startY: e.clientY,\n startTime: performance.now(),\n lastX: e.clientX, lastY: e.clientY,\n lastTime: performance.now(),\n pointerType: e.pointerType,\n };\n this._pointers.set(e.pointerId, t);\n\n // Long press fires if the pointer stays still for longPressDuration\n if (this._pointers.size === 1) {\n this._longPressTimer = window.setTimeout(() => {\n const tr = this._pointers.get(e.pointerId);\n if (!tr) return;\n const d = distance({ x: tr.startX, y: tr.startY }, { x: tr.lastX, y: tr.lastY });\n if (d <= this._opts.tapMaxDistance) {\n this._ev.emit('longpress', {\n x: tr.startX, y: tr.startY,\n duration: performance.now() - tr.startTime,\n pointerType: tr.pointerType,\n });\n }\n }, this._opts.longPressDuration);\n }\n\n // Two-finger gestures start\n if (this._pointers.size === 2) {\n const [a, b] = Array.from(this._pointers.values());\n this._pinchStart = distance({ x: a!.startX, y: a!.startY }, { x: b!.startX, y: b!.startY });\n this._rotateStart = Math.atan2(b!.startY - a!.startY, b!.startX - a!.startX);\n this._pinchActive = true; this._rotateActive = true;\n const center = { x: (a!.startX + b!.startX) / 2, y: (a!.startY + b!.startY) / 2 };\n this._ev.emit('pinchstart', { scale: 1, delta: 0, center });\n this._ev.emit('rotatestart', { angle: 0, delta: 0, center });\n }\n }\n\n private _handleMove(e: PointerEvent): void {\n const t = this._pointers.get(e.pointerId);\n if (!t) return;\n const now = performance.now();\n const dt = (now - t.lastTime) / 1000;\n const dx = e.clientX - t.lastX;\n const dy = e.clientY - t.lastY;\n t.lastX = e.clientX; t.lastY = e.clientY; t.lastTime = now;\n\n // Single pointer → pan\n if (this._pointers.size === 1) {\n const tx = e.clientX - t.startX;\n const ty = e.clientY - t.startY;\n const movedEnough = Math.hypot(tx, ty) > this._opts.tapMaxDistance;\n if (movedEnough && !this._panActive) {\n this._panActive = true;\n if (this._longPressTimer) { clearTimeout(this._longPressTimer); this._longPressTimer = 0; }\n this._ev.emit('panstart', {\n x: e.clientX, y: e.clientY,\n dx: 0, dy: 0, tx, ty, vx: 0, vy: 0, speed: 0,\n pointerType: t.pointerType,\n });\n }\n if (this._panActive) {\n const vx = dt > 0 ? dx / dt : 0;\n const vy = dt > 0 ? dy / dt : 0;\n this._ev.emit('pan', {\n x: e.clientX, y: e.clientY,\n dx, dy, tx, ty, vx, vy, speed: Math.hypot(vx, vy),\n pointerType: t.pointerType,\n });\n }\n return;\n }\n\n // Two pointers → pinch + rotate\n if (this._pointers.size === 2) {\n const [a, b] = Array.from(this._pointers.values());\n const curDist = distance({ x: a!.lastX, y: a!.lastY }, { x: b!.lastX, y: b!.lastY });\n const curAngle = Math.atan2(b!.lastY - a!.lastY, b!.lastX - a!.lastX);\n const scale = this._pinchStart > 0 ? curDist / this._pinchStart : 1;\n const center = { x: (a!.lastX + b!.lastX) / 2, y: (a!.lastY + b!.lastY) / 2 };\n this._ev.emit('pinch', { scale, delta: 0, center });\n this._ev.emit('rotate', { angle: curAngle - this._rotateStart, delta: 0, center });\n }\n }\n\n private _handleUp(e: PointerEvent): void {\n const t = this._pointers.get(e.pointerId);\n if (!t) return;\n this._pointers.delete(e.pointerId);\n if (this._longPressTimer) { clearTimeout(this._longPressTimer); this._longPressTimer = 0; }\n\n const now = performance.now();\n const duration = now - t.startTime;\n const tx = t.lastX - t.startX;\n const ty = t.lastY - t.startY;\n const totalDist = Math.hypot(tx, ty);\n\n // Pan end\n if (this._panActive) {\n this._panActive = false;\n const dt = duration / 1000;\n const vx = dt > 0 ? tx / dt : 0;\n const vy = dt > 0 ? ty / dt : 0;\n this._ev.emit('panend', {\n x: t.lastX, y: t.lastY,\n dx: 0, dy: 0, tx, ty, vx, vy, speed: Math.hypot(vx, vy),\n pointerType: t.pointerType,\n });\n\n // Swipe check\n const velocity = Math.hypot(vx, vy);\n if (velocity >= this._opts.swipeMinVelocity && totalDist >= this._opts.swipeMinDistance) {\n const dir = dirOf(tx, ty, this._opts.swipeMinDistance);\n if (dir) {\n this._ev.emit('swipe', {\n direction: dir, distance: totalDist, velocity, duration,\n pointerType: t.pointerType,\n });\n }\n }\n } else if (totalDist <= this._opts.tapMaxDistance && duration <= this._opts.tapMaxDuration) {\n // Tap\n const gap = now - this._lastTapAt;\n const near = distance({ x: t.startX, y: t.startY }, { x: this._lastTapX, y: this._lastTapY }) <= this._opts.tapMaxDistance * 3;\n if (gap <= this._opts.doubleTapMaxGap && near) {\n this._ev.emit('doubletap', { x: t.startX, y: t.startY, pointerType: t.pointerType });\n this._lastTapAt = 0;\n } else {\n this._ev.emit('tap', { x: t.startX, y: t.startY, pointerType: t.pointerType });\n this._lastTapAt = now;\n this._lastTapX = t.startX;\n this._lastTapY = t.startY;\n }\n }\n\n // Pinch/rotate end when second finger lifts\n if (this._pointers.size < 2) {\n if (this._pinchActive) { this._pinchActive = false; this._ev.emit('pinchend', { scale: 1, delta: 0, center: { x: t.lastX, y: t.lastY } }); }\n if (this._rotateActive) { this._rotateActive = false; this._ev.emit('rotateend', { angle: 0, delta: 0, center: { x: t.lastX, y: t.lastY } }); }\n }\n }\n}\n","import { Emitter } from '../events/events';\n\n/**\n * Global cursor tracker — tracks last known position, velocity, and idle state.\n * One instance per page; emits 'move', 'idle', 'active' events.\n */\nexport class Cursor {\n private _ev = new Emitter();\n private _x = 0;\n private _y = 0;\n private _vx = 0;\n private _vy = 0;\n private _lastX = 0;\n private _lastY = 0;\n private _lastT = 0;\n private _idle = false;\n private _idleTimer = 0;\n private _idleDuration = 2000;\n private _started = false;\n\n private _onMove: (e: Event) => void;\n\n constructor() {\n this._onMove = (e) => this._handle(e as PointerEvent);\n }\n\n start(): void {\n if (this._started) return;\n this._started = true;\n window.addEventListener('pointermove', this._onMove, { passive: true });\n }\n\n stop(): void {\n window.removeEventListener('pointermove', this._onMove);\n this._started = false;\n }\n\n get x(): number { return this._x; }\n get y(): number { return this._y; }\n get vx(): number { return this._vx; }\n get vy(): number { return this._vy; }\n get speed(): number { return Math.hypot(this._vx, this._vy); }\n get idle(): boolean { return this._idle; }\n\n on(event: 'move' | 'idle' | 'active', fn: (...args: any[]) => void): () => void {\n return this._ev.on(event, fn);\n }\n\n /** Set idle threshold in ms. Default 2000. */\n setIdleTimeout(ms: number): void {\n this._idleDuration = ms;\n this._resetIdle();\n }\n\n private _handle(e: PointerEvent): void {\n const now = performance.now();\n const dt = (now - this._lastT) / 1000;\n this._x = e.clientX;\n this._y = e.clientY;\n if (dt > 0 && dt < 0.2) {\n this._vx = (this._x - this._lastX) / dt;\n this._vy = (this._y - this._lastY) / dt;\n } else {\n this._vx = 0;\n this._vy = 0;\n }\n this._lastX = this._x; this._lastY = this._y; this._lastT = now;\n this._ev.emit('move', { x: this._x, y: this._y, vx: this._vx, vy: this._vy, speed: this.speed });\n\n if (this._idle) {\n this._idle = false;\n this._ev.emit('active');\n }\n this._resetIdle();\n }\n\n private _resetIdle(): void {\n if (this._idleTimer) clearTimeout(this._idleTimer);\n this._idleTimer = window.setTimeout(() => {\n this._idle = true;\n this._ev.emit('idle');\n }, this._idleDuration);\n }\n}\n","import type { Cursor } from './cursor';\n\nexport interface MagnetOptions {\n /** Max distance (px) at which the magnet engages. Default 120. */\n range?: number;\n /** How strongly the element is pulled toward the cursor. 0–1. Default 0.35. */\n strength?: number;\n /** Easing factor per frame. Lower = smoother. Default 0.18. */\n ease?: number;\n}\n\nconst DEFAULTS: Required<MagnetOptions> = {\n range: 120,\n strength: 0.35,\n ease: 0.18,\n};\n\n/**\n * Make an element magnetically attracted to the cursor when nearby.\n * Returns a destroy function.\n */\nexport function magnet(el: HTMLElement, cursor: Cursor, opts?: MagnetOptions): () => void {\n const cfg = { ...DEFAULTS, ...opts };\n let tx = 0, ty = 0; // target\n let cx = 0, cy = 0; // current\n let rafId = 0;\n let destroyed = false;\n\n function tick(): void {\n if (destroyed) return;\n const rect = el.getBoundingClientRect();\n const eCx = rect.left + rect.width / 2;\n const eCy = rect.top + rect.height / 2;\n const dx = cursor.x - eCx;\n const dy = cursor.y - eCy;\n const d = Math.hypot(dx, dy);\n\n if (d < cfg.range) {\n const pull = (1 - d / cfg.range) * cfg.strength;\n tx = dx * pull;\n ty = dy * pull;\n } else {\n tx = 0;\n ty = 0;\n }\n\n cx += (tx - cx) * cfg.ease;\n cy += (ty - cy) * cfg.ease;\n el.style.transform = `translate(${cx.toFixed(2)}px, ${cy.toFixed(2)}px)`;\n rafId = requestAnimationFrame(tick);\n }\n\n rafId = requestAnimationFrame(tick);\n return () => {\n destroyed = true;\n if (rafId) cancelAnimationFrame(rafId);\n el.style.transform = '';\n };\n}\n","import { Emitter } from '../events/events';\n\nexport type InputKind = 'mouse' | 'trackpad' | 'touch' | 'unknown';\n\nexport interface WheelInfo {\n dx: number;\n dy: number;\n kind: InputKind;\n /** True if the user is pinch-zooming on a trackpad (ctrlKey + wheel). */\n pinch: boolean;\n}\n\n/**\n * Heuristic trackpad detection + normalized wheel stream.\n *\n * Detection heuristic:\n * - `deltaMode === 0` (pixel) with small non-integer deltas → trackpad\n * - `deltaMode === 1` (line) → mouse wheel\n * - `ctrlKey + wheel` → trackpad pinch-to-zoom (Safari/Chrome)\n */\nexport class Trackpad {\n private _ev = new Emitter();\n private _kind: InputKind = 'unknown';\n private _started = false;\n private _onWheel: (e: Event) => void;\n\n constructor() {\n this._onWheel = (e) => this._handle(e as WheelEvent);\n }\n\n start(target: EventTarget = window): void {\n if (this._started) return;\n this._started = true;\n target.addEventListener('wheel', this._onWheel, { passive: false });\n }\n\n stop(target: EventTarget = window): void {\n target.removeEventListener('wheel', this._onWheel);\n this._started = false;\n }\n\n get kind(): InputKind { return this._kind; }\n get isTrackpad(): boolean { return this._kind === 'trackpad'; }\n get isMouse(): boolean { return this._kind === 'mouse'; }\n\n on(event: 'wheel' | 'pinch' | 'kind', fn: (...args: any[]) => void): () => void {\n return this._ev.on(event, fn);\n }\n\n private _handle(e: WheelEvent): void {\n const { deltaX, deltaY, deltaMode, ctrlKey } = e;\n\n // Trackpad pinch-zoom comes through as wheel with ctrlKey=true.\n // The browser intercepts it before user code unless we preventDefault.\n const pinch = ctrlKey;\n\n // Detect kind. Mouse wheels typically use deltaMode=1 (line) with larger\n // integer steps. Trackpads use deltaMode=0 (pixel) with small/fractional\n // deltas. Some mice also send deltaMode=0 but with multiples of 100.\n let kind: InputKind = this._kind;\n if (deltaMode === 1) {\n kind = 'mouse';\n } else if (deltaMode === 0) {\n const absMax = Math.max(Math.abs(deltaX), Math.abs(deltaY));\n if (absMax > 0 && absMax < 50 && absMax !== Math.floor(absMax)) kind = 'trackpad';\n else if (absMax > 0 && absMax < 20) kind = 'trackpad';\n else if (absMax >= 100 && absMax % 100 === 0) kind = 'mouse';\n }\n\n if (kind !== this._kind && kind !== 'unknown') {\n this._kind = kind;\n this._ev.emit('kind', kind);\n }\n\n const info: WheelInfo = { dx: deltaX, dy: deltaY, kind: this._kind, pinch };\n if (pinch) this._ev.emit('pinch', info);\n else this._ev.emit('wheel', info);\n }\n}\n","import { Gesture } from './gestures/gesture';\nimport type {\n GestureOptions, GestureEventName,\n TapEvent, DoubleTapEvent, LongPressEvent,\n PanEvent, SwipeEvent, PinchEvent, RotateEvent,\n} from './gestures/gesture';\nimport { Cursor } from './cursor/cursor';\nimport { magnet as magnetFn } from './cursor/magnet';\nimport type { MagnetOptions } from './cursor/magnet';\nimport { follow as followFn } from './cursor/follow';\nimport type { FollowOptions } from './cursor/follow';\nimport { tilt as tiltFn } from './cursor/tilt';\nimport type { TiltOptions } from './cursor/tilt';\nimport { Trackpad } from './trackpad/trackpad';\nimport type { InputKind, WheelInfo } from './trackpad/trackpad';\n\nclass MousePad {\n private _cursor = new Cursor();\n private _trackpad = new Trackpad();\n private _initialized = false;\n\n /** Start tracking the cursor and trackpad globally. */\n init(): void {\n if (this._initialized) return;\n this._cursor.start();\n this._trackpad.start();\n this._initialized = true;\n }\n\n destroy(): void {\n this._cursor.stop();\n this._trackpad.stop();\n this._initialized = false;\n }\n\n /** Attach a gesture recognizer to an element. */\n gesture(el: Element, opts?: GestureOptions): Gesture {\n return new Gesture(el, opts);\n }\n\n /** Global cursor tracker (position, velocity, idle). */\n get cursor(): Cursor { return this._cursor; }\n\n /** Trackpad detector + wheel stream. */\n get trackpad(): Trackpad { return this._trackpad; }\n\n /** Make an element magnetically attracted to the cursor. */\n magnet(el: HTMLElement, opts?: MagnetOptions): () => void {\n if (!this._initialized) this.init();\n return magnetFn(el, this._cursor, opts);\n }\n\n /** Make an element follow the cursor with optional easing. */\n follow(el: HTMLElement, opts?: FollowOptions): () => void {\n if (!this._initialized) this.init();\n return followFn(el, this._cursor, opts);\n }\n\n /** Add a 3D tilt-on-hover effect to an element. */\n tilt(el: HTMLElement, opts?: TiltOptions): () => void {\n return tiltFn(el, opts);\n }\n}\n\nconst mousepad = new MousePad();\nexport default mousepad;\n\nexport type {\n GestureOptions, GestureEventName,\n TapEvent, DoubleTapEvent, LongPressEvent,\n PanEvent, SwipeEvent, PinchEvent, RotateEvent,\n MagnetOptions, FollowOptions, TiltOptions,\n InputKind, WheelInfo,\n Gesture, Cursor, Trackpad,\n};\n","import type { Cursor } from './cursor';\n\nexport interface FollowOptions {\n /** Easing factor (0–1). Lower = smoother lag. Default 0.18. */\n ease?: number;\n /** Lock to cursor with no lag. Default false. */\n instant?: boolean;\n /** Offset from cursor position. */\n offset?: { x: number; y: number };\n}\n\n/**\n * Make an element follow the cursor with optional easing.\n * Element must be positioned (fixed or absolute).\n */\nexport function follow(el: HTMLElement, cursor: Cursor, opts?: FollowOptions): () => void {\n const ease = opts?.ease ?? 0.18;\n const instant = opts?.instant ?? false;\n const offX = opts?.offset?.x ?? 0;\n const offY = opts?.offset?.y ?? 0;\n\n let x = cursor.x, y = cursor.y;\n let rafId = 0;\n let destroyed = false;\n\n function tick(): void {\n if (destroyed) return;\n if (instant) {\n x = cursor.x; y = cursor.y;\n } else {\n x += (cursor.x - x) * ease;\n y += (cursor.y - y) * ease;\n }\n el.style.transform = `translate(${(x + offX).toFixed(2)}px, ${(y + offY).toFixed(2)}px)`;\n rafId = requestAnimationFrame(tick);\n }\n\n rafId = requestAnimationFrame(tick);\n return () => {\n destroyed = true;\n if (rafId) cancelAnimationFrame(rafId);\n };\n}\n","export interface TiltOptions {\n /** Max rotation in degrees. Default 12. */\n max?: number;\n /** Scale factor while tilted. Default 1.03. */\n scale?: number;\n /** Perspective distance in px. Default 800. */\n perspective?: number;\n /** Easing on entering tilt. Lower = smoother. Default 0.18. */\n ease?: number;\n}\n\n/**\n * 3D tilt-on-hover effect — the element tilts toward the cursor position\n * within its own bounding box.\n */\nexport function tilt(el: HTMLElement, opts?: TiltOptions): () => void {\n const max = opts?.max ?? 12;\n const scale = opts?.scale ?? 1.03;\n const perspective = opts?.perspective ?? 800;\n const ease = opts?.ease ?? 0.18;\n\n let tx = 0, ty = 0, sc = 1; // targets\n let cx = 0, cy = 0, cs = 1; // current\n let active = false;\n let rafId = 0;\n let destroyed = false;\n\n function onEnter() { active = true; sc = scale; }\n function onLeave() { active = false; tx = 0; ty = 0; sc = 1; }\n function onMove(e: PointerEvent) {\n if (!active) return;\n const rect = el.getBoundingClientRect();\n const px = (e.clientX - rect.left) / rect.width - 0.5;\n const py = (e.clientY - rect.top) / rect.height - 0.5;\n tx = -py * max * 2; // rotateX\n ty = px * max * 2; // rotateY\n }\n\n function tick(): void {\n if (destroyed) return;\n cx += (tx - cx) * ease;\n cy += (ty - cy) * ease;\n cs += (sc - cs) * ease;\n el.style.transform =\n `perspective(${perspective}px) rotateX(${cx.toFixed(2)}deg) rotateY(${cy.toFixed(2)}deg) scale(${cs.toFixed(3)})`;\n rafId = requestAnimationFrame(tick);\n }\n\n el.addEventListener('pointerenter', onEnter);\n el.addEventListener('pointerleave', onLeave);\n el.addEventListener('pointermove', onMove as EventListener);\n el.style.transformStyle = 'preserve-3d';\n el.style.willChange = 'transform';\n rafId = requestAnimationFrame(tick);\n\n return () => {\n destroyed = true;\n if (rafId) cancelAnimationFrame(rafId);\n el.removeEventListener('pointerenter', onEnter);\n el.removeEventListener('pointerleave', onLeave);\n el.removeEventListener('pointermove', onMove as EventListener);\n el.style.transform = '';\n };\n}\n"],"names":["Emitter","_map","Map","on","event","fn","set","this","get","Set","add","off","delete","emit","args","e","console","error","distance","a","b","Math","hypot","x","y","DEFAULTS","tapMaxDistance","tapMaxDuration","doubleTapMaxGap","longPressDuration","swipeMinVelocity","swipeMinDistance","Gesture","_el","_ev","_pointers","_opts","_longPressTimer","_lastTapAt","_lastTapX","_lastTapY","_panActive","_pinchStart","_rotateStart","_pinchActive","_rotateActive","_onDown","_onMove","_onUp","constructor","opts","_handleDown","_handleMove","_handleUp","addEventListener","destroy","removeEventListener","clearTimeout","clear","target","setPointerCapture","pointerId","t","id","startX","clientX","startY","clientY","startTime","performance","now","lastX","lastY","lastTime","pointerType","size","window","setTimeout","tr","duration","Array","from","values","atan2","center","scale","delta","angle","dt","dx","dy","tx","ty","vx","vy","speed","curDist","curAngle","totalDist","velocity","dir","threshold","abs","dirOf","direction","gap","near","Cursor","_x","_y","_vx","_vy","_lastX","_lastY","_lastT","_idle","_idleTimer","_idleDuration","_started","_handle","start","passive","stop","idle","setIdleTimeout","ms","_resetIdle","range","strength","ease","Trackpad","_kind","_onWheel","kind","isTrackpad","isMouse","deltaX","deltaY","deltaMode","ctrlKey","pinch","absMax","max","floor","_cursor","_trackpad","_initialized","init","gesture","el","cursor","trackpad","magnet","cfg","cx","cy","rafId","destroyed","requestAnimationFrame","tick","rect","getBoundingClientRect","left","width","top","height","d","pull","style","transform","toFixed","cancelAnimationFrame","magnetFn","follow","instant","offX","offset","offY","followFn","tilt","perspective","sc","cs","active","onEnter","onLeave","onMove","transformStyle","willChange","tiltFn"],"mappings":"8OAEaA,EACHC,EAAO,IAAIC,IAEnB,EAAAC,CAAGC,EAAeC,GAChB,IAAIC,EAAMC,KAAKN,EAAKO,IAAIJ,GAGxB,OAFKE,IAAOA,EAAM,IAAIG,IAAOF,KAAKN,EAAKK,IAAIF,EAAOE,IAClDA,EAAII,IAAIL,GACD,IAAME,KAAKI,IAAIP,EAAOC,EAC/B,CAEA,GAAAM,CAAIP,EAAeC,GACZA,EACLE,KAAKN,EAAKO,IAAIJ,IAAQQ,OAAOP,GADlBE,KAAKN,EAAKW,OAAOR,EAE9B,CAEA,IAAAS,CAAKT,KAAkBU,GACrB,MAAMR,EAAMC,KAAKN,EAAKO,IAAIJ,GAC1B,GAAKE,EACL,IAAK,MAAMD,KAAMC,EACf,IAAMD,KAAMS,EAAO,CAAE,MAAOC,GAAKC,QAAQC,MAAM,gBAAiBF,EAAI,CAExE,ECVI,SAAUG,EAASC,EAASC,GAChC,OAAOC,KAAKC,MAAMH,EAAEI,EAAIH,EAAEG,EAAGJ,EAAEK,EAAIJ,EAAEI,EACvC,CCyCA,MAAMC,EAAqC,CACzCC,eAAgB,GAChBC,eAAgB,IAChBC,gBAAiB,IACjBC,kBAAmB,IACnBC,iBAAkB,IAClBC,iBAAkB,UAkBPC,EAoBSC,EAnBZC,EAAM,IAAIlC,EACVmC,EAAY,IAAIjC,IAChBkC,EAEAC,EAAkB,EAClBC,EAAa,EACbC,EAAY,EACZC,EAAY,EAEZC,GAAa,EACbC,EAAc,EACdC,EAAe,EACfC,GAAe,EACfC,GAAgB,EAEhBC,EACAC,EACAC,EAER,WAAAC,CAAoBhB,EAAciB,GAAd3C,KAAA0B,EAAAA,EAClB1B,KAAK6B,EAAQ,IAAKX,KAAayB,GAC/B3C,KAAKuC,EAAW/B,GAAMR,KAAK4C,EAAYpC,GACvCR,KAAKwC,EAAWhC,GAAMR,KAAK6C,EAAYrC,GACvCR,KAAKyC,EAAWjC,GAAMR,KAAK8C,EAAUtC,GACrCkB,EAAIqB,iBAAiB,cAAe/C,KAAKuC,GACzCb,EAAIqB,iBAAiB,cAAe/C,KAAKwC,GACzCd,EAAIqB,iBAAiB,YAAa/C,KAAKyC,GACvCf,EAAIqB,iBAAiB,gBAAiB/C,KAAKyC,EAC7C,CAEA,EAAA7C,CAAGC,EAAyBC,GAC1B,OAAOE,KAAK2B,EAAI/B,GAAGC,EAAOC,EAC5B,CAEA,OAAAkD,GACEhD,KAAK0B,EAAIuB,oBAAoB,cAAejD,KAAKuC,GACjDvC,KAAK0B,EAAIuB,oBAAoB,cAAejD,KAAKwC,GACjDxC,KAAK0B,EAAIuB,oBAAoB,YAAajD,KAAKyC,GAC/CzC,KAAK0B,EAAIuB,oBAAoB,gBAAiBjD,KAAKyC,GAC/CzC,KAAK8B,GAAiBoB,aAAalD,KAAK8B,GAC5C9B,KAAK4B,EAAUuB,OACjB,CAEQ,CAAAP,CAAYpC,GACjBA,EAAE4C,OAAmBC,oBAAoB7C,EAAE8C,WAC5C,MAAMC,EAAa,CACjBC,GAAIhD,EAAE8C,UACNG,OAAQjD,EAAEkD,QAASC,OAAQnD,EAAEoD,QAC7BC,UAAWC,YAAYC,MACvBC,MAAOxD,EAAEkD,QAASO,MAAOzD,EAAEoD,QAC3BM,SAAUJ,YAAYC,MACtBI,YAAa3D,EAAE2D,aAqBjB,GAnBAnE,KAAK4B,EAAU7B,IAAIS,EAAE8C,UAAWC,GAGJ,IAAxBvD,KAAK4B,EAAUwC,OACjBpE,KAAK8B,EAAkBuC,OAAOC,WAAW,KACvC,MAAMC,EAAKvE,KAAK4B,EAAU3B,IAAIO,EAAE8C,WAC3BiB,GACK5D,EAAS,CAAEK,EAAGuD,EAAGd,OAAQxC,EAAGsD,EAAGZ,QAAU,CAAE3C,EAAGuD,EAAGP,MAAO/C,EAAGsD,EAAGN,SAC/DjE,KAAK6B,EAAMV,gBAClBnB,KAAK2B,EAAIrB,KAAK,YAAa,CACzBU,EAAGuD,EAAGd,OAAQxC,EAAGsD,EAAGZ,OACpBa,SAAUV,YAAYC,MAAQQ,EAAGV,UACjCM,YAAaI,EAAGJ,eAGnBnE,KAAK6B,EAAMP,oBAIY,IAAxBtB,KAAK4B,EAAUwC,KAAY,CAC7B,MAAOxD,EAAGC,GAAK4D,MAAMC,KAAK1E,KAAK4B,EAAU+C,UACzC3E,KAAKmC,EAAcxB,EAAS,CAAEK,EAAGJ,EAAG6C,OAAQxC,EAAGL,EAAG+C,QAAU,CAAE3C,EAAGH,EAAG4C,OAAQxC,EAAGJ,EAAG8C,SAClF3D,KAAKoC,EAAetB,KAAK8D,MAAM/D,EAAG8C,OAAS/C,EAAG+C,OAAQ9C,EAAG4C,OAAS7C,EAAG6C,QACrEzD,KAAKqC,GAAe,EAAMrC,KAAKsC,GAAgB,EAC/C,MAAMuC,EAAS,CAAE7D,GAAIJ,EAAG6C,OAAS5C,EAAG4C,QAAU,EAAGxC,GAAIL,EAAG+C,OAAS9C,EAAG8C,QAAU,GAC9E3D,KAAK2B,EAAIrB,KAAK,aAAe,CAAEwE,MAAO,EAAGC,MAAO,EAAGF,WACnD7E,KAAK2B,EAAIrB,KAAK,cAAe,CAAE0E,MAAO,EAAGD,MAAO,EAAGF,UACrD,CACF,CAEQ,CAAAhC,CAAYrC,GAClB,MAAM+C,EAAIvD,KAAK4B,EAAU3B,IAAIO,EAAE8C,WAC/B,IAAKC,EAAG,OACR,MAAMQ,EAAMD,YAAYC,MAClBkB,GAAMlB,EAAMR,EAAEW,UAAY,IAC1BgB,EAAK1E,EAAEkD,QAAUH,EAAES,MACnBmB,EAAK3E,EAAEoD,QAAUL,EAAEU,MAIzB,GAHAV,EAAES,MAAQxD,EAAEkD,QAASH,EAAEU,MAAQzD,EAAEoD,QAASL,EAAEW,SAAWH,EAG3B,IAAxB/D,KAAK4B,EAAUwC,KAAY,CAC7B,MAAMgB,EAAK5E,EAAEkD,QAAUH,EAAEE,OACnB4B,EAAK7E,EAAEoD,QAAUL,EAAEI,OAWzB,GAVoB7C,KAAKC,MAAMqE,EAAIC,GAAMrF,KAAK6B,EAAMV,iBAChCnB,KAAKkC,IACvBlC,KAAKkC,GAAa,EACdlC,KAAK8B,IAAmBoB,aAAalD,KAAK8B,GAAkB9B,KAAK8B,EAAkB,GACvF9B,KAAK2B,EAAIrB,KAAK,WAAY,CACxBU,EAAGR,EAAEkD,QAASzC,EAAGT,EAAEoD,QACnBsB,GAAI,EAAGC,GAAI,EAAGC,KAAIC,KAAIC,GAAI,EAAGC,GAAI,EAAGC,MAAO,EAC3CrB,YAAaZ,EAAEY,eAGfnE,KAAKkC,EAAY,CACnB,MAAMoD,EAAKL,EAAK,EAAIC,EAAKD,EAAK,EACxBM,EAAKN,EAAK,EAAIE,EAAKF,EAAK,EAC9BjF,KAAK2B,EAAIrB,KAAK,MAAO,CACnBU,EAAGR,EAAEkD,QAASzC,EAAGT,EAAEoD,QACnBsB,KAAIC,KAAIC,KAAIC,KAAIC,KAAIC,KAAIC,MAAO1E,KAAKC,MAAMuE,EAAIC,GAC9CpB,YAAaZ,EAAEY,aAEnB,CACA,MACF,CAGA,GAA4B,IAAxBnE,KAAK4B,EAAUwC,KAAY,CAC7B,MAAOxD,EAAGC,GAAK4D,MAAMC,KAAK1E,KAAK4B,EAAU+C,UACnCc,EAAU9E,EAAS,CAAEK,EAAGJ,EAAGoD,MAAO/C,EAAGL,EAAGqD,OAAS,CAAEjD,EAAGH,EAAGmD,MAAO/C,EAAGJ,EAAGoD,QACtEyB,EAAW5E,KAAK8D,MAAM/D,EAAGoD,MAAQrD,EAAGqD,MAAOpD,EAAGmD,MAAQpD,EAAGoD,OAEzDa,EAAS,CAAE7D,GAAIJ,EAAGoD,MAAQnD,EAAGmD,OAAS,EAAG/C,GAAIL,EAAGqD,MAAQpD,EAAGoD,OAAS,GAC1EjE,KAAK2B,EAAIrB,KAAK,QAAU,CAAEwE,MAFZ9E,KAAKmC,EAAc,EAAIsD,EAAUzF,KAAKmC,EAAc,EAEjC4C,MAAO,EAAGF,WAC3C7E,KAAK2B,EAAIrB,KAAK,SAAU,CAAE0E,MAAOU,EAAW1F,KAAKoC,EAAc2C,MAAO,EAAGF,UAC3E,CACF,CAEQ,CAAA/B,CAAUtC,GAChB,MAAM+C,EAAIvD,KAAK4B,EAAU3B,IAAIO,EAAE8C,WAC/B,IAAKC,EAAG,OACRvD,KAAK4B,EAAUvB,OAAOG,EAAE8C,WACpBtD,KAAK8B,IAAmBoB,aAAalD,KAAK8B,GAAkB9B,KAAK8B,EAAkB,GAEvF,MAAMiC,EAAMD,YAAYC,MAClBS,EAAWT,EAAMR,EAAEM,UACnBuB,EAAK7B,EAAES,MAAQT,EAAEE,OACjB4B,EAAK9B,EAAEU,MAAQV,EAAEI,OACjBgC,EAAY7E,KAAKC,MAAMqE,EAAIC,GAGjC,GAAIrF,KAAKkC,EAAY,CACnBlC,KAAKkC,GAAa,EAClB,MAAM+C,EAAKT,EAAW,IAChBc,EAAKL,EAAK,EAAIG,EAAKH,EAAK,EACxBM,EAAKN,EAAK,EAAII,EAAKJ,EAAK,EAC9BjF,KAAK2B,EAAIrB,KAAK,SAAU,CACtBU,EAAGuC,EAAES,MAAO/C,EAAGsC,EAAEU,MACjBiB,GAAI,EAAGC,GAAI,EAAGC,KAAIC,KAAIC,KAAIC,KAAIC,MAAO1E,KAAKC,MAAMuE,EAAIC,GACpDpB,YAAaZ,EAAEY,cAIjB,MAAMyB,EAAW9E,KAAKC,MAAMuE,EAAIC,GAChC,GAAIK,GAAY5F,KAAK6B,EAAMN,kBAAoBoE,GAAa3F,KAAK6B,EAAML,iBAAkB,CACvF,MAAMqE,EDxNR,SAAoBX,EAAYC,EAAYW,EAAY,IAC5D,OAAIhF,KAAKC,MAAMmE,EAAIC,GAAMW,EAAkB,GACvChF,KAAKiF,IAAIb,GAAMpE,KAAKiF,IAAIZ,GAAYD,EAAK,EAAI,QAAU,OACpDC,EAAK,EAAI,OAAS,IAC3B,CCoNoBa,CAAMZ,EAAIC,EAAIrF,KAAK6B,EAAML,kBACjCqE,GACF7F,KAAK2B,EAAIrB,KAAK,QAAS,CACrB2F,UAAWJ,EAAKlF,SAAUgF,EAAWC,WAAUpB,WAC/CL,YAAaZ,EAAEY,aAGrB,CACF,MAAO,GAAIwB,GAAa3F,KAAK6B,EAAMV,gBAAkBqD,GAAYxE,KAAK6B,EAAMT,eAAgB,CAE1F,MAAM8E,EAAMnC,EAAM/D,KAAK+B,EACjBoE,EAAOxF,EAAS,CAAEK,EAAGuC,EAAEE,OAAQxC,EAAGsC,EAAEI,QAAU,CAAE3C,EAAGhB,KAAKgC,EAAWf,EAAGjB,KAAKiC,KAA4C,EAA5BjC,KAAK6B,EAAMV,eACxG+E,GAAOlG,KAAK6B,EAAMR,iBAAmB8E,GACvCnG,KAAK2B,EAAIrB,KAAK,YAAa,CAAEU,EAAGuC,EAAEE,OAAQxC,EAAGsC,EAAEI,OAAQQ,YAAaZ,EAAEY,cACtEnE,KAAK+B,EAAa,IAElB/B,KAAK2B,EAAIrB,KAAK,MAAO,CAAEU,EAAGuC,EAAEE,OAAQxC,EAAGsC,EAAEI,OAAQQ,YAAaZ,EAAEY,cAChEnE,KAAK+B,EAAagC,EAClB/D,KAAKgC,EAAYuB,EAAEE,OACnBzD,KAAKiC,EAAYsB,EAAEI,OAEvB,CAGI3D,KAAK4B,EAAUwC,KAAO,IACpBpE,KAAKqC,IAAiBrC,KAAKqC,GAAe,EAAQrC,KAAK2B,EAAIrB,KAAK,WAAa,CAAEwE,MAAO,EAAGC,MAAO,EAAGF,OAAQ,CAAE7D,EAAGuC,EAAES,MAAO/C,EAAGsC,EAAEU,UAC9HjE,KAAKsC,IAAiBtC,KAAKsC,GAAgB,EAAOtC,KAAK2B,EAAIrB,KAAK,YAAa,CAAE0E,MAAO,EAAGD,MAAO,EAAGF,OAAQ,CAAE7D,EAAGuC,EAAES,MAAO/C,EAAGsC,EAAEU,UAEtI,QCpQWmC,EACHzE,EAAM,IAAIlC,EACV4G,EAAK,EACLC,EAAK,EACLC,EAAM,EACNC,EAAM,EACNC,EAAS,EACTC,EAAS,EACTC,EAAS,EACTC,GAAQ,EACRC,EAAa,EACbC,EAAgB,IAChBC,GAAW,EAEXvE,EAER,WAAAE,GACE1C,KAAKwC,EAAWhC,GAAMR,KAAKgH,EAAQxG,EACrC,CAEA,KAAAyG,GACMjH,KAAK+G,IACT/G,KAAK+G,GAAW,EAChB1C,OAAOtB,iBAAiB,cAAe/C,KAAKwC,EAAS,CAAE0E,SAAS,IAClE,CAEA,IAAAC,GACE9C,OAAOpB,oBAAoB,cAAejD,KAAKwC,GAC/CxC,KAAK+G,GAAW,CAClB,CAEA,KAAI/F,GAAe,OAAOhB,KAAKqG,CAAI,CACnC,KAAIpF,GAAe,OAAOjB,KAAKsG,CAAI,CACnC,MAAIhB,GAAe,OAAOtF,KAAKuG,CAAK,CACpC,MAAIhB,GAAe,OAAOvF,KAAKwG,CAAK,CACpC,SAAIhB,GAAkB,OAAO1E,KAAKC,MAAMf,KAAKuG,EAAKvG,KAAKwG,EAAM,CAC7D,QAAIY,GAAkB,OAAOpH,KAAK4G,CAAO,CAEzC,EAAAhH,CAAGC,EAAmCC,GACpC,OAAOE,KAAK2B,EAAI/B,GAAGC,EAAOC,EAC5B,CAGA,cAAAuH,CAAeC,GACbtH,KAAK8G,EAAgBQ,EACrBtH,KAAKuH,GACP,CAEQ,CAAAP,CAAQxG,GACd,MAAMuD,EAAMD,YAAYC,MAClBkB,GAAMlB,EAAM/D,KAAK2G,GAAU,IACjC3G,KAAKqG,EAAK7F,EAAEkD,QACZ1D,KAAKsG,EAAK9F,EAAEoD,QACRqB,EAAK,GAAKA,EAAK,IACjBjF,KAAKuG,GAAOvG,KAAKqG,EAAKrG,KAAKyG,GAAUxB,EACrCjF,KAAKwG,GAAOxG,KAAKsG,EAAKtG,KAAK0G,GAAUzB,IAErCjF,KAAKuG,EAAM,EACXvG,KAAKwG,EAAM,GAEbxG,KAAKyG,EAASzG,KAAKqG,EAAIrG,KAAK0G,EAAS1G,KAAKsG,EAAItG,KAAK2G,EAAS5C,EAC5D/D,KAAK2B,EAAIrB,KAAK,OAAQ,CAAEU,EAAGhB,KAAKqG,EAAIpF,EAAGjB,KAAKsG,EAAIhB,GAAItF,KAAKuG,EAAKhB,GAAIvF,KAAKwG,EAAKhB,MAAOxF,KAAKwF,QAEpFxF,KAAK4G,IACP5G,KAAK4G,GAAQ,EACb5G,KAAK2B,EAAIrB,KAAK,WAEhBN,KAAKuH,GACP,CAEQ,CAAAA,GACFvH,KAAK6G,GAAY3D,aAAalD,KAAK6G,GACvC7G,KAAK6G,EAAaxC,OAAOC,WAAW,KAClCtE,KAAK4G,GAAQ,EACb5G,KAAK2B,EAAIrB,KAAK,SACbN,KAAK8G,EACV,ECvEF,MAAM5F,EAAoC,CACxCsG,MAAO,IACPC,SAAU,IACVC,KAAM,WCMKC,EACHhG,EAAM,IAAIlC,EACVmI,EAAmB,UACnBb,GAAW,EACXc,EAER,WAAAnF,GACE1C,KAAK6H,EAAYrH,GAAMR,KAAKgH,EAAQxG,EACtC,CAEA,KAAAyG,CAAM7D,EAAsBiB,QACtBrE,KAAK+G,IACT/G,KAAK+G,GAAW,EAChB3D,EAAOL,iBAAiB,QAAS/C,KAAK6H,EAAU,CAAEX,SAAS,IAC7D,CAEA,IAAAC,CAAK/D,EAAsBiB,QACzBjB,EAAOH,oBAAoB,QAASjD,KAAK6H,GACzC7H,KAAK+G,GAAW,CAClB,CAEA,QAAIe,GAAoB,OAAO9H,KAAK4H,CAAO,CAC3C,cAAIG,GAAwB,MAAsB,aAAf/H,KAAK4H,CAAsB,CAC9D,WAAII,GAAqB,MAAsB,UAAfhI,KAAK4H,CAAmB,CAExD,EAAAhI,CAAGC,EAAmCC,GACpC,OAAOE,KAAK2B,EAAI/B,GAAGC,EAAOC,EAC5B,CAEQ,CAAAkH,CAAQxG,GACd,MAAMyH,OAAEA,EAAMC,OAAEA,EAAMC,UAAEA,EAASC,QAAEA,GAAY5H,EAIzC6H,EAAQD,EAKd,IAAIN,EAAkB9H,KAAK4H,EAC3B,GAAkB,IAAdO,EACFL,EAAO,aACF,GAAkB,IAAdK,EAAiB,CAC1B,MAAMG,EAASxH,KAAKyH,IAAIzH,KAAKiF,IAAIkC,GAASnH,KAAKiF,IAAImC,IAC/CI,EAAS,GAAKA,EAAS,IAAMA,IAAWxH,KAAK0H,MAAMF,IAC9CA,EAAS,GAAKA,EAAS,GADgCR,EAAO,WAE9DQ,GAAU,KAAOA,EAAS,KAAQ,IAAGR,EAAO,QACvD,CAEIA,IAAS9H,KAAK4H,GAAkB,YAATE,IACzB9H,KAAK4H,EAAQE,EACb9H,KAAK2B,EAAIrB,KAAK,OAAQwH,IAIb9H,KAAK2B,EAAIrB,KAAhB+H,EAAqB,QACN,QAFK,CAAEnD,GAAI+C,EAAQ9C,GAAI+C,EAAQJ,KAAM9H,KAAK4H,EAAOS,SAGtE,SCbe,IAhDjB,MACUI,EAAU,IAAIrC,EACdsC,EAAY,IAAIf,EAChBgB,GAAe,EAGvB,IAAAC,GACM5I,KAAK2I,IACT3I,KAAKyI,EAAQxB,QACbjH,KAAK0I,EAAUzB,QACfjH,KAAK2I,GAAe,EACtB,CAEA,OAAA3F,GACEhD,KAAKyI,EAAQtB,OACbnH,KAAK0I,EAAUvB,OACfnH,KAAK2I,GAAe,CACtB,CAGA,OAAAE,CAAQC,EAAanG,GACnB,OAAO,IAAIlB,EAAQqH,EAAInG,EACzB,CAGA,UAAIoG,GAAmB,OAAO/I,KAAKyI,CAAS,CAG5C,YAAIO,GAAuB,OAAOhJ,KAAK0I,CAAW,CAGlD,MAAAO,CAAOH,EAAiBnG,GAEtB,OADK3C,KAAK2I,GAAc3I,KAAK4I,gBF3BVE,EAAiBC,EAAgBpG,GACtD,MAAMuG,EAAM,IAAKhI,KAAayB,GAC9B,IAAIyC,EAAK,EAAGC,EAAK,EACb8D,EAAK,EAAGC,EAAK,EACbC,EAAQ,EACRC,GAAY,EA2BhB,OADAD,EAAQE,sBAxBR,SAASC,IACP,GAAIF,EAAW,OACf,MAAMG,EAAOX,EAAGY,wBAGVxE,EAAK6D,EAAO/H,GAFNyI,EAAKE,KAAOF,EAAKG,MAAQ,GAG/BzE,EAAK4D,EAAO9H,GAFNwI,EAAKI,IAAMJ,EAAKK,OAAS,GAG/BC,EAAIjJ,KAAKC,MAAMmE,EAAIC,GAEzB,GAAI4E,EAAIb,EAAI1B,MAAO,CACjB,MAAMwC,GAAQ,EAAID,EAAIb,EAAI1B,OAAS0B,EAAIzB,SACvCrC,EAAKF,EAAK8E,EACV3E,EAAKF,EAAK6E,CACZ,MACE5E,EAAK,EACLC,EAAK,EAGP8D,IAAO/D,EAAK+D,GAAMD,EAAIxB,KACtB0B,IAAO/D,EAAK+D,GAAMF,EAAIxB,KACtBoB,EAAGmB,MAAMC,UAAY,aAAaf,EAAGgB,QAAQ,SAASf,EAAGe,QAAQ,QACjEd,EAAQE,sBAAsBC,EAChC,GAGO,KACLF,GAAY,EACRD,GAAOe,qBAAqBf,GAChCP,EAAGmB,MAAMC,UAAY,GAEzB,CETWG,CAASvB,EAAI9I,KAAKyI,EAAS9F,EACpC,CAGA,MAAA2H,CAAOxB,EAAiBnG,GAEtB,OADK3C,KAAK2I,GAAc3I,KAAK4I,gBCvCVE,EAAiBC,EAAgBpG,GACtD,MAAM+E,EAAO/E,GAAM+E,MAAQ,IACrB6C,EAAU5H,GAAM4H,UAAW,EAC3BC,EAAO7H,GAAM8H,QAAQzJ,GAAK,EAC1B0J,EAAO/H,GAAM8H,QAAQxJ,GAAK,EAEhC,IAAID,EAAI+H,EAAO/H,EAAGC,EAAI8H,EAAO9H,EACzBoI,EAAQ,EACRC,GAAY,EAehB,OADAD,EAAQE,sBAZR,SAASC,IACHF,IACAiB,GACFvJ,EAAI+H,EAAO/H,EAAGC,EAAI8H,EAAO9H,IAEzBD,IAAM+H,EAAO/H,EAAIA,GAAK0G,EACtBzG,IAAM8H,EAAO9H,EAAIA,GAAKyG,GAExBoB,EAAGmB,MAAMC,UAAY,cAAclJ,EAAIwJ,GAAML,QAAQ,UAAUlJ,EAAIyJ,GAAMP,QAAQ,QACjFd,EAAQE,sBAAsBC,GAChC,GAGO,KACLF,GAAY,EACRD,GAAOe,qBAAqBf,GAEpC,CDaWsB,CAAS7B,EAAI9I,KAAKyI,EAAS9F,EACpC,CAGA,IAAAiI,CAAK9B,EAAiBnG,GACpB,OE7CE,SAAemG,EAAiBnG,GACpC,MAAM4F,EAAM5F,GAAM4F,KAAO,GACnBzD,EAAQnC,GAAMmC,OAAS,KACvB+F,EAAclI,GAAMkI,aAAe,IACnCnD,EAAO/E,GAAM+E,MAAQ,IAE3B,IAAItC,EAAK,EAAGC,EAAK,EAAGyF,EAAK,EACrB3B,EAAK,EAAGC,EAAK,EAAG2B,EAAK,EACrBC,GAAS,EACT3B,EAAQ,EACRC,GAAY,EAEhB,SAAS2B,IAAYD,GAAS,EAAMF,EAAKhG,CAAO,CAChD,SAASoG,IAAYF,GAAS,EAAO5F,EAAK,EAAGC,EAAK,EAAGyF,EAAK,CAAG,CAC7D,SAASK,EAAO3K,GACd,IAAKwK,EAAQ,OACb,MAAMvB,EAAOX,EAAGY,wBAGhBtE,KADY5E,EAAEoD,QAAU6F,EAAKI,KAAOJ,EAAKK,OAAS,IACvCvB,EAAM,EACjBlD,IAHY7E,EAAEkD,QAAU+F,EAAKE,MAAQF,EAAKG,MAAQ,IAGxCrB,EAAM,CAClB,CAmBA,OAPAO,EAAG/F,iBAAiB,eAAgBkI,GACpCnC,EAAG/F,iBAAiB,eAAgBmI,GACpCpC,EAAG/F,iBAAiB,cAAeoI,GACnCrC,EAAGmB,MAAMmB,eAAiB,cAC1BtC,EAAGmB,MAAMoB,WAAa,YACtBhC,EAAQE,sBAfR,SAASC,IACHF,IACJH,IAAO/D,EAAK+D,GAAMzB,EAClB0B,IAAO/D,EAAK+D,GAAM1B,EAClBqD,IAAOD,EAAKC,GAAMrD,EAClBoB,EAAGmB,MAAMC,UACP,eAAeW,gBAA0B1B,EAAGgB,QAAQ,kBAAkBf,EAAGe,QAAQ,gBAAgBY,EAAGZ,QAAQ,MAC9Gd,EAAQE,sBAAsBC,GAChC,GASO,KACLF,GAAY,EACRD,GAAOe,qBAAqBf,GAChCP,EAAG7F,oBAAoB,eAAgBgI,GACvCnC,EAAG7F,oBAAoB,eAAgBiI,GACvCpC,EAAG7F,oBAAoB,cAAekI,GACtCrC,EAAGmB,MAAMC,UAAY,GAEzB,CFHWoB,CAAOxC,EAAInG,EACpB"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@buildwithdarsh/mousepadjs",
3
+ "version": "1.0.0",
4
+ "description": "Pointer intelligence for the web — gestures, cursor effects, and trackpad smarts. Unified mouse, touch, pen, and trackpad input.",
5
+ "main": "dist/mousepad.umd.js",
6
+ "module": "dist/mousepad.esm.js",
7
+ "types": "dist/mousepad.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/mousepad.d.ts",
11
+ "import": "./dist/mousepad.esm.js",
12
+ "require": "./dist/mousepad.umd.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist/mousepad.umd.js",
17
+ "dist/mousepad.umd.js.map",
18
+ "dist/mousepad.esm.js",
19
+ "dist/mousepad.esm.js.map",
20
+ "dist/mousepad.d.ts"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "scripts": {
26
+ "build": "rollup -c && rm -rf example/dist && cp -r dist example/dist",
27
+ "typecheck": "tsc --noEmit",
28
+ "dev": "rollup -c -w"
29
+ },
30
+ "keywords": [
31
+ "mouse",
32
+ "touchpad",
33
+ "trackpad",
34
+ "pointer",
35
+ "gestures",
36
+ "tap",
37
+ "swipe",
38
+ "pinch",
39
+ "cursor",
40
+ "magnet",
41
+ "parallax",
42
+ "tilt"
43
+ ],
44
+ "author": "Darsh Gupta",
45
+ "license": "MIT",
46
+ "type": "module",
47
+ "devDependencies": {
48
+ "@rollup/plugin-terser": "^1.0.0",
49
+ "@rollup/plugin-typescript": "^12.1.2",
50
+ "rollup": "^4.34.8",
51
+ "rollup-plugin-dts": "^6.1.1",
52
+ "tslib": "^2.8.1",
53
+ "typescript": "^5.7.3"
54
+ }
55
+ }