@msobiecki/react-marauders-path 1.24.3 → 1.26.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.
Files changed (33) hide show
  1. package/README.md +147 -12
  2. package/dist/index.d.ts +100 -0
  3. package/dist/index.js +29 -17
  4. package/dist/index.js.map +1 -1
  5. package/dist/use-double-tap/invoke-double-tap-action.js +7 -0
  6. package/dist/use-double-tap/invoke-double-tap-action.js.map +1 -0
  7. package/dist/use-double-tap/use-double-tap.js +77 -0
  8. package/dist/use-double-tap/use-double-tap.js.map +1 -0
  9. package/dist/use-double-tap/use-double-tap.types.js +9 -0
  10. package/dist/use-double-tap/use-double-tap.types.js.map +1 -0
  11. package/dist/use-drag/use-drag.js +68 -70
  12. package/dist/use-drag/use-drag.js.map +1 -1
  13. package/dist/use-key/use-key.js +96 -104
  14. package/dist/use-key/use-key.js.map +1 -1
  15. package/dist/use-pinch/use-pinch.js +77 -79
  16. package/dist/use-pinch/use-pinch.js.map +1 -1
  17. package/dist/use-press/invoke-press-action.js +7 -0
  18. package/dist/use-press/invoke-press-action.js.map +1 -0
  19. package/dist/use-press/use-press.js +98 -0
  20. package/dist/use-press/use-press.js.map +1 -0
  21. package/dist/use-press/use-press.types.js +9 -0
  22. package/dist/use-press/use-press.types.js.map +1 -0
  23. package/dist/use-swipe/use-swipe.js +61 -68
  24. package/dist/use-swipe/use-swipe.js.map +1 -1
  25. package/dist/use-tap/invoke-tap-action.js +7 -0
  26. package/dist/use-tap/invoke-tap-action.js.map +1 -0
  27. package/dist/use-tap/use-tap.js +94 -0
  28. package/dist/use-tap/use-tap.js.map +1 -0
  29. package/dist/use-tap/use-tap.types.js +9 -0
  30. package/dist/use-tap/use-tap.types.js.map +1 -0
  31. package/dist/use-wheel/use-wheel.js +33 -47
  32. package/dist/use-wheel/use-wheel.js.map +1 -1
  33. package/package.json +1 -1
package/README.md CHANGED
@@ -2,17 +2,20 @@
2
2
 
3
3
  [![License](https://img.shields.io/badge/license-%20%20GNU%20GPLv3%20-green.svg)](https://github.com/msobiecki/react-marauders-path/blob/master/LICENSE)
4
4
 
5
- A lightweight, type-safe React library for handling keyboard, wheel, swipe, drag, and pinch events. Perfect for games, interactive applications, and input-driven interfaces.
5
+ A lightweight, type-safe React library for handling keyboard, wheel, tap, double-tap, press, swipe, drag, and pinch events. Perfect for games, interactive applications, and input-driven interfaces.
6
6
 
7
7
  ![react-marauders-path](./docs/images/logotype.png)
8
8
 
9
9
  ## Features
10
10
 
11
- - 🎮 **Keyboard Event Handling** - Detect single keys, key combinations and sequences with configurable timing thresholds
12
- - 🎡 **Wheel Event Handling** - Track wheel, delta values with optional `requestAnimationFrame` batching for smoother updates
13
- - 🖐️ **Swipe Gesture Handling** - Detect directional swipes with configurable distance and velocity with pointer type filtering
14
- - 🖱️ **Drag Event Handling** - Track movement, delta values, duration, start/end positions with pointer type filtering and optional `requestAnimationFrame` batching for smoother updates
15
- - 🤏 **Pinch Gesture Handling** - Track two-finger distance, delta, and scale with pointer type filtering and optional `requestAnimationFrame` batching for smoother updates
11
+ - 🎮 **Keyboard Event Handling** - Detect single keys, key combinations, and sequences with configurable timing thresholds
12
+ - 🎡 **Wheel Event Handling** - Detect wheel delta values with optional `requestAnimationFrame` batching for smoother updates
13
+ - 👆 **Tap Gesture Handling** - Detect single taps/clicks with configurable movement and duration thresholds
14
+ - 👆👆 **Double-Tap Gesture Handling** - Detect consecutive taps/clicks with configurable timing and position thresholds
15
+ - **Press Gesture Handling** - Detect press-and-hold interactions with configurable delay and movement thresholds
16
+ - 🖐️ **Swipe Gesture Handling** - Detect directional swipes with configurable distance, velocity, and pointer type filtering
17
+ - ✊ **Drag Gesture Handling** - Detect movement, deltas, duration, and start/end positions with pointer type filtering and optional `requestAnimationFrame` batching
18
+ - 🤏 **Pinch Gesture Handling** - Detect two-finger distance, delta, and scale with pointer type filtering and optional `requestAnimationFrame` batching
16
19
 
17
20
  ## Installation
18
21
 
@@ -95,6 +98,48 @@ function MyComponent() {
95
98
  }
96
99
  ```
97
100
 
101
+ ### Tap Event Hook
102
+
103
+ ```typescript
104
+ import { useTap } from '@msobiecki/react-marauders-path';
105
+
106
+ function MyComponent() {
107
+ useTap((event, data) => {
108
+ console.log(`Tapped at X: ${data.x}, Y: ${data.y}`);
109
+ });
110
+
111
+ return <div>Tap to interact</div>;
112
+ }
113
+ ```
114
+
115
+ ### Double Tap Event Hook
116
+
117
+ ```typescript
118
+ import { useDoubleTap } from '@msobiecki/react-marauders-path';
119
+
120
+ function MyComponent() {
121
+ useDoubleTap((event, data) => {
122
+ console.log(`Double tapped at X: ${data.x}, Y: ${data.y}`);
123
+ });
124
+
125
+ return <div>Double tap to interact</div>;
126
+ }
127
+ ```
128
+
129
+ ### Press Event Hook
130
+
131
+ ```typescript
132
+ import { usePress } from '@msobiecki/react-marauders-path';
133
+
134
+ function MyComponent() {
135
+ usePress((event, data) => {
136
+ console.log(`Pressed at X: ${data.x}, Y: ${data.y}`);
137
+ });
138
+
139
+ return <div>Press and hold to interact</div>;
140
+ }
141
+ ```
142
+
98
143
  ### Swipe Event Hook
99
144
 
100
145
  ```typescript
@@ -197,6 +242,102 @@ interface WheelData {
197
242
  }
198
243
  ```
199
244
 
245
+ ### `useTap(callback, options?)`
246
+
247
+ Hook for handling single tap/click interactions.
248
+
249
+ **Parameters:**
250
+
251
+ - `callback: (event: PointerEvent, data: TapData) => void | boolean` - Called when tap gesture is recognized
252
+ - `options?: UseTapOptions` - Optional configuration
253
+
254
+ **Options:**
255
+
256
+ ```typescript
257
+ interface UseTapOptions {
258
+ eventPointerTypes?: Array<"touch" | "mouse" | "pen">; // Default: ["touch", "mouse", "pen"]
259
+ eventCapture?: boolean; // Default: false
260
+ eventOnce?: boolean; // Default: false
261
+ eventStopImmediatePropagation?: boolean; // Default: false
262
+ threshold?: number; // Default: 8 (px) - Maximum movement allowed between pointerdown and pointerup
263
+ maxDuration?: number; // Default: 250 (ms) - Maximum tap duration
264
+ container?: RefObject<HTMLElement>; // Default: window
265
+ }
266
+ ```
267
+
268
+ **Tap Data:**
269
+
270
+ ```typescript
271
+ interface TapData {
272
+ x: number; // Tap pointerup X
273
+ y: number; // Tap pointerup Y
274
+ }
275
+ ```
276
+
277
+ ### `useDoubleTap(callback, options?)`
278
+
279
+ Hook for handling double-tap / double-click interactions.
280
+
281
+ **Parameters:**
282
+
283
+ - `callback: (event: PointerEvent, data: DoubleTapData) => void | boolean` - Called when double tap is recognized
284
+ - `options?: UseDoubleTapOptions` - Optional configuration
285
+
286
+ **Options:**
287
+
288
+ ```typescript
289
+ interface UseDoubleTapOptions {
290
+ eventPointerTypes?: Array<"touch" | "mouse" | "pen">; // Default: ["touch", "mouse", "pen"]
291
+ eventCapture?: boolean; // Default: false
292
+ eventOnce?: boolean; // Default: false
293
+ eventStopImmediatePropagation?: boolean; // Default: false
294
+ delay?: number; // Default: 300 (ms) - Maximum interval between taps
295
+ threshold?: number; // Default: 8 (px) - Maximum distance between two tap positions
296
+ container?: RefObject<HTMLElement>; // Default: window
297
+ }
298
+ ```
299
+
300
+ **Double Tap Data:**
301
+
302
+ ```typescript
303
+ interface DoubleTapData {
304
+ x: number; // Tap pointerup X
305
+ y: number; // Tap pointerup Y
306
+ }
307
+ ```
308
+
309
+ ### `usePress(callback, options?)`
310
+
311
+ Hook for handling press-and-hold interactions.
312
+
313
+ **Parameters:**
314
+
315
+ - `callback: (event: PointerEvent, data: PressData) => void | boolean` - Called when press delay completes
316
+ - `options?: UsePressOptions` - Optional configuration
317
+
318
+ **Options:**
319
+
320
+ ```typescript
321
+ interface UsePressOptions {
322
+ eventPointerTypes?: Array<"touch" | "mouse" | "pen">; // Default: ["touch", "mouse", "pen"]
323
+ eventCapture?: boolean; // Default: false
324
+ eventOnce?: boolean; // Default: false
325
+ eventStopImmediatePropagation?: boolean; // Default: false
326
+ delay?: number; // Default: 500 (ms) - Press-and-hold duration required
327
+ threshold?: number; // Default: 8 (px) - Maximum movement allowed while holding
328
+ container?: RefObject<HTMLElement>; // Default: window
329
+ }
330
+ ```
331
+
332
+ **Press Data:**
333
+
334
+ ```typescript
335
+ interface PressData {
336
+ x: number; // Pointerdown X at press start
337
+ y: number; // Pointerdown Y at press start
338
+ }
339
+ ```
340
+
200
341
  ### `useSwipe(swipe, callback, options?)`
201
342
 
202
343
  Hook for handling touch swipe gestures with configurable distance and velocity thresholds.
@@ -414,12 +555,6 @@ npm run lint
414
555
  - `drag` / `pan` – track movement of finger or mouse
415
556
  - `pinch` / `zoom` – two-finger pinch / zoom
416
557
 
417
- ### Low-level Gesture Hooks
418
-
419
- - 🚧 **`useTap`** – single tap / click
420
- - 🚧 **`useDoubleTap`** – quick double tap
421
- - 🚧 **`usePress`** – press and hold (longPress)
422
-
423
558
  ### Pointer / Mouse Hooks (Unified)
424
559
 
425
560
  - 🚧 **`usePointer`** – unified hook for MouseEvent, PointerEvent, and TouchEvent
package/dist/index.d.ts CHANGED
@@ -9,6 +9,31 @@ export declare interface CombinationState {
9
9
  activeKeys: Map<Key, CombinationActiveKey>;
10
10
  }
11
11
 
12
+ export declare interface DoubleTapData {
13
+ x: number;
14
+ y: number;
15
+ }
16
+
17
+ export declare type DoubleTapEventPointerType = (typeof DoubleTapEventPointerTypes)[keyof typeof DoubleTapEventPointerTypes];
18
+
19
+ export declare const DoubleTapEventPointerTypes: {
20
+ readonly Touch: "touch";
21
+ readonly Mouse: "mouse";
22
+ readonly Pen: "pen";
23
+ };
24
+
25
+ export declare interface DoubleTapOptions {
26
+ eventPointerTypes: DoubleTapEventPointerType[];
27
+ eventCapture: boolean;
28
+ eventOnce: boolean;
29
+ eventStopImmediatePropagation: boolean;
30
+ delay: number;
31
+ threshold: number;
32
+ container: {
33
+ current: EventTarget | null;
34
+ };
35
+ }
36
+
12
37
  export declare interface DragData {
13
38
  deltaX: number;
14
39
  deltaY: number;
@@ -108,6 +133,31 @@ export declare interface PinchState {
108
133
  active: boolean;
109
134
  }
110
135
 
136
+ export declare interface PressData {
137
+ x: number;
138
+ y: number;
139
+ }
140
+
141
+ export declare type PressEventPointerType = (typeof PressEventPointerTypes)[keyof typeof PressEventPointerTypes];
142
+
143
+ export declare const PressEventPointerTypes: {
144
+ readonly Touch: "touch";
145
+ readonly Mouse: "mouse";
146
+ readonly Pen: "pen";
147
+ };
148
+
149
+ export declare interface PressOptions {
150
+ eventPointerTypes: PressEventPointerType[];
151
+ eventCapture: boolean;
152
+ eventOnce: boolean;
153
+ eventStopImmediatePropagation: boolean;
154
+ delay: number;
155
+ threshold: number;
156
+ container: {
157
+ current: EventTarget | null;
158
+ };
159
+ }
160
+
111
161
  export declare interface SequenceState {
112
162
  key: Key;
113
163
  chord: KeyChord;
@@ -161,6 +211,44 @@ export declare interface SwipeState {
161
211
  active: boolean;
162
212
  }
163
213
 
214
+ export declare interface TapData {
215
+ x: number;
216
+ y: number;
217
+ }
218
+
219
+ export declare type TapEventPointerType = (typeof TapEventPointerTypes)[keyof typeof TapEventPointerTypes];
220
+
221
+ export declare const TapEventPointerTypes: {
222
+ readonly Touch: "touch";
223
+ readonly Mouse: "mouse";
224
+ readonly Pen: "pen";
225
+ };
226
+
227
+ export declare interface TapOptions {
228
+ eventPointerTypes: TapEventPointerType[];
229
+ eventCapture: boolean;
230
+ eventOnce: boolean;
231
+ eventStopImmediatePropagation: boolean;
232
+ threshold: number;
233
+ maxDuration: number;
234
+ container: {
235
+ current: EventTarget | null;
236
+ };
237
+ }
238
+
239
+ export declare interface TapState {
240
+ startX: number;
241
+ startY: number;
242
+ startTime: number;
243
+ active: boolean;
244
+ }
245
+
246
+ export declare const useDoubleTap: (doubleTapCallback: UseDoubleTapCallback, options?: UseDoubleTapOptions) => void;
247
+
248
+ export declare type UseDoubleTapCallback = ((event: PointerEvent, data: DoubleTapData) => boolean) | ((event: PointerEvent, data: DoubleTapData) => void);
249
+
250
+ export declare type UseDoubleTapOptions = Partial<DoubleTapOptions>;
251
+
164
252
  export declare const useDrag: (dragCallback: UseDragCallback, options?: UseDragOptions) => void;
165
253
 
166
254
  export declare type UseDragCallback = ((event: PointerEvent, data: DragData) => boolean) | ((event: PointerEvent, data: DragData) => void);
@@ -241,6 +329,12 @@ export declare type UsePinchCallback = ((event: PointerEvent, data: PinchData) =
241
329
 
242
330
  export declare type UsePinchOptions = Partial<PinchOptions>;
243
331
 
332
+ export declare const usePress: (pressCallback: UsePressCallback, options?: UsePressOptions) => void;
333
+
334
+ export declare type UsePressCallback = ((event: PointerEvent, data: PressData) => void) | ((event: PointerEvent, data: PressData) => boolean);
335
+
336
+ export declare type UsePressOptions = Partial<PressOptions>;
337
+
244
338
  export declare const useSwipe: (swipe: UseSwipeSchema, swipeCallback: UseSwipeCallback, options?: UseSwipeOptions) => void;
245
339
 
246
340
  export declare type UseSwipeCallback = ((event: PointerEvent, direction: SwipeDirection, data: SwipeData, ...properties: unknown[]) => boolean) | ((event: PointerEvent, direction: SwipeDirection, data: SwipeData, ...properties: unknown[]) => void);
@@ -249,6 +343,12 @@ export declare type UseSwipeOptions = Partial<SwipeOptions>;
249
343
 
250
344
  export declare type UseSwipeSchema = SwipeDirection | SwipeDirection[];
251
345
 
346
+ export declare const useTap: (tapCallback: UseTapCallback, options?: UseTapOptions) => void;
347
+
348
+ export declare type UseTapCallback = ((event: PointerEvent, data: TapData) => boolean) | ((event: PointerEvent, data: TapData) => void);
349
+
350
+ export declare type UseTapOptions = Partial<TapOptions>;
351
+
252
352
  export declare const useWheel: (wheelCallback: UseWheelCallback, options?: UseWheelOptions) => void;
253
353
 
254
354
  export declare type UseWheelCallback = ((event: WheelEvent, delta: WheelData, ...properties: unknown[]) => void) | ((event: WheelEvent, delta: WheelData, ...properties: unknown[]) => boolean);
package/dist/index.js CHANGED
@@ -1,22 +1,34 @@
1
- import { default as o } from "./use-drag/use-drag.js";
2
- import { DragEventPointerTypes as p } from "./use-drag/use-drag.types.js";
3
- import { default as f } from "./use-key/use-key.js";
1
+ import { default as o } from "./use-double-tap/use-double-tap.js";
2
+ import { DoubleTapEventPointerTypes as p } from "./use-double-tap/use-double-tap.types.js";
3
+ import { default as f } from "./use-drag/use-drag.js";
4
+ import { DragEventPointerTypes as u } from "./use-drag/use-drag.types.js";
5
+ import { default as m } from "./use-key/use-key.js";
4
6
  import { KeyEventTypes as i } from "./use-key/use-key.types.js";
5
- import { default as u } from "./use-pinch/use-pinch.js";
6
- import { PinchEventPointerTypes as x } from "./use-pinch/use-pinch.types.js";
7
- import { default as y } from "./use-swipe/use-swipe.js";
8
- import { SwipeDirections as P, SwipeEventPointerTypes as v } from "./use-swipe/use-swipe.types.js";
9
- import { default as T } from "./use-wheel/use-wheel.js";
7
+ import { default as T } from "./use-pinch/use-pinch.js";
8
+ import { PinchEventPointerTypes as y } from "./use-pinch/use-pinch.types.js";
9
+ import { default as v } from "./use-press/use-press.js";
10
+ import { PressEventPointerTypes as D } from "./use-press/use-press.types.js";
11
+ import { default as h } from "./use-swipe/use-swipe.js";
12
+ import { SwipeDirections as S, SwipeEventPointerTypes as b } from "./use-swipe/use-swipe.types.js";
13
+ import { default as K } from "./use-tap/use-tap.js";
14
+ import { TapEventPointerTypes as j } from "./use-tap/use-tap.types.js";
15
+ import { default as q } from "./use-wheel/use-wheel.js";
10
16
  export {
11
- p as DragEventPointerTypes,
17
+ p as DoubleTapEventPointerTypes,
18
+ u as DragEventPointerTypes,
12
19
  i as KeyEventTypes,
13
- x as PinchEventPointerTypes,
14
- P as SwipeDirections,
15
- v as SwipeEventPointerTypes,
16
- o as useDrag,
17
- f as useKey,
18
- u as usePinch,
19
- y as useSwipe,
20
- T as useWheel
20
+ y as PinchEventPointerTypes,
21
+ D as PressEventPointerTypes,
22
+ S as SwipeDirections,
23
+ b as SwipeEventPointerTypes,
24
+ j as TapEventPointerTypes,
25
+ o as useDoubleTap,
26
+ f as useDrag,
27
+ m as useKey,
28
+ T as usePinch,
29
+ v as usePress,
30
+ h as useSwipe,
31
+ K as useTap,
32
+ q as useWheel
21
33
  };
22
34
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
@@ -0,0 +1,7 @@
1
+ const i = (e, t, n, o) => {
2
+ o.stopImmediate && e.stopImmediatePropagation(), n(e, t) && e.preventDefault(), o.once && o.onOnce?.();
3
+ };
4
+ export {
5
+ i as invokeDoubleTapAction
6
+ };
7
+ //# sourceMappingURL=invoke-double-tap-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke-double-tap-action.js","sources":["../../src/use-double-tap/invoke-double-tap-action.ts"],"sourcesContent":["import { DoubleTapData } from \"./use-double-tap.types\";\n\n/**\n * Invokes a double tap action callback with optional event modifications.\n *\n * Handles double tap event processing including preventing default behavior,\n * stopping immediate propagation, and managing one-time event handlers.\n *\n * @param {PointerEvent} event - The double tap event\n * @param {DoubleTapData} data - The normalized double tap data\n * @param {Function} callback - Function to invoke with (event, data). Return true to prevent default.\n * @param {Object} options - Action options\n * @param {boolean} [options.stopImmediate=false] - Whether to stop immediate propagation\n * @param {boolean} [options.once=false] - Whether this is a one-time event\n * @param {Function} [options.onOnce] - Callback to invoke when one-time event fires\n *\n * @example\n * invokeTapAction(event, data, (e, d) => {\n * console.log(`Double tap at: ${d.x}, ${d.y}`);\n * return true; // Prevent default\n * }, { stopImmediate: true });\n */\nexport const invokeDoubleTapAction = (\n event: PointerEvent,\n data: DoubleTapData,\n callback:\n | ((event: PointerEvent, data: DoubleTapData) => boolean)\n | ((event: PointerEvent, data: DoubleTapData) => void),\n options: {\n stopImmediate?: boolean;\n once?: boolean;\n onOnce?: () => void;\n },\n) => {\n if (options.stopImmediate) {\n event.stopImmediatePropagation();\n }\n\n const shouldPrevent = callback(event, data);\n if (shouldPrevent) {\n event.preventDefault();\n }\n\n if (options.once) {\n options.onOnce?.();\n }\n};\n"],"names":["invokeDoubleTapAction","event","data","callback","options"],"mappings":"AAsBO,MAAMA,IAAwB,CACnCC,GACAC,GACAC,GAGAC,MAKG;AACH,EAAIA,EAAQ,iBACVH,EAAM,yBAAA,GAGcE,EAASF,GAAOC,CAAI,KAExCD,EAAM,eAAA,GAGJG,EAAQ,QACVA,EAAQ,SAAA;AAEZ;"}
@@ -0,0 +1,77 @@
1
+ import { useRef as c, useCallback as g, useEffect as x } from "react";
2
+ import { invokeDoubleTapAction as X } from "./invoke-double-tap-action.js";
3
+ const Y = {
4
+ eventPointerTypes: ["touch", "mouse", "pen"],
5
+ eventCapture: !1,
6
+ eventOnce: !1,
7
+ eventStopImmediatePropagation: !1,
8
+ delay: 300,
9
+ threshold: 8,
10
+ container: { current: null }
11
+ }, R = (i, h = {}) => {
12
+ const {
13
+ eventPointerTypes: l,
14
+ eventCapture: u,
15
+ eventOnce: a,
16
+ eventStopImmediatePropagation: s,
17
+ delay: p,
18
+ threshold: f,
19
+ container: d
20
+ } = { ...Y, ...h }, m = c(null), r = c(null), t = c(null), y = g(
21
+ (e) => {
22
+ if (!e.isPrimary || !l.includes(
23
+ e.pointerType
24
+ ))
25
+ return;
26
+ const n = Date.now();
27
+ if (!t.current) {
28
+ t.current = {
29
+ time: n,
30
+ x: e.clientX,
31
+ y: e.clientY
32
+ };
33
+ return;
34
+ }
35
+ const o = n - t.current.time, P = e.clientX - t.current.x, T = e.clientY - t.current.y;
36
+ if (o <= p && Math.hypot(P, T) <= f) {
37
+ const b = {
38
+ x: e.clientX,
39
+ y: e.clientY
40
+ };
41
+ X(e, b, i, {
42
+ stopImmediate: s,
43
+ once: a,
44
+ onOnce: () => r.current?.abort()
45
+ }), t.current = null;
46
+ return;
47
+ }
48
+ t.current = {
49
+ time: n,
50
+ x: e.clientX,
51
+ y: e.clientY
52
+ };
53
+ },
54
+ [
55
+ i,
56
+ p,
57
+ f,
58
+ l,
59
+ a,
60
+ s
61
+ ]
62
+ );
63
+ x(() => {
64
+ m.current = d?.current ?? globalThis, r.current = new AbortController();
65
+ const { signal: e } = r.current, n = (o) => o instanceof PointerEvent && y(o);
66
+ return m.current.addEventListener("pointerup", n, {
67
+ capture: u,
68
+ signal: e
69
+ }), () => {
70
+ r.current?.abort(), t.current = null;
71
+ };
72
+ }, [d, u, y]);
73
+ };
74
+ export {
75
+ R as default
76
+ };
77
+ //# sourceMappingURL=use-double-tap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-double-tap.js","sources":["../../src/use-double-tap/use-double-tap.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from \"react\";\nimport {\n DoubleTapOptions,\n UseDoubleTapCallback,\n UseDoubleTapOptions,\n DoubleTapEventPointerType,\n DoubleTapData,\n} from \"./use-double-tap.types\";\nimport { invokeDoubleTapAction } from \"./invoke-double-tap-action\";\n\nconst defaultOptions: DoubleTapOptions = {\n eventPointerTypes: [\"touch\", \"mouse\", \"pen\"],\n eventCapture: false,\n eventOnce: false,\n eventStopImmediatePropagation: false,\n delay: 300,\n threshold: 8,\n container: { current: null },\n};\n\nconst useDoubleTap = (\n doubleTapCallback: UseDoubleTapCallback,\n options: UseDoubleTapOptions = {},\n) => {\n const {\n eventPointerTypes,\n eventCapture,\n eventOnce,\n eventStopImmediatePropagation,\n delay,\n threshold,\n container,\n } = { ...defaultOptions, ...options };\n\n const targetReference = useRef<EventTarget | null>(null);\n const abortControllerReference = useRef<AbortController | null>(null);\n\n const lastTapReference = useRef<{\n time: number;\n x: number;\n y: number;\n } | null>(null);\n\n const handlePointerUp = useCallback(\n (event: PointerEvent) => {\n if (!event.isPrimary) {\n return;\n }\n if (\n !eventPointerTypes.includes(\n event.pointerType as DoubleTapEventPointerType,\n )\n ) {\n return;\n }\n\n const now = Date.now();\n\n if (!lastTapReference.current) {\n lastTapReference.current = {\n time: now,\n x: event.clientX,\n y: event.clientY,\n };\n return;\n }\n\n const deltaTime = now - lastTapReference.current.time;\n const deltaX = event.clientX - lastTapReference.current.x;\n const deltaY = event.clientY - lastTapReference.current.y;\n\n if (deltaTime <= delay && Math.hypot(deltaX, deltaY) <= threshold) {\n const data: DoubleTapData = {\n x: event.clientX,\n y: event.clientY,\n };\n\n invokeDoubleTapAction(event, data, doubleTapCallback, {\n stopImmediate: eventStopImmediatePropagation,\n once: eventOnce,\n onOnce: () => abortControllerReference.current?.abort(),\n });\n\n lastTapReference.current = null;\n return;\n }\n\n lastTapReference.current = {\n time: now,\n x: event.clientX,\n y: event.clientY,\n };\n },\n [\n doubleTapCallback,\n delay,\n threshold,\n eventPointerTypes,\n eventOnce,\n eventStopImmediatePropagation,\n ],\n );\n\n useEffect(() => {\n targetReference.current = container?.current ?? globalThis;\n abortControllerReference.current = new AbortController();\n const { signal } = abortControllerReference.current;\n\n const pointerUpListener = (event: Event) =>\n event instanceof PointerEvent && handlePointerUp(event);\n\n targetReference.current.addEventListener(\"pointerup\", pointerUpListener, {\n capture: eventCapture,\n signal,\n });\n\n return () => {\n abortControllerReference.current?.abort();\n lastTapReference.current = null;\n };\n }, [container, eventCapture, handlePointerUp]);\n};\n\nexport default useDoubleTap;\n"],"names":["defaultOptions","useDoubleTap","doubleTapCallback","options","eventPointerTypes","eventCapture","eventOnce","eventStopImmediatePropagation","delay","threshold","container","targetReference","useRef","abortControllerReference","lastTapReference","handlePointerUp","useCallback","event","now","deltaTime","deltaX","deltaY","data","invokeDoubleTapAction","useEffect","signal","pointerUpListener"],"mappings":";;AAUA,MAAMA,IAAmC;AAAA,EACvC,mBAAmB,CAAC,SAAS,SAAS,KAAK;AAAA,EAC3C,cAAc;AAAA,EACd,WAAW;AAAA,EACX,+BAA+B;AAAA,EAC/B,OAAO;AAAA,EACP,WAAW;AAAA,EACX,WAAW,EAAE,SAAS,KAAA;AACxB,GAEMC,IAAe,CACnBC,GACAC,IAA+B,OAC5B;AACH,QAAM;AAAA,IACJ,mBAAAC;AAAA,IACA,cAAAC;AAAA,IACA,WAAAC;AAAA,IACA,+BAAAC;AAAA,IACA,OAAAC;AAAA,IACA,WAAAC;AAAA,IACA,WAAAC;AAAA,EAAA,IACE,EAAE,GAAGV,GAAgB,GAAGG,EAAA,GAEtBQ,IAAkBC,EAA2B,IAAI,GACjDC,IAA2BD,EAA+B,IAAI,GAE9DE,IAAmBF,EAIf,IAAI,GAERG,IAAkBC;AAAA,IACtB,CAACC,MAAwB;AAIvB,UAHI,CAACA,EAAM,aAIT,CAACb,EAAkB;AAAA,QACjBa,EAAM;AAAA,MAAA;AAGR;AAGF,YAAMC,IAAM,KAAK,IAAA;AAEjB,UAAI,CAACJ,EAAiB,SAAS;AAC7B,QAAAA,EAAiB,UAAU;AAAA,UACzB,MAAMI;AAAA,UACN,GAAGD,EAAM;AAAA,UACT,GAAGA,EAAM;AAAA,QAAA;AAEX;AAAA,MACF;AAEA,YAAME,IAAYD,IAAMJ,EAAiB,QAAQ,MAC3CM,IAASH,EAAM,UAAUH,EAAiB,QAAQ,GAClDO,IAASJ,EAAM,UAAUH,EAAiB,QAAQ;AAExD,UAAIK,KAAaX,KAAS,KAAK,MAAMY,GAAQC,CAAM,KAAKZ,GAAW;AACjE,cAAMa,IAAsB;AAAA,UAC1B,GAAGL,EAAM;AAAA,UACT,GAAGA,EAAM;AAAA,QAAA;AAGX,QAAAM,EAAsBN,GAAOK,GAAMpB,GAAmB;AAAA,UACpD,eAAeK;AAAA,UACf,MAAMD;AAAA,UACN,QAAQ,MAAMO,EAAyB,SAAS,MAAA;AAAA,QAAM,CACvD,GAEDC,EAAiB,UAAU;AAC3B;AAAA,MACF;AAEA,MAAAA,EAAiB,UAAU;AAAA,QACzB,MAAMI;AAAA,QACN,GAAGD,EAAM;AAAA,QACT,GAAGA,EAAM;AAAA,MAAA;AAAA,IAEb;AAAA,IACA;AAAA,MACEf;AAAA,MACAM;AAAA,MACAC;AAAA,MACAL;AAAA,MACAE;AAAA,MACAC;AAAA,IAAA;AAAA,EACF;AAGF,EAAAiB,EAAU,MAAM;AACd,IAAAb,EAAgB,UAAUD,GAAW,WAAW,YAChDG,EAAyB,UAAU,IAAI,gBAAA;AACvC,UAAM,EAAE,QAAAY,MAAWZ,EAAyB,SAEtCa,IAAoB,CAACT,MACzBA,aAAiB,gBAAgBF,EAAgBE,CAAK;AAExD,WAAAN,EAAgB,QAAQ,iBAAiB,aAAae,GAAmB;AAAA,MACvE,SAASrB;AAAA,MACT,QAAAoB;AAAA,IAAA,CACD,GAEM,MAAM;AACX,MAAAZ,EAAyB,SAAS,MAAA,GAClCC,EAAiB,UAAU;AAAA,IAC7B;AAAA,EACF,GAAG,CAACJ,GAAWL,GAAcU,CAAe,CAAC;AAC/C;"}
@@ -0,0 +1,9 @@
1
+ const e = {
2
+ Touch: "touch",
3
+ Mouse: "mouse",
4
+ Pen: "pen"
5
+ };
6
+ export {
7
+ e as DoubleTapEventPointerTypes
8
+ };
9
+ //# sourceMappingURL=use-double-tap.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-double-tap.types.js","sources":["../../src/use-double-tap/use-double-tap.types.ts"],"sourcesContent":["export const DoubleTapEventPointerTypes = {\n Touch: \"touch\",\n Mouse: \"mouse\",\n Pen: \"pen\",\n} as const;\n\nexport type DoubleTapEventPointerType =\n (typeof DoubleTapEventPointerTypes)[keyof typeof DoubleTapEventPointerTypes];\n\nexport interface DoubleTapData {\n x: number;\n y: number;\n}\n\nexport interface DoubleTapOptions {\n eventPointerTypes: DoubleTapEventPointerType[];\n eventCapture: boolean;\n eventOnce: boolean;\n eventStopImmediatePropagation: boolean;\n delay: number;\n threshold: number;\n container: { current: EventTarget | null };\n}\n\nexport type UseDoubleTapCallback =\n | ((event: PointerEvent, data: DoubleTapData) => boolean)\n | ((event: PointerEvent, data: DoubleTapData) => void);\n\nexport type UseDoubleTapOptions = Partial<DoubleTapOptions>;\n"],"names":["DoubleTapEventPointerTypes"],"mappings":"AAAO,MAAMA,IAA6B;AAAA,EACxC,OAAO;AAAA,EACP,OAAO;AAAA,EACP,KAAK;AACP;"}