@msobiecki/react-marauders-path 1.24.0 → 1.24.2
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/dist/index.d.ts +276 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/use-drag/invoke-drag-action.js +7 -0
- package/dist/use-drag/invoke-drag-action.js.map +1 -0
- package/dist/use-drag/use-drag.js +141 -0
- package/dist/use-drag/use-drag.js.map +1 -0
- package/dist/use-drag/use-drag.types.js +9 -0
- package/dist/use-drag/use-drag.types.js.map +1 -0
- package/dist/use-key/event-guards.js +5 -0
- package/dist/use-key/event-guards.js.map +1 -0
- package/dist/use-key/invoke-key-action.js +7 -0
- package/dist/use-key/invoke-key-action.js.map +1 -0
- package/dist/use-key/normalize-key.js +43 -0
- package/dist/use-key/normalize-key.js.map +1 -0
- package/dist/use-key/parse-key-sequences.js +16 -0
- package/dist/use-key/parse-key-sequences.js.map +1 -0
- package/dist/use-key/sequence-state.js +25 -0
- package/dist/use-key/sequence-state.js.map +1 -0
- package/dist/use-key/use-key.js +206 -0
- package/dist/use-key/use-key.js.map +1 -0
- package/dist/use-key/use-key.types.js +8 -0
- package/dist/use-key/use-key.types.js.map +1 -0
- package/dist/use-pinch/invoke-pinch-action.js +7 -0
- package/dist/use-pinch/invoke-pinch-action.js.map +1 -0
- package/dist/use-pinch/use-pinch.js +131 -0
- package/dist/use-pinch/use-pinch.js.map +1 -0
- package/dist/use-pinch/use-pinch.types.js +9 -0
- package/dist/use-pinch/use-pinch.types.js.map +1 -0
- package/dist/use-swipe/invoke-swipe-action.js +7 -0
- package/dist/use-swipe/invoke-swipe-action.js.map +1 -0
- package/dist/use-swipe/parse-swipe-direction.js +5 -0
- package/dist/use-swipe/parse-swipe-direction.js.map +1 -0
- package/dist/use-swipe/use-swipe.js +134 -0
- package/dist/use-swipe/use-swipe.js.map +1 -0
- package/dist/use-swipe/use-swipe.types.js +18 -0
- package/dist/use-swipe/use-swipe.types.js.map +1 -0
- package/dist/use-wheel/invoke-wheel-action.js +7 -0
- package/dist/use-wheel/invoke-wheel-action.js.map +1 -0
- package/dist/use-wheel/use-wheel.js +79 -0
- package/dist/use-wheel/use-wheel.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { useRef as w, useCallback as s, useEffect as H } from "react";
|
|
2
|
+
import { KeyEventTypes as T } from "./use-key.types.js";
|
|
3
|
+
import { parseKeySequences as F } from "./parse-key-sequences.js";
|
|
4
|
+
import { resetSequenceState as G, advanceSequenceState as _ } from "./sequence-state.js";
|
|
5
|
+
import { invokeKeyAction as P } from "./invoke-key-action.js";
|
|
6
|
+
import { shouldHandleKeyboardEvent as J } from "./event-guards.js";
|
|
7
|
+
import { SPECIAL_KEYS as u } from "./normalize-key.js";
|
|
8
|
+
const j = {
|
|
9
|
+
eventType: T.KeyUp,
|
|
10
|
+
eventRepeat: !1,
|
|
11
|
+
eventCapture: !1,
|
|
12
|
+
eventOnce: !1,
|
|
13
|
+
eventStopImmediatePropagation: !1,
|
|
14
|
+
sequenceThreshold: 1e3,
|
|
15
|
+
combinationThreshold: 200,
|
|
16
|
+
container: { current: null }
|
|
17
|
+
}, ne = (L, f, B = j) => {
|
|
18
|
+
const {
|
|
19
|
+
eventType: d,
|
|
20
|
+
eventRepeat: R,
|
|
21
|
+
eventCapture: A,
|
|
22
|
+
eventOnce: m,
|
|
23
|
+
eventStopImmediatePropagation: p,
|
|
24
|
+
sequenceThreshold: b,
|
|
25
|
+
combinationThreshold: K,
|
|
26
|
+
container: C
|
|
27
|
+
} = { ...j, ...B }, S = w(null), l = w(null), y = w({
|
|
28
|
+
activeKeys: /* @__PURE__ */ new Map()
|
|
29
|
+
}), c = w([]), h = s(() => {
|
|
30
|
+
l.current && l.current.abort();
|
|
31
|
+
}, []), D = s(() => {
|
|
32
|
+
y.current.activeKeys.clear();
|
|
33
|
+
}, []), i = s((e) => {
|
|
34
|
+
c.current = G(
|
|
35
|
+
e,
|
|
36
|
+
c.current
|
|
37
|
+
);
|
|
38
|
+
}, []), I = s(
|
|
39
|
+
(e) => J(e, {
|
|
40
|
+
repeat: R
|
|
41
|
+
}),
|
|
42
|
+
[R]
|
|
43
|
+
), O = s((e) => {
|
|
44
|
+
const t = e.key === " " ? u.SPACE : e.key;
|
|
45
|
+
y.current.activeKeys.set(t, {
|
|
46
|
+
pressedAt: Date.now()
|
|
47
|
+
});
|
|
48
|
+
}, []), z = s((e) => {
|
|
49
|
+
const t = e.key === " " ? u.SPACE : e.key, n = y.current.activeKeys.get(t);
|
|
50
|
+
n && (n.releasedAt = Date.now());
|
|
51
|
+
}, []), k = s(() => {
|
|
52
|
+
const e = Date.now(), t = y.current;
|
|
53
|
+
[...t.activeKeys.entries()].forEach(([n, r]) => {
|
|
54
|
+
d === T.KeyDown ? r.releasedAt && t.activeKeys.delete(n) : r.releasedAt && e - r.releasedAt > K && t.activeKeys.delete(n);
|
|
55
|
+
});
|
|
56
|
+
}, [d, K]), E = s(
|
|
57
|
+
(e, t) => {
|
|
58
|
+
if (d === T.KeyDown)
|
|
59
|
+
return t.size === e.length && e.every((n) => n === u.ANY ? t.size > 0 : t.has(n));
|
|
60
|
+
if (d === T.KeyUp) {
|
|
61
|
+
const n = e.map((o) => {
|
|
62
|
+
if (o === u.ANY) {
|
|
63
|
+
const U = [...t.entries()].at(-1);
|
|
64
|
+
return U ? U[1] : void 0;
|
|
65
|
+
}
|
|
66
|
+
return t.get(o);
|
|
67
|
+
});
|
|
68
|
+
if (n.some((o) => !o?.releasedAt))
|
|
69
|
+
return !1;
|
|
70
|
+
const r = n.map((o) => o?.pressedAt).filter((o) => o !== void 0), a = n.map((o) => o?.releasedAt).filter((o) => o !== void 0), g = Math.min(...a), x = Math.max(...a);
|
|
71
|
+
return !(Math.max(...r) > g || x - g > K);
|
|
72
|
+
}
|
|
73
|
+
return !1;
|
|
74
|
+
},
|
|
75
|
+
[d, K]
|
|
76
|
+
), q = s(
|
|
77
|
+
(e, t) => {
|
|
78
|
+
const n = t.chord[0];
|
|
79
|
+
if (Array.isArray(n)) {
|
|
80
|
+
const { activeKeys: a } = y.current;
|
|
81
|
+
if (!E(n, a))
|
|
82
|
+
return;
|
|
83
|
+
P(e, t.key, f, {
|
|
84
|
+
stopImmediate: p,
|
|
85
|
+
once: m,
|
|
86
|
+
onOnce: () => {
|
|
87
|
+
h();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const r = e.key === " " ? u.SPACE : e.key;
|
|
93
|
+
n !== u.ANY && n !== r || P(e, t.key, f, {
|
|
94
|
+
stopImmediate: p,
|
|
95
|
+
once: m,
|
|
96
|
+
onOnce: () => {
|
|
97
|
+
h();
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
},
|
|
101
|
+
[
|
|
102
|
+
p,
|
|
103
|
+
m,
|
|
104
|
+
f,
|
|
105
|
+
E,
|
|
106
|
+
h
|
|
107
|
+
]
|
|
108
|
+
), Y = s(
|
|
109
|
+
(e, t) => {
|
|
110
|
+
const n = t.chord[t.index];
|
|
111
|
+
if (Array.isArray(n)) {
|
|
112
|
+
const { activeKeys: x } = y.current;
|
|
113
|
+
if (!E(n, x))
|
|
114
|
+
return;
|
|
115
|
+
const [v, o] = _(
|
|
116
|
+
t,
|
|
117
|
+
c.current,
|
|
118
|
+
b,
|
|
119
|
+
i
|
|
120
|
+
);
|
|
121
|
+
c.current = o, v.index === v.chord.length && (P(e, v.key, f, {
|
|
122
|
+
stopImmediate: p,
|
|
123
|
+
once: m,
|
|
124
|
+
onOnce: () => {
|
|
125
|
+
h();
|
|
126
|
+
}
|
|
127
|
+
}), i(v));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const r = e.key === " " ? u.SPACE : e.key;
|
|
131
|
+
if (n !== u.ANY && n !== r) {
|
|
132
|
+
i(t);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const [a, g] = _(
|
|
136
|
+
t,
|
|
137
|
+
c.current,
|
|
138
|
+
b,
|
|
139
|
+
i
|
|
140
|
+
);
|
|
141
|
+
c.current = g, a.index === a.chord.length && (P(e, a.key, f, {
|
|
142
|
+
stopImmediate: p,
|
|
143
|
+
once: m,
|
|
144
|
+
onOnce: () => {
|
|
145
|
+
h();
|
|
146
|
+
}
|
|
147
|
+
}), i(a));
|
|
148
|
+
},
|
|
149
|
+
[
|
|
150
|
+
m,
|
|
151
|
+
p,
|
|
152
|
+
b,
|
|
153
|
+
f,
|
|
154
|
+
i,
|
|
155
|
+
E,
|
|
156
|
+
h
|
|
157
|
+
]
|
|
158
|
+
), M = s(
|
|
159
|
+
(e) => {
|
|
160
|
+
c.current.forEach((t) => {
|
|
161
|
+
t.chord.length === 1 ? q(e, t) : Y(e, t);
|
|
162
|
+
});
|
|
163
|
+
},
|
|
164
|
+
[q, Y]
|
|
165
|
+
), N = s(
|
|
166
|
+
(e) => {
|
|
167
|
+
I(e) && (k(), M(e));
|
|
168
|
+
},
|
|
169
|
+
[I, k, M]
|
|
170
|
+
);
|
|
171
|
+
H(() => {
|
|
172
|
+
c.current = F(L);
|
|
173
|
+
}, [L]), H(() => {
|
|
174
|
+
S.current = C?.current ?? globalThis, l.current = new AbortController();
|
|
175
|
+
const e = (r) => O(r);
|
|
176
|
+
S.current.addEventListener("keydown", e, {
|
|
177
|
+
capture: A,
|
|
178
|
+
signal: l.current.signal
|
|
179
|
+
});
|
|
180
|
+
const t = (r) => z(r);
|
|
181
|
+
S.current.addEventListener("keyup", t, {
|
|
182
|
+
capture: A,
|
|
183
|
+
signal: l.current.signal
|
|
184
|
+
});
|
|
185
|
+
const n = (r) => N(r);
|
|
186
|
+
return S.current.addEventListener(d, n, {
|
|
187
|
+
capture: A,
|
|
188
|
+
signal: l.current.signal
|
|
189
|
+
}), () => {
|
|
190
|
+
l.current?.abort(), D(), c.current.forEach((r) => i(r));
|
|
191
|
+
};
|
|
192
|
+
}, [
|
|
193
|
+
d,
|
|
194
|
+
A,
|
|
195
|
+
C,
|
|
196
|
+
O,
|
|
197
|
+
z,
|
|
198
|
+
N,
|
|
199
|
+
D,
|
|
200
|
+
i
|
|
201
|
+
]);
|
|
202
|
+
};
|
|
203
|
+
export {
|
|
204
|
+
ne as default
|
|
205
|
+
};
|
|
206
|
+
//# sourceMappingURL=use-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-key.js","sources":["../../src/use-key/use-key.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from \"react\";\n\nimport {\n KeyOptions,\n SequenceState,\n UseKeySchema,\n UseKeyCallback,\n UseKeyOptions,\n CombinationState,\n KeyEventTypes,\n} from \"./use-key.types\";\nimport { parseKeySequences } from \"./parse-key-sequences\";\nimport { advanceSequenceState, resetSequenceState } from \"./sequence-state\";\nimport { invokeKeyAction } from \"./invoke-key-action\";\nimport { shouldHandleKeyboardEvent } from \"./event-guards\";\nimport { SPECIAL_KEYS } from \"./normalize-key\";\n\nconst defaultOptions: KeyOptions = {\n eventType: KeyEventTypes.KeyUp,\n eventRepeat: false,\n eventCapture: false,\n eventOnce: false,\n eventStopImmediatePropagation: false,\n sequenceThreshold: 1000,\n combinationThreshold: 200,\n container: { current: null },\n};\n\n/**\n * React hook for handling keyboard events with support for key sequences and combinations.\n *\n * Enables listening for single key presses, key combinations, and sequential key presses.\n * Supports customizable options like event type, repeat handling, and one-time listeners.\n *\n * @template T - The callback function type\n * @param {UseKeySchema} key - Single key, combination, sequence, or array of patterns to listen for\n * @param {UseKeyCallback} keyCallback - Callback function invoked when key pattern matches\n * @param {UseKeyOptions} [options] - Configuration options for the hook\n * @param {KeyEventType} [options.eventType=KeyEventTypes.KeyUp] - Type of keyboard event ('keydown' or 'keyup')\n * @param {boolean} [options.eventRepeat=false] - Allow repeated key presses to trigger callback\n * @param {boolean} [options.eventCapture=false] - Use event capture phase instead of bubbling\n * @param {boolean} [options.eventOnce=false] - Trigger callback only once\n * @param {boolean} [options.eventStopImmediatePropagation=false] - Stop immediate propagation\n * @param {number} [options.sequenceThreshold=1000] - Timeout in ms between sequence keys\n * @param {number} [options.combinationThreshold=200] - Timeout in ms between combination keys\n * @param {RefObject<HTMLElement>} [options.container] - DOM element to attach listener to (default: window)\n *\n * @example\n * // Single key schema\n * useKey('a', (event, key) => console.log(`Pressed ${key}`));\n *\n * @example\n * // Multiple patterns of single key schema\n * useKey(['a', 'b', 'c'], (event, key) => console.log(`Pressed ${key}`));\n *\n * @example\n * // Combination key schema\n * useKey('a+b', (event, key) => {\n * console.log(`Pressed ${key}`);\n * });\n *\n * @example\n * // Multiple patterns of combination key schema\n * useKey(['a+b', 'c+d'], (event, key) => {\n * console.log(`Pressed ${key}`);\n * });\n *\n * @example\n * // Sequential key schema\n * useKey('ArrowUp ArrowUp ArrowDown ArrowDown', (event, key) => {\n * console.log(`Pressed ${key}`);\n * });\n *\n * @example\n * // Multiple patterns of sequential key schema\n * useKey(['ArrowUp ArrowUp ArrowDown ArrowDown', 'ArrowLeft ArrowRight'], (event, key) => {\n * console.log(`Pressed ${key}`);\n * });\n *\n * @example\n * // Using options to listen for a key on keydown event and stop propagation\n * useKey('Any', handleSubmit, {\n * eventType: KeyEventTypes.KeyDown,\n * eventStopImmediatePropagation: true,\n * container: inputRef\n * });\n *\n */\nconst useKey = (\n key: UseKeySchema,\n keyCallback: UseKeyCallback,\n options: UseKeyOptions = defaultOptions,\n) => {\n const {\n eventType,\n eventRepeat,\n eventCapture,\n eventOnce,\n eventStopImmediatePropagation,\n sequenceThreshold,\n combinationThreshold,\n container,\n } = { ...defaultOptions, ...options };\n\n const targetReference = useRef<EventTarget | null>(null);\n const abortControllerReference = useRef<AbortController | null>(null);\n\n const combinationReference = useRef<CombinationState>({\n activeKeys: new Map(),\n });\n const sequenceReference = useRef<SequenceState[]>([]);\n\n const destroyListener = useCallback(() => {\n if (abortControllerReference.current) {\n abortControllerReference.current.abort();\n }\n }, []);\n\n const resetCombination = useCallback(() => {\n combinationReference.current.activeKeys.clear();\n }, []);\n\n const resetSequence = useCallback((sequence: SequenceState) => {\n sequenceReference.current = resetSequenceState(\n sequence,\n sequenceReference.current,\n );\n }, []);\n\n const shouldProcessEvent = useCallback(\n (event: KeyboardEvent) => {\n return shouldHandleKeyboardEvent(event, {\n repeat: eventRepeat,\n });\n },\n [eventRepeat],\n );\n\n const registerKeyDown = useCallback((event: KeyboardEvent) => {\n const normalizedEventKey =\n event.key === \" \" ? SPECIAL_KEYS.SPACE : event.key;\n combinationReference.current.activeKeys.set(normalizedEventKey, {\n pressedAt: Date.now(),\n });\n }, []);\n\n const registerKeyUp = useCallback((event: KeyboardEvent) => {\n const normalizedEventKey =\n event.key === \" \" ? SPECIAL_KEYS.SPACE : event.key;\n const state =\n combinationReference.current.activeKeys.get(normalizedEventKey);\n if (state) state.releasedAt = Date.now();\n }, []);\n\n const cleanupCombinationKeys = useCallback(() => {\n const now = Date.now();\n const combo = combinationReference.current;\n\n [...combo.activeKeys.entries()].forEach(([key, state]) => {\n if (eventType === KeyEventTypes.KeyDown) {\n if (state.releasedAt) {\n combo.activeKeys.delete(key);\n }\n } else if (\n state.releasedAt &&\n now - state.releasedAt > combinationThreshold\n ) {\n combo.activeKeys.delete(key);\n }\n });\n }, [eventType, combinationThreshold]);\n\n const validateCombination = useCallback(\n (\n expectedKey: string[],\n activeKeys: Map<string, { pressedAt: number; releasedAt?: number }>,\n ): boolean => {\n if (eventType === KeyEventTypes.KeyDown) {\n return (\n activeKeys.size === expectedKey.length &&\n expectedKey.every((key) => {\n if (key === SPECIAL_KEYS.ANY) {\n return activeKeys.size > 0;\n }\n return activeKeys.has(key);\n })\n );\n }\n if (eventType === KeyEventTypes.KeyUp) {\n const keyStates = expectedKey.map((key) => {\n if (key === SPECIAL_KEYS.ANY) {\n const entries = [...activeKeys.entries()];\n const lastEntry = entries.at(-1);\n return lastEntry ? lastEntry[1] : undefined;\n }\n return activeKeys.get(key);\n });\n\n if (keyStates.some((state) => !state?.releasedAt)) {\n return false;\n }\n\n const pressedTimes: number[] = keyStates\n .map((state) => state?.pressedAt)\n .filter((value): value is number => value !== undefined);\n const releasedTimes: number[] = keyStates\n .map((state) => state?.releasedAt)\n .filter((value): value is number => value !== undefined);\n\n const minReleased = Math.min(...releasedTimes);\n const maxReleased = Math.max(...releasedTimes);\n const maxPressed = Math.max(...pressedTimes);\n\n if (maxPressed > minReleased) {\n return false;\n }\n\n if (maxReleased - minReleased > combinationThreshold) {\n return false;\n }\n\n return true;\n }\n\n return false;\n },\n [eventType, combinationThreshold],\n );\n\n const handleSingleKey = useCallback(\n (event: KeyboardEvent, sequence: SequenceState) => {\n const expectedKey = sequence.chord[0];\n\n if (Array.isArray(expectedKey)) {\n const { activeKeys } = combinationReference.current;\n\n if (!validateCombination(expectedKey, activeKeys)) {\n return;\n }\n\n invokeKeyAction(event, sequence.key, keyCallback, {\n stopImmediate: eventStopImmediatePropagation,\n once: eventOnce,\n onOnce: () => {\n destroyListener();\n },\n });\n\n return;\n }\n\n const normalizedEventKey =\n event.key === \" \" ? SPECIAL_KEYS.SPACE : event.key;\n if (\n expectedKey !== SPECIAL_KEYS.ANY &&\n expectedKey !== normalizedEventKey\n ) {\n return;\n }\n\n invokeKeyAction(event, sequence.key, keyCallback, {\n stopImmediate: eventStopImmediatePropagation,\n once: eventOnce,\n onOnce: () => {\n destroyListener();\n },\n });\n },\n [\n eventStopImmediatePropagation,\n eventOnce,\n keyCallback,\n validateCombination,\n destroyListener,\n ],\n );\n\n const handleSequenceStep = useCallback(\n (event: KeyboardEvent, sequence: SequenceState) => {\n const expectedKey = sequence.chord[sequence.index];\n\n if (Array.isArray(expectedKey)) {\n const { activeKeys } = combinationReference.current;\n\n if (!validateCombination(expectedKey, activeKeys)) {\n return;\n }\n\n const [updatedSequence, updatedSequences] = advanceSequenceState(\n sequence,\n sequenceReference.current,\n sequenceThreshold,\n resetSequence,\n );\n sequenceReference.current = updatedSequences;\n\n if (updatedSequence.index === updatedSequence.chord.length) {\n invokeKeyAction(event, updatedSequence.key, keyCallback, {\n stopImmediate: eventStopImmediatePropagation,\n once: eventOnce,\n onOnce: () => {\n destroyListener();\n },\n });\n\n resetSequence(updatedSequence);\n }\n\n return;\n }\n\n const normalizedEventKey =\n event.key === \" \" ? SPECIAL_KEYS.SPACE : event.key;\n if (\n expectedKey !== SPECIAL_KEYS.ANY &&\n expectedKey !== normalizedEventKey\n ) {\n resetSequence(sequence);\n return;\n }\n\n const [updatedSequence, updatedSequences] = advanceSequenceState(\n sequence,\n sequenceReference.current,\n sequenceThreshold,\n resetSequence,\n );\n sequenceReference.current = updatedSequences;\n\n if (updatedSequence.index === updatedSequence.chord.length) {\n invokeKeyAction(event, updatedSequence.key, keyCallback, {\n stopImmediate: eventStopImmediatePropagation,\n once: eventOnce,\n onOnce: () => {\n destroyListener();\n },\n });\n\n resetSequence(updatedSequence);\n }\n },\n [\n eventOnce,\n eventStopImmediatePropagation,\n sequenceThreshold,\n keyCallback,\n resetSequence,\n validateCombination,\n destroyListener,\n ],\n );\n\n const evaluateSequences = useCallback(\n (event: KeyboardEvent) => {\n sequenceReference.current.forEach((sequence) => {\n if (sequence.chord.length === 1) {\n handleSingleKey(event, sequence);\n } else {\n handleSequenceStep(event, sequence);\n }\n });\n },\n [handleSingleKey, handleSequenceStep],\n );\n\n const handleEventListener = useCallback(\n (event: KeyboardEvent) => {\n if (!shouldProcessEvent(event)) {\n return;\n }\n\n cleanupCombinationKeys();\n evaluateSequences(event);\n },\n [shouldProcessEvent, cleanupCombinationKeys, evaluateSequences],\n );\n\n useEffect(() => {\n sequenceReference.current = parseKeySequences(key);\n }, [key]);\n\n useEffect(() => {\n targetReference.current = container?.current ?? globalThis;\n abortControllerReference.current = new AbortController();\n\n const keyDownListener = (event: Event) =>\n registerKeyDown(event as KeyboardEvent);\n targetReference.current.addEventListener(\"keydown\", keyDownListener, {\n capture: eventCapture,\n signal: abortControllerReference.current.signal,\n });\n\n const keyUpListener = (event: Event) =>\n registerKeyUp(event as KeyboardEvent);\n targetReference.current.addEventListener(\"keyup\", keyUpListener, {\n capture: eventCapture,\n signal: abortControllerReference.current.signal,\n });\n\n const eventListener = (event: Event) =>\n handleEventListener(event as KeyboardEvent);\n\n targetReference.current.addEventListener(eventType, eventListener, {\n capture: eventCapture,\n signal: abortControllerReference.current.signal,\n });\n\n return () => {\n abortControllerReference.current?.abort();\n\n resetCombination();\n sequenceReference.current.forEach((sequence) => resetSequence(sequence));\n };\n }, [\n eventType,\n eventCapture,\n container,\n registerKeyDown,\n registerKeyUp,\n handleEventListener,\n resetCombination,\n resetSequence,\n ]);\n};\n\nexport default useKey;\n"],"names":["defaultOptions","KeyEventTypes","useKey","key","keyCallback","options","eventType","eventRepeat","eventCapture","eventOnce","eventStopImmediatePropagation","sequenceThreshold","combinationThreshold","container","targetReference","useRef","abortControllerReference","combinationReference","sequenceReference","destroyListener","useCallback","resetCombination","resetSequence","sequence","resetSequenceState","shouldProcessEvent","event","shouldHandleKeyboardEvent","registerKeyDown","normalizedEventKey","SPECIAL_KEYS","registerKeyUp","state","cleanupCombinationKeys","now","combo","validateCombination","expectedKey","activeKeys","keyStates","lastEntry","pressedTimes","value","releasedTimes","minReleased","maxReleased","handleSingleKey","invokeKeyAction","handleSequenceStep","updatedSequence","updatedSequences","advanceSequenceState","evaluateSequences","handleEventListener","useEffect","parseKeySequences","keyDownListener","keyUpListener","eventListener"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-key.types.js","sources":["../../src/use-key/use-key.types.ts"],"sourcesContent":["import { RefObject } from \"react\";\n\nexport type Key = string;\n\nexport type KeyEvent = Key | Key[];\n\nexport const KeyEventTypes = {\n KeyUp: \"keyup\",\n KeyDown: \"keydown\",\n} as const;\n\nexport type KeyEventType = (typeof KeyEventTypes)[keyof typeof KeyEventTypes];\n\nexport interface KeyOptions {\n eventType: KeyEventType;\n eventRepeat: boolean;\n eventCapture: boolean;\n eventOnce: boolean;\n eventStopImmediatePropagation: boolean;\n sequenceThreshold: number;\n combinationThreshold: number;\n container: RefObject<HTMLElement | null>;\n}\n\nexport interface CombinationActiveKey {\n pressedAt: number;\n releasedAt?: number;\n}\n\nexport interface CombinationState {\n activeKeys: Map<Key, CombinationActiveKey>;\n}\n\nexport type KeyChord = (Key | Key[])[];\n\nexport interface SequenceState {\n key: Key;\n chord: KeyChord;\n index: number;\n sequenceTimeout: ReturnType<typeof setTimeout> | null;\n}\n\nexport type UseKeySchema = KeyEvent;\n\nexport type UseKeyCallback =\n | ((event: KeyboardEvent, key: Key, ...properties: unknown[]) => boolean)\n | ((event: KeyboardEvent, key: Key, ...properties: unknown[]) => void);\n\nexport type UseKeyOptions = Partial<KeyOptions>;\n"],"names":["KeyEventTypes"],"mappings":"AAMO,MAAMA,IAAgB;AAAA,EAC3B,OAAO;AAAA,EACP,SAAS;AACX;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoke-pinch-action.js","sources":["../../src/use-pinch/invoke-pinch-action.ts"],"sourcesContent":["import { PinchData } from \"./use-pinch.types\";\n\n/**\n * Invokes a pinch action callback with optional event modifications.\n *\n * Handles pinch event processing including preventing default behavior,\n * stopping immediate propagation, and managing one-time event handlers.\n *\n * @param {PointerEvent} event - The pinch event\n * @param {PinchData} data - The normalized pinch 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 * invokePinchAction(event, data, (e, d) => {\n * console.log(`Pinch moved: ${d.distance}, ${d.delta}, ${d.scale}`);\n * return true; // Prevent default\n * }, { stopImmediate: true });\n */\nexport const invokePinchAction = (\n event: PointerEvent,\n data: PinchData,\n callback:\n | ((event: PointerEvent, data: PinchData) => boolean)\n | ((event: PointerEvent, data: PinchData) => 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":["invokePinchAction","event","data","callback","options"],"mappings":"AAsBO,MAAMA,IAAoB,CAC/BC,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,131 @@
|
|
|
1
|
+
import { useRef as a, useCallback as l, useEffect as F } from "react";
|
|
2
|
+
import { invokePinchAction as A } from "./invoke-pinch-action.js";
|
|
3
|
+
const S = {
|
|
4
|
+
eventPointerTypes: ["touch"],
|
|
5
|
+
eventCapture: !1,
|
|
6
|
+
eventOnce: !1,
|
|
7
|
+
eventStopImmediatePropagation: !1,
|
|
8
|
+
threshold: 0,
|
|
9
|
+
container: { current: null },
|
|
10
|
+
raf: !1
|
|
11
|
+
}, x = (f, C = {}) => {
|
|
12
|
+
const {
|
|
13
|
+
eventPointerTypes: I,
|
|
14
|
+
eventCapture: u,
|
|
15
|
+
eventOnce: v,
|
|
16
|
+
eventStopImmediatePropagation: m,
|
|
17
|
+
threshold: L,
|
|
18
|
+
container: R,
|
|
19
|
+
raf: y
|
|
20
|
+
} = { ...S, ...C }, p = a(null), s = a(null), d = a(null), g = a(null), D = a(null), i = a({
|
|
21
|
+
pointers: /* @__PURE__ */ new Map(),
|
|
22
|
+
startDistance: 0,
|
|
23
|
+
lastDistance: 0,
|
|
24
|
+
active: !1
|
|
25
|
+
}), h = l(() => {
|
|
26
|
+
s.current?.abort();
|
|
27
|
+
}, []), E = l(() => {
|
|
28
|
+
d.current = null;
|
|
29
|
+
const t = g.current, e = D.current;
|
|
30
|
+
!t || !e || (A(e, t, f, {
|
|
31
|
+
stopImmediate: m,
|
|
32
|
+
once: v,
|
|
33
|
+
onOnce: () => h()
|
|
34
|
+
}), g.current = null, D.current = null);
|
|
35
|
+
}, [
|
|
36
|
+
f,
|
|
37
|
+
m,
|
|
38
|
+
v,
|
|
39
|
+
h
|
|
40
|
+
]), M = l(
|
|
41
|
+
(t) => {
|
|
42
|
+
if (!I.includes(t.pointerType))
|
|
43
|
+
return;
|
|
44
|
+
const e = i.current;
|
|
45
|
+
if (e.pointers.set(t.pointerId, t), e.pointers.size === 2) {
|
|
46
|
+
const [c, o] = [...e.pointers.values()], n = o.clientX - c.clientX, P = o.clientY - c.clientY, r = Math.hypot(n, P);
|
|
47
|
+
e.startDistance = r, e.lastDistance = r, e.active = !0;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
[I]
|
|
51
|
+
), X = l(
|
|
52
|
+
(t) => {
|
|
53
|
+
const e = i.current;
|
|
54
|
+
if (!e.active || !e.pointers.has(t.pointerId) || (e.pointers.set(t.pointerId, t), e.pointers.size < 2)) return;
|
|
55
|
+
const [c, o] = [...e.pointers.values()], n = o.clientX - c.clientX, P = o.clientY - c.clientY, r = Math.hypot(n, P), T = r - e.lastDistance, O = r - e.startDistance;
|
|
56
|
+
if (Math.abs(O) < L) return;
|
|
57
|
+
const z = r / e.startDistance, b = {
|
|
58
|
+
distance: r,
|
|
59
|
+
delta: T,
|
|
60
|
+
totalDelta: O,
|
|
61
|
+
scale: z
|
|
62
|
+
};
|
|
63
|
+
if (e.lastDistance = r, !y) {
|
|
64
|
+
A(t, b, f, {
|
|
65
|
+
stopImmediate: m,
|
|
66
|
+
once: v,
|
|
67
|
+
onOnce: () => h()
|
|
68
|
+
});
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
g.current = b, D.current = t, d.current === null && (d.current = requestAnimationFrame(E));
|
|
72
|
+
},
|
|
73
|
+
[
|
|
74
|
+
L,
|
|
75
|
+
y,
|
|
76
|
+
f,
|
|
77
|
+
m,
|
|
78
|
+
v,
|
|
79
|
+
h,
|
|
80
|
+
E
|
|
81
|
+
]
|
|
82
|
+
), Y = l((t) => {
|
|
83
|
+
const e = i.current;
|
|
84
|
+
e.pointers.delete(t.pointerId), e.pointers.size < 2 && (e.active = !1, e.startDistance = 0, e.lastDistance = 0);
|
|
85
|
+
}, []), w = l((t) => {
|
|
86
|
+
const e = i.current;
|
|
87
|
+
e.pointers.delete(t.pointerId), e.active = !1;
|
|
88
|
+
}, []);
|
|
89
|
+
F(() => {
|
|
90
|
+
p.current = R?.current ?? globalThis, s.current = new AbortController();
|
|
91
|
+
const t = (n) => M(n), e = (n) => X(n), c = (n) => Y(n), o = (n) => w(n);
|
|
92
|
+
return p.current.addEventListener(
|
|
93
|
+
"pointerdown",
|
|
94
|
+
t,
|
|
95
|
+
{
|
|
96
|
+
capture: u,
|
|
97
|
+
signal: s.current.signal
|
|
98
|
+
}
|
|
99
|
+
), p.current.addEventListener(
|
|
100
|
+
"pointermove",
|
|
101
|
+
e,
|
|
102
|
+
{
|
|
103
|
+
capture: u,
|
|
104
|
+
signal: s.current.signal
|
|
105
|
+
}
|
|
106
|
+
), p.current.addEventListener("pointerup", c, {
|
|
107
|
+
capture: u,
|
|
108
|
+
signal: s.current.signal
|
|
109
|
+
}), p.current.addEventListener(
|
|
110
|
+
"pointercancel",
|
|
111
|
+
o,
|
|
112
|
+
{
|
|
113
|
+
capture: u,
|
|
114
|
+
signal: s.current.signal
|
|
115
|
+
}
|
|
116
|
+
), () => {
|
|
117
|
+
s.current?.abort(), i.current.active = !1, i.current.pointers.clear(), d.current !== null && cancelAnimationFrame(d.current);
|
|
118
|
+
};
|
|
119
|
+
}, [
|
|
120
|
+
R,
|
|
121
|
+
u,
|
|
122
|
+
M,
|
|
123
|
+
X,
|
|
124
|
+
Y,
|
|
125
|
+
w
|
|
126
|
+
]);
|
|
127
|
+
};
|
|
128
|
+
export {
|
|
129
|
+
x as default
|
|
130
|
+
};
|
|
131
|
+
//# sourceMappingURL=use-pinch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-pinch.js","sources":["../../src/use-pinch/use-pinch.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from \"react\";\nimport {\n PinchState,\n PinchData,\n UsePinchCallback,\n UsePinchOptions,\n PinchOptions,\n PinchEventPointerType,\n} from \"./use-pinch.types\";\nimport { invokePinchAction } from \"./invoke-pinch-action\";\n\nconst defaultOptions: PinchOptions = {\n eventPointerTypes: [\"touch\"],\n eventCapture: false,\n eventOnce: false,\n eventStopImmediatePropagation: false,\n threshold: 0,\n container: { current: null },\n raf: false,\n};\n\nconst usePinch = (\n pinchCallback: UsePinchCallback,\n options: UsePinchOptions = {},\n) => {\n const {\n eventPointerTypes,\n eventCapture,\n eventOnce,\n eventStopImmediatePropagation,\n threshold,\n container,\n raf,\n } = { ...defaultOptions, ...options };\n\n const targetReference = useRef<EventTarget | null>(null);\n const abortControllerReference = useRef<AbortController | null>(null);\n\n const frameReference = useRef<number | null>(null);\n const pendingDataReference = useRef<PinchData | null>(null);\n const pendingEventReference = useRef<PointerEvent | null>(null);\n\n const pinchStateReference = useRef<PinchState>({\n pointers: new Map(),\n startDistance: 0,\n lastDistance: 0,\n active: false,\n });\n\n const destroyListener = useCallback(() => {\n abortControllerReference.current?.abort();\n }, []);\n\n const flushFrame = useCallback(() => {\n frameReference.current = null;\n\n const data = pendingDataReference.current;\n const event = pendingEventReference.current;\n\n if (!data || !event) return;\n\n invokePinchAction(event, data, pinchCallback, {\n stopImmediate: eventStopImmediatePropagation,\n once: eventOnce,\n onOnce: () => destroyListener(),\n });\n\n pendingDataReference.current = null;\n pendingEventReference.current = null;\n }, [\n pinchCallback,\n eventStopImmediatePropagation,\n eventOnce,\n destroyListener,\n ]);\n\n const handlePointerDown = useCallback(\n (event: PointerEvent) => {\n if (\n !eventPointerTypes.includes(event.pointerType as PinchEventPointerType)\n ) {\n return;\n }\n\n const state = pinchStateReference.current;\n\n state.pointers.set(event.pointerId, event);\n\n if (state.pointers.size === 2) {\n const [pointer1, pointer2] = [...state.pointers.values()];\n\n const deltaX = pointer2.clientX - pointer1.clientX;\n const deltaY = pointer2.clientY - pointer1.clientY;\n\n const distance = Math.hypot(deltaX, deltaY);\n\n state.startDistance = distance;\n state.lastDistance = distance;\n state.active = true;\n }\n },\n [eventPointerTypes],\n );\n\n const handlePointerMove = useCallback(\n (event: PointerEvent) => {\n const state = pinchStateReference.current;\n if (!state.active) return;\n\n if (!state.pointers.has(event.pointerId)) return;\n\n state.pointers.set(event.pointerId, event);\n\n if (state.pointers.size < 2) return;\n\n const [pointer1, pointer2] = [...state.pointers.values()];\n\n const deltaX = pointer2.clientX - pointer1.clientX;\n const deltaY = pointer2.clientY - pointer1.clientY;\n\n const distance = Math.hypot(deltaX, deltaY);\n\n const delta = distance - state.lastDistance;\n const totalDelta = distance - state.startDistance;\n\n if (Math.abs(totalDelta) < threshold) return;\n\n const scale = distance / state.startDistance;\n\n const data: PinchData = {\n distance,\n delta,\n totalDelta,\n scale,\n };\n\n state.lastDistance = distance;\n\n if (!raf) {\n invokePinchAction(event, data, pinchCallback, {\n stopImmediate: eventStopImmediatePropagation,\n once: eventOnce,\n onOnce: () => destroyListener(),\n });\n return;\n }\n\n pendingDataReference.current = data;\n pendingEventReference.current = event;\n\n if (frameReference.current === null) {\n frameReference.current = requestAnimationFrame(flushFrame);\n }\n },\n [\n threshold,\n raf,\n pinchCallback,\n eventStopImmediatePropagation,\n eventOnce,\n destroyListener,\n flushFrame,\n ],\n );\n\n const handlePointerUp = useCallback((event: PointerEvent) => {\n const state = pinchStateReference.current;\n\n state.pointers.delete(event.pointerId);\n\n if (state.pointers.size < 2) {\n state.active = false;\n state.startDistance = 0;\n state.lastDistance = 0;\n }\n }, []);\n\n const handlePointerCancel = useCallback((event: PointerEvent) => {\n const state = pinchStateReference.current;\n\n state.pointers.delete(event.pointerId);\n state.active = false;\n }, []);\n\n useEffect(() => {\n targetReference.current = container?.current ?? globalThis;\n abortControllerReference.current = new AbortController();\n\n const pointerDownListener = (event: Event) =>\n handlePointerDown(event as PointerEvent);\n\n const pointerMoveListener = (event: Event) =>\n handlePointerMove(event as PointerEvent);\n\n const pointerUpListener = (event: Event) =>\n handlePointerUp(event as PointerEvent);\n\n const pointerCancelListener = (event: Event) =>\n handlePointerCancel(event as PointerEvent);\n\n targetReference.current.addEventListener(\n \"pointerdown\",\n pointerDownListener,\n {\n capture: eventCapture,\n signal: abortControllerReference.current.signal,\n },\n );\n\n targetReference.current.addEventListener(\n \"pointermove\",\n pointerMoveListener,\n {\n capture: eventCapture,\n signal: abortControllerReference.current.signal,\n },\n );\n\n targetReference.current.addEventListener(\"pointerup\", pointerUpListener, {\n capture: eventCapture,\n signal: abortControllerReference.current.signal,\n });\n\n targetReference.current.addEventListener(\n \"pointercancel\",\n pointerCancelListener,\n {\n capture: eventCapture,\n signal: abortControllerReference.current.signal,\n },\n );\n\n return () => {\n abortControllerReference.current?.abort();\n pinchStateReference.current.active = false;\n pinchStateReference.current.pointers.clear();\n\n if (frameReference.current !== null) {\n cancelAnimationFrame(frameReference.current);\n }\n };\n }, [\n container,\n eventCapture,\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n handlePointerCancel,\n ]);\n};\n\nexport default usePinch;\n"],"names":["defaultOptions","usePinch","pinchCallback","options","eventPointerTypes","eventCapture","eventOnce","eventStopImmediatePropagation","threshold","container","raf","targetReference","useRef","abortControllerReference","frameReference","pendingDataReference","pendingEventReference","pinchStateReference","destroyListener","useCallback","flushFrame","data","event","invokePinchAction","handlePointerDown","state","pointer1","pointer2","deltaX","deltaY","distance","handlePointerMove","delta","totalDelta","scale","handlePointerUp","handlePointerCancel","useEffect","pointerDownListener","pointerMoveListener","pointerUpListener","pointerCancelListener"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-pinch.types.js","sources":["../../src/use-pinch/use-pinch.types.ts"],"sourcesContent":["export interface PinchState {\n pointers: Map<number, PointerEvent>;\n startDistance: number;\n lastDistance: number;\n active: boolean;\n}\n\nexport const PinchEventPointerTypes = {\n Touch: \"touch\",\n Mouse: \"mouse\",\n Pen: \"pen\",\n} as const;\n\nexport type PinchEventPointerType =\n (typeof PinchEventPointerTypes)[keyof typeof PinchEventPointerTypes];\n\nexport interface PinchOptions {\n eventPointerTypes: PinchEventPointerType[];\n eventCapture: boolean;\n eventOnce: boolean;\n eventStopImmediatePropagation: boolean;\n threshold: number;\n container: { current: HTMLElement | null };\n raf: boolean;\n}\n\nexport interface PinchData {\n distance: number;\n delta: number;\n totalDelta: number;\n scale: number;\n}\n\nexport type UsePinchCallback =\n | ((event: PointerEvent, data: PinchData) => boolean)\n | ((event: PointerEvent, data: PinchData) => void);\n\nexport type UsePinchOptions = Partial<PinchOptions>;\n"],"names":["PinchEventPointerTypes"],"mappings":"AAOO,MAAMA,IAAyB;AAAA,EACpC,OAAO;AAAA,EACP,OAAO;AAAA,EACP,KAAK;AACP;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoke-swipe-action.js","sources":["../../src/use-swipe/invoke-swipe-action.ts"],"sourcesContent":["import { SwipeData, SwipeDirection } from \"./use-swipe.types\";\n\n/**\n * Invokes a swipe action callback with optional event modifications.\n *\n * Handles swipe event processing including preventing default behavior,\n * stopping immediate propagation, and managing one-time event handlers.\n *\n * @param {PointerEvent} event - The swipe event\n * @param {SwipeData} data - The normalized swipe 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 * invokeSwipeAction(event, data, (e, d) => {\n * console.log(`Swipe moved: ${d.x}, ${d.y}, ${d.z}`);\n * return true; // Prevent default\n * }, { stopImmediate: true });\n */\nexport const invokeSwipeAction = (\n event: PointerEvent,\n direction: SwipeDirection,\n data: SwipeData,\n callback:\n | ((\n event: PointerEvent,\n direction: SwipeDirection,\n data: SwipeData,\n ) => boolean)\n | ((\n event: PointerEvent,\n direction: SwipeDirection,\n data: SwipeData,\n ) => 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, direction, data);\n if (shouldPrevent) {\n event.preventDefault();\n }\n\n if (options.once) {\n options.onOnce?.();\n }\n};\n"],"names":["invokeSwipeAction","event","direction","data","callback","options"],"mappings":"AAsBO,MAAMA,IAAoB,CAC/BC,GACAC,GACAC,GACAC,GAWAC,MAKG;AACH,EAAIA,EAAQ,iBACVJ,EAAM,yBAAA,GAGcG,EAASH,GAAOC,GAAWC,CAAI,KAEnDF,EAAM,eAAA,GAGJI,EAAQ,QACVA,EAAQ,SAAA;AAEZ;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-swipe-direction.js","sources":["../../src/use-swipe/parse-swipe-direction.ts"],"sourcesContent":["import { SwipeDirection } from \"./use-swipe.types\";\n\n/**\n * Parses the swipe direction schema into an array of swipe directions.\n *\n * Converts a single SwipeDirection or an array of SwipeDirections into a consistent array format.\n * This allows the useSwipe hook to uniformly handle both single and multiple direction schemas.\n *\n * @param {SwipeDirection | SwipeDirection[]} input - The swipe direction(s) to parse\n * @returns {SwipeDirection[]} An array of swipe directions\n *\n * @example\n * parseSwipeDirection('left') // ['left']\n * parseSwipeDirection(['left', 'up']) // ['left', 'up']\n */\nexport const parseSwipeDirection = (\n input: SwipeDirection | SwipeDirection[],\n): SwipeDirection[] => {\n return Array.isArray(input) ? input : [input];\n};\n"],"names":["parseSwipeDirection","input"],"mappings":"AAeO,MAAMA,IAAsB,CACjCC,MAEO,MAAM,QAAQA,CAAK,IAAIA,IAAQ,CAACA,CAAK;"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { useRef as p, useCallback as i, useEffect as O } from "react";
|
|
2
|
+
import { SwipeDirections as n } from "./use-swipe.types.js";
|
|
3
|
+
import { parseSwipeDirection as I } from "./parse-swipe-direction.js";
|
|
4
|
+
import { invokeSwipeAction as M } from "./invoke-swipe-action.js";
|
|
5
|
+
const A = {
|
|
6
|
+
eventPointerTypes: ["touch", "mouse", "pen"],
|
|
7
|
+
eventCapture: !1,
|
|
8
|
+
eventOnce: !1,
|
|
9
|
+
eventStopImmediatePropagation: !1,
|
|
10
|
+
threshold: 50,
|
|
11
|
+
velocity: 0.3,
|
|
12
|
+
container: { current: null }
|
|
13
|
+
}, H = (d, m, U = {}) => {
|
|
14
|
+
const {
|
|
15
|
+
eventPointerTypes: s,
|
|
16
|
+
eventCapture: a,
|
|
17
|
+
eventOnce: h,
|
|
18
|
+
eventStopImmediatePropagation: v,
|
|
19
|
+
threshold: w,
|
|
20
|
+
velocity: g,
|
|
21
|
+
container: y
|
|
22
|
+
} = { ...A, ...U }, D = p([]), u = p(null), c = p(null), l = p({
|
|
23
|
+
startX: 0,
|
|
24
|
+
startY: 0,
|
|
25
|
+
startTime: 0,
|
|
26
|
+
active: !1
|
|
27
|
+
}), b = i(() => {
|
|
28
|
+
c.current?.abort();
|
|
29
|
+
}, []), L = i(
|
|
30
|
+
(e, t) => {
|
|
31
|
+
const o = Math.abs(e), r = Math.abs(t);
|
|
32
|
+
return o > r ? e > 0 ? n.Right : n.Left : t > 0 ? n.Down : n.Up;
|
|
33
|
+
},
|
|
34
|
+
[]
|
|
35
|
+
), P = i((e) => {
|
|
36
|
+
const t = D.current;
|
|
37
|
+
return t.includes(n.Both) || t.includes(n.Horizontal) && (e === n.Left || e === n.Right) || t.includes(n.Vertical) && (e === n.Up || e === n.Down) ? !0 : t.includes(e);
|
|
38
|
+
}, []), S = i(
|
|
39
|
+
(e) => {
|
|
40
|
+
e.isPrimary && s.includes(e.pointerType) && (l.current = {
|
|
41
|
+
startX: e.clientX,
|
|
42
|
+
startY: e.clientY,
|
|
43
|
+
startTime: Date.now(),
|
|
44
|
+
active: !0
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
[s]
|
|
48
|
+
), T = i(
|
|
49
|
+
(e) => {
|
|
50
|
+
const t = l.current;
|
|
51
|
+
if (!t.active)
|
|
52
|
+
return;
|
|
53
|
+
t.active = !1;
|
|
54
|
+
const o = Date.now() - t.startTime;
|
|
55
|
+
if (o === 0)
|
|
56
|
+
return;
|
|
57
|
+
const r = e.clientX - t.startX, f = e.clientY - t.startY, X = Math.hypot(r, f), Y = X / o;
|
|
58
|
+
if (X < w || Y < g)
|
|
59
|
+
return;
|
|
60
|
+
const E = L(r, f);
|
|
61
|
+
if (!P(E))
|
|
62
|
+
return;
|
|
63
|
+
M(e, E, {
|
|
64
|
+
deltaX: r,
|
|
65
|
+
deltaY: f,
|
|
66
|
+
velocity: Y,
|
|
67
|
+
duration: o
|
|
68
|
+
}, m, {
|
|
69
|
+
stopImmediate: v,
|
|
70
|
+
once: h,
|
|
71
|
+
onOnce: () => {
|
|
72
|
+
b();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
[
|
|
77
|
+
w,
|
|
78
|
+
g,
|
|
79
|
+
L,
|
|
80
|
+
P,
|
|
81
|
+
m,
|
|
82
|
+
h,
|
|
83
|
+
v,
|
|
84
|
+
b
|
|
85
|
+
]
|
|
86
|
+
), R = i(
|
|
87
|
+
(e) => {
|
|
88
|
+
e.isPrimary && s.includes(e.pointerType) && T(e);
|
|
89
|
+
},
|
|
90
|
+
[T, s]
|
|
91
|
+
), C = i(() => {
|
|
92
|
+
l.current.active = !1;
|
|
93
|
+
}, []);
|
|
94
|
+
O(() => {
|
|
95
|
+
D.current = I(d);
|
|
96
|
+
}, [d]), O(() => {
|
|
97
|
+
u.current = y?.current ?? globalThis, c.current = new AbortController();
|
|
98
|
+
const e = (r) => S(r);
|
|
99
|
+
u.current.addEventListener(
|
|
100
|
+
"pointerdown",
|
|
101
|
+
e,
|
|
102
|
+
{
|
|
103
|
+
capture: a,
|
|
104
|
+
signal: c.current.signal
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
const t = (r) => R(r);
|
|
108
|
+
u.current.addEventListener("pointerup", t, {
|
|
109
|
+
capture: a,
|
|
110
|
+
signal: c.current.signal
|
|
111
|
+
});
|
|
112
|
+
const o = () => C();
|
|
113
|
+
return u.current.addEventListener(
|
|
114
|
+
"pointercancel",
|
|
115
|
+
o,
|
|
116
|
+
{
|
|
117
|
+
capture: a,
|
|
118
|
+
signal: c.current.signal
|
|
119
|
+
}
|
|
120
|
+
), () => {
|
|
121
|
+
c.current?.abort(), l.current.active = !1;
|
|
122
|
+
};
|
|
123
|
+
}, [
|
|
124
|
+
y,
|
|
125
|
+
a,
|
|
126
|
+
S,
|
|
127
|
+
R,
|
|
128
|
+
C
|
|
129
|
+
]);
|
|
130
|
+
};
|
|
131
|
+
export {
|
|
132
|
+
H as default
|
|
133
|
+
};
|
|
134
|
+
//# sourceMappingURL=use-swipe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-swipe.js","sources":["../../src/use-swipe/use-swipe.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from \"react\";\nimport {\n SwipeDirection,\n SwipeState,\n SwipeData,\n UseSwipeSchema,\n UseSwipeOptions,\n UseSwipeCallback,\n SwipeOptions,\n SwipeDirections,\n SwipeEventPointerType,\n} from \"./use-swipe.types\";\nimport { parseSwipeDirection } from \"./parse-swipe-direction\";\nimport { invokeSwipeAction } from \"./invoke-swipe-action\";\n\nconst defaultOptions: SwipeOptions = {\n eventPointerTypes: [\"touch\", \"mouse\", \"pen\"],\n eventCapture: false,\n eventOnce: false,\n eventStopImmediatePropagation: false,\n threshold: 50,\n velocity: 0.3,\n container: { current: null },\n};\n\nconst useSwipe = (\n swipe: UseSwipeSchema,\n swipeCallback: UseSwipeCallback,\n options: UseSwipeOptions = {},\n) => {\n const {\n eventPointerTypes,\n eventCapture,\n eventOnce,\n eventStopImmediatePropagation,\n threshold,\n velocity,\n container,\n } = { ...defaultOptions, ...options };\n\n const allowedDirectionsReference = useRef<SwipeDirection[]>([]);\n const targetReference = useRef<EventTarget | null>(null);\n const abortControllerReference = useRef<AbortController | null>(null);\n\n const swipeStateReference = useRef<SwipeState>({\n startX: 0,\n startY: 0,\n startTime: 0,\n active: false,\n });\n\n const destroyListener = useCallback(() => {\n abortControllerReference.current?.abort();\n }, []);\n\n const resolveDirection = useCallback(\n (deltaX: number, deltaY: number): SwipeDirection => {\n const absX = Math.abs(deltaX);\n const absY = Math.abs(deltaY);\n\n if (absX > absY) {\n return deltaX > 0 ? SwipeDirections.Right : SwipeDirections.Left;\n }\n\n return deltaY > 0 ? SwipeDirections.Down : SwipeDirections.Up;\n },\n [],\n );\n\n const matchesSchema = useCallback((direction: SwipeDirection): boolean => {\n const allowed = allowedDirectionsReference.current;\n\n if (allowed.includes(SwipeDirections.Both)) {\n return true;\n }\n\n if (\n allowed.includes(SwipeDirections.Horizontal) &&\n (direction === SwipeDirections.Left ||\n direction === SwipeDirections.Right)\n ) {\n return true;\n }\n\n if (\n allowed.includes(SwipeDirections.Vertical) &&\n (direction === SwipeDirections.Up || direction === SwipeDirections.Down)\n ) {\n return true;\n }\n\n return allowed.includes(direction);\n }, []);\n\n const handlePointerDown = useCallback(\n (event: PointerEvent) => {\n if (!event.isPrimary) {\n return;\n }\n\n if (\n !eventPointerTypes.includes(event.pointerType as SwipeEventPointerType)\n ) {\n return;\n }\n\n swipeStateReference.current = {\n startX: event.clientX,\n startY: event.clientY,\n startTime: Date.now(),\n active: true,\n };\n },\n [eventPointerTypes],\n );\n\n const endSwipe = useCallback(\n (event: PointerEvent) => {\n const state = swipeStateReference.current;\n if (!state.active) {\n return;\n }\n\n state.active = false;\n\n const duration = Date.now() - state.startTime;\n\n if (duration === 0) {\n return;\n }\n\n const deltaX = event.clientX - state.startX;\n const deltaY = event.clientY - state.startY;\n\n const distance = Math.hypot(deltaX, deltaY);\n\n const computedVelocity = distance / duration;\n\n if (distance < threshold) {\n return;\n }\n if (computedVelocity < velocity) {\n return;\n }\n\n const direction = resolveDirection(deltaX, deltaY);\n if (!matchesSchema(direction)) {\n return;\n }\n\n const data: SwipeData = {\n deltaX,\n deltaY,\n velocity: computedVelocity,\n duration,\n };\n\n invokeSwipeAction(event, direction, data, swipeCallback, {\n stopImmediate: eventStopImmediatePropagation,\n once: eventOnce,\n onOnce: () => {\n destroyListener();\n },\n });\n },\n [\n threshold,\n velocity,\n resolveDirection,\n matchesSchema,\n swipeCallback,\n eventOnce,\n eventStopImmediatePropagation,\n destroyListener,\n ],\n );\n\n const handlePointerUp = useCallback(\n (event: PointerEvent) => {\n if (!event.isPrimary) {\n return;\n }\n if (\n !eventPointerTypes.includes(event.pointerType as SwipeEventPointerType)\n ) {\n return;\n }\n endSwipe(event);\n },\n [endSwipe, eventPointerTypes],\n );\n\n const handlePointerCancel = useCallback(() => {\n swipeStateReference.current.active = false;\n }, []);\n\n useEffect(() => {\n allowedDirectionsReference.current = parseSwipeDirection(swipe);\n }, [swipe]);\n\n useEffect(() => {\n targetReference.current = container?.current ?? globalThis;\n abortControllerReference.current = new AbortController();\n\n const pointerDownListener = (event: Event) =>\n handlePointerDown(event as PointerEvent);\n\n targetReference.current.addEventListener(\n \"pointerdown\",\n pointerDownListener,\n {\n capture: eventCapture,\n signal: abortControllerReference.current.signal,\n },\n );\n\n const pointerUpListener = (event: Event) =>\n handlePointerUp(event as PointerEvent);\n\n targetReference.current.addEventListener(\"pointerup\", pointerUpListener, {\n capture: eventCapture,\n signal: abortControllerReference.current.signal,\n });\n\n const pointerCancelListener = () => handlePointerCancel();\n\n targetReference.current.addEventListener(\n \"pointercancel\",\n pointerCancelListener,\n {\n capture: eventCapture,\n signal: abortControllerReference.current.signal,\n },\n );\n\n return () => {\n abortControllerReference.current?.abort();\n swipeStateReference.current.active = false;\n };\n }, [\n container,\n eventCapture,\n handlePointerDown,\n handlePointerUp,\n handlePointerCancel,\n ]);\n};\n\nexport default useSwipe;\n"],"names":["defaultOptions","useSwipe","swipe","swipeCallback","options","eventPointerTypes","eventCapture","eventOnce","eventStopImmediatePropagation","threshold","velocity","container","allowedDirectionsReference","useRef","targetReference","abortControllerReference","swipeStateReference","destroyListener","useCallback","resolveDirection","deltaX","deltaY","absX","absY","SwipeDirections","matchesSchema","direction","allowed","handlePointerDown","event","endSwipe","state","duration","distance","computedVelocity","invokeSwipeAction","handlePointerUp","handlePointerCancel","useEffect","parseSwipeDirection","pointerDownListener","pointerUpListener","pointerCancelListener"],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const o = {
|
|
2
|
+
Left: "left",
|
|
3
|
+
Right: "right",
|
|
4
|
+
Up: "up",
|
|
5
|
+
Down: "down",
|
|
6
|
+
Horizontal: "horizontal",
|
|
7
|
+
Vertical: "vertical",
|
|
8
|
+
Both: "both"
|
|
9
|
+
}, t = {
|
|
10
|
+
Touch: "touch",
|
|
11
|
+
Mouse: "mouse",
|
|
12
|
+
Pen: "pen"
|
|
13
|
+
};
|
|
14
|
+
export {
|
|
15
|
+
o as SwipeDirections,
|
|
16
|
+
t as SwipeEventPointerTypes
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=use-swipe.types.js.map
|