@msobiecki/react-marauders-path 1.24.1 → 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.
Files changed (43) hide show
  1. package/dist/index.js +22 -0
  2. package/dist/index.js.map +1 -0
  3. package/dist/use-drag/invoke-drag-action.js +7 -0
  4. package/dist/use-drag/invoke-drag-action.js.map +1 -0
  5. package/dist/use-drag/use-drag.js +141 -0
  6. package/dist/use-drag/use-drag.js.map +1 -0
  7. package/dist/use-drag/use-drag.types.js +9 -0
  8. package/dist/use-drag/use-drag.types.js.map +1 -0
  9. package/dist/use-key/event-guards.js +5 -0
  10. package/dist/use-key/event-guards.js.map +1 -0
  11. package/dist/use-key/invoke-key-action.js +7 -0
  12. package/dist/use-key/invoke-key-action.js.map +1 -0
  13. package/dist/use-key/normalize-key.js +43 -0
  14. package/dist/use-key/normalize-key.js.map +1 -0
  15. package/dist/use-key/parse-key-sequences.js +16 -0
  16. package/dist/use-key/parse-key-sequences.js.map +1 -0
  17. package/dist/use-key/sequence-state.js +25 -0
  18. package/dist/use-key/sequence-state.js.map +1 -0
  19. package/dist/use-key/use-key.js +206 -0
  20. package/dist/use-key/use-key.js.map +1 -0
  21. package/dist/use-key/use-key.types.js +8 -0
  22. package/dist/use-key/use-key.types.js.map +1 -0
  23. package/dist/use-pinch/invoke-pinch-action.js +7 -0
  24. package/dist/use-pinch/invoke-pinch-action.js.map +1 -0
  25. package/dist/use-pinch/use-pinch.js +131 -0
  26. package/dist/use-pinch/use-pinch.js.map +1 -0
  27. package/dist/use-pinch/use-pinch.types.js +9 -0
  28. package/dist/use-pinch/use-pinch.types.js.map +1 -0
  29. package/dist/use-swipe/invoke-swipe-action.js +7 -0
  30. package/dist/use-swipe/invoke-swipe-action.js.map +1 -0
  31. package/dist/use-swipe/parse-swipe-direction.js +5 -0
  32. package/dist/use-swipe/parse-swipe-direction.js.map +1 -0
  33. package/dist/use-swipe/use-swipe.js +134 -0
  34. package/dist/use-swipe/use-swipe.js.map +1 -0
  35. package/dist/use-swipe/use-swipe.types.js +18 -0
  36. package/dist/use-swipe/use-swipe.types.js.map +1 -0
  37. package/dist/use-wheel/invoke-wheel-action.js +7 -0
  38. package/dist/use-wheel/invoke-wheel-action.js.map +1 -0
  39. package/dist/use-wheel/use-wheel.js +79 -0
  40. package/dist/use-wheel/use-wheel.js.map +1 -0
  41. package/package.json +3 -3
  42. package/dist/index.es.js +0 -761
  43. /package/dist/{index.es.d.ts → index.d.ts} +0 -0
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
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";
4
+ 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";
10
+ export {
11
+ p as DragEventPointerTypes,
12
+ 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
21
+ };
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
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 invokeDragAction
6
+ };
7
+ //# sourceMappingURL=invoke-drag-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke-drag-action.js","sources":["../../src/use-drag/invoke-drag-action.ts"],"sourcesContent":["import { DragData } from \"./use-drag.types\";\n\n/**\n * Invokes a drag action callback with optional event modifications.\n *\n * Handles drag event processing including preventing default behavior,\n * stopping immediate propagation, and managing one-time event handlers.\n *\n * @param {PointerEvent} event - The drag event\n * @param {DragData} data - The normalized drag 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 * invokeDragAction(event, data, (e, d) => {\n * console.log(`Drag moved: ${d.x}, ${d.y}, ${d.z}`);\n * return true; // Prevent default\n * }, { stopImmediate: true });\n */\nexport const invokeDragAction = (\n event: PointerEvent,\n data: DragData,\n callback:\n | ((event: PointerEvent, data: DragData) => boolean)\n | ((event: PointerEvent, data: DragData) => 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":["invokeDragAction","event","data","callback","options"],"mappings":"AAsBO,MAAMA,IAAmB,CAC9BC,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,141 @@
1
+ import { useRef as a, useCallback as s, useEffect as b } from "react";
2
+ import { invokeDragAction as O } from "./invoke-drag-action.js";
3
+ const F = {
4
+ eventPointerTypes: ["touch", "mouse", "pen"],
5
+ eventCapture: !1,
6
+ eventOnce: !1,
7
+ eventStopImmediatePropagation: !1,
8
+ threshold: 0,
9
+ container: { current: null },
10
+ raf: !1
11
+ }, q = (p, A = {}) => {
12
+ const {
13
+ eventPointerTypes: c,
14
+ eventCapture: i,
15
+ eventOnce: f,
16
+ eventStopImmediatePropagation: d,
17
+ threshold: P,
18
+ container: y,
19
+ raf: v
20
+ } = { ...F, ...A }, o = a(null), n = a(null), l = a(null), g = a(null), h = a(null), u = a({
21
+ startX: 0,
22
+ startY: 0,
23
+ lastX: 0,
24
+ lastY: 0,
25
+ startTime: 0,
26
+ active: !1
27
+ }), m = s(() => {
28
+ n.current?.abort();
29
+ }, []), L = s(() => {
30
+ l.current = null;
31
+ const t = g.current, e = h.current;
32
+ !t || !e || (O(e, t, p, {
33
+ stopImmediate: d,
34
+ once: f,
35
+ onOnce: () => {
36
+ m();
37
+ }
38
+ }), g.current = null, h.current = null);
39
+ }, [p, d, f, m]), T = s(
40
+ (t) => {
41
+ t.isPrimary && c.includes(t.pointerType) && (u.current = {
42
+ startX: t.clientX,
43
+ startY: t.clientY,
44
+ lastX: t.clientX,
45
+ lastY: t.clientY,
46
+ startTime: Date.now(),
47
+ active: !0
48
+ });
49
+ },
50
+ [c]
51
+ ), D = s(
52
+ (t) => {
53
+ const e = u.current;
54
+ if (!e.active || !t.isPrimary || !c.includes(t.pointerType))
55
+ return;
56
+ const X = t.clientX - e.startX, Y = t.clientY - e.startY, r = t.clientX - e.lastX, C = t.clientY - e.lastY;
57
+ if (Math.hypot(X, Y) < P) return;
58
+ const I = Date.now() - e.startTime, E = {
59
+ deltaX: X,
60
+ deltaY: Y,
61
+ movementX: r,
62
+ movementY: C,
63
+ duration: I,
64
+ startX: e.startX,
65
+ startY: e.startY,
66
+ endX: t.clientX,
67
+ endY: t.clientY
68
+ };
69
+ if (e.lastX = t.clientX, e.lastY = t.clientY, !v) {
70
+ O(t, E, p, {
71
+ stopImmediate: d,
72
+ once: f,
73
+ onOnce: () => {
74
+ m();
75
+ }
76
+ });
77
+ return;
78
+ }
79
+ g.current = E, h.current = t, l.current === null && (l.current = requestAnimationFrame(L));
80
+ },
81
+ [
82
+ c,
83
+ P,
84
+ v,
85
+ p,
86
+ d,
87
+ f,
88
+ m,
89
+ L
90
+ ]
91
+ ), R = s(
92
+ (t) => {
93
+ t.isPrimary && c.includes(t.pointerType) && (u.current.active = !1);
94
+ },
95
+ [c]
96
+ ), w = s(() => {
97
+ u.current.active = !1;
98
+ }, []);
99
+ b(() => {
100
+ o.current = y?.current ?? globalThis, n.current = new AbortController();
101
+ const t = (r) => T(r), e = (r) => D(r), X = (r) => R(r), Y = () => w();
102
+ return o.current.addEventListener(
103
+ "pointerdown",
104
+ t,
105
+ {
106
+ capture: i,
107
+ signal: n.current.signal
108
+ }
109
+ ), o.current.addEventListener(
110
+ "pointermove",
111
+ e,
112
+ {
113
+ capture: i,
114
+ signal: n.current.signal
115
+ }
116
+ ), o.current.addEventListener("pointerup", X, {
117
+ capture: i,
118
+ signal: n.current.signal
119
+ }), o.current.addEventListener(
120
+ "pointercancel",
121
+ Y,
122
+ {
123
+ capture: i,
124
+ signal: n.current.signal
125
+ }
126
+ ), () => {
127
+ n.current?.abort(), u.current.active = !1, l.current !== null && cancelAnimationFrame(l.current);
128
+ };
129
+ }, [
130
+ y,
131
+ i,
132
+ T,
133
+ D,
134
+ R,
135
+ w
136
+ ]);
137
+ };
138
+ export {
139
+ q as default
140
+ };
141
+ //# sourceMappingURL=use-drag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-drag.js","sources":["../../src/use-drag/use-drag.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from \"react\";\nimport {\n DragState,\n DragData,\n UseDragCallback,\n UseDragOptions,\n DragOptions,\n DragEventPointerType,\n} from \"./use-drag.types\";\nimport { invokeDragAction } from \"./invoke-drag-action\";\n\nconst defaultOptions: DragOptions = {\n eventPointerTypes: [\"touch\", \"mouse\", \"pen\"],\n eventCapture: false,\n eventOnce: false,\n eventStopImmediatePropagation: false,\n threshold: 0,\n container: { current: null },\n raf: false,\n};\n\nconst useDrag = (\n dragCallback: UseDragCallback,\n options: UseDragOptions = {},\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<DragData | null>(null);\n const pendingEventReference = useRef<PointerEvent | null>(null);\n\n const dragStateReference = useRef<DragState>({\n startX: 0,\n startY: 0,\n lastX: 0,\n lastY: 0,\n startTime: 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 invokeDragAction(event, data, dragCallback, {\n stopImmediate: eventStopImmediatePropagation,\n once: eventOnce,\n onOnce: () => {\n destroyListener();\n },\n });\n\n pendingDataReference.current = null;\n pendingEventReference.current = null;\n }, [dragCallback, eventStopImmediatePropagation, eventOnce, destroyListener]);\n\n const handlePointerDown = useCallback(\n (event: PointerEvent) => {\n if (!event.isPrimary) return;\n\n if (\n !eventPointerTypes.includes(event.pointerType as DragEventPointerType)\n ) {\n return;\n }\n\n dragStateReference.current = {\n startX: event.clientX,\n startY: event.clientY,\n lastX: event.clientX,\n lastY: event.clientY,\n startTime: Date.now(),\n active: true,\n };\n },\n [eventPointerTypes],\n );\n\n const handlePointerMove = useCallback(\n (event: PointerEvent) => {\n const state = dragStateReference.current;\n if (!state.active) return;\n if (!event.isPrimary) return;\n\n if (\n !eventPointerTypes.includes(event.pointerType as DragEventPointerType)\n ) {\n return;\n }\n\n const deltaX = event.clientX - state.startX;\n const deltaY = event.clientY - state.startY;\n\n const movementX = event.clientX - state.lastX;\n const movementY = event.clientY - state.lastY;\n\n const distance = Math.hypot(deltaX, deltaY);\n\n if (distance < threshold) return;\n\n const duration = Date.now() - state.startTime;\n\n const data: DragData = {\n deltaX,\n deltaY,\n movementX,\n movementY,\n duration,\n startX: state.startX,\n startY: state.startY,\n endX: event.clientX,\n endY: event.clientY,\n };\n\n state.lastX = event.clientX;\n state.lastY = event.clientY;\n\n if (!raf) {\n invokeDragAction(event, data, dragCallback, {\n stopImmediate: eventStopImmediatePropagation,\n once: eventOnce,\n onOnce: () => {\n destroyListener();\n },\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 eventPointerTypes,\n threshold,\n raf,\n dragCallback,\n eventStopImmediatePropagation,\n eventOnce,\n destroyListener,\n flushFrame,\n ],\n );\n\n const handlePointerUp = useCallback(\n (event: PointerEvent) => {\n if (!event.isPrimary) return;\n\n if (\n !eventPointerTypes.includes(event.pointerType as DragEventPointerType)\n ) {\n return;\n }\n\n dragStateReference.current.active = false;\n },\n [eventPointerTypes],\n );\n\n const handlePointerCancel = useCallback(() => {\n dragStateReference.current.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 = () => handlePointerCancel();\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 dragStateReference.current.active = false;\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 useDrag;\n"],"names":["defaultOptions","useDrag","dragCallback","options","eventPointerTypes","eventCapture","eventOnce","eventStopImmediatePropagation","threshold","container","raf","targetReference","useRef","abortControllerReference","frameReference","pendingDataReference","pendingEventReference","dragStateReference","destroyListener","useCallback","flushFrame","data","event","invokeDragAction","handlePointerDown","handlePointerMove","state","deltaX","deltaY","movementX","movementY","duration","handlePointerUp","handlePointerCancel","useEffect","pointerDownListener","pointerMoveListener","pointerUpListener","pointerCancelListener"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ const e = {
2
+ Touch: "touch",
3
+ Mouse: "mouse",
4
+ Pen: "pen"
5
+ };
6
+ export {
7
+ e as DragEventPointerTypes
8
+ };
9
+ //# sourceMappingURL=use-drag.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-drag.types.js","sources":["../../src/use-drag/use-drag.types.ts"],"sourcesContent":["export interface DragState {\n startX: number;\n startY: number;\n lastX: number;\n lastY: number;\n startTime: number;\n active: boolean;\n}\n\nexport const DragEventPointerTypes = {\n Touch: \"touch\",\n Mouse: \"mouse\",\n Pen: \"pen\",\n} as const;\n\nexport type DragEventPointerType =\n (typeof DragEventPointerTypes)[keyof typeof DragEventPointerTypes];\n\nexport interface DragData {\n deltaX: number;\n deltaY: number;\n movementX: number;\n movementY: number;\n duration: number;\n startX: number;\n startY: number;\n endX: number;\n endY: number;\n}\n\nexport interface DragOptions {\n eventPointerTypes: DragEventPointerType[];\n eventCapture: boolean;\n eventOnce: boolean;\n eventStopImmediatePropagation: boolean;\n threshold: number;\n container: { current: HTMLElement | null };\n raf: boolean;\n}\n\nexport type UseDragCallback =\n | ((event: PointerEvent, data: DragData) => boolean)\n | ((event: PointerEvent, data: DragData) => void);\n\nexport type UseDragOptions = Partial<DragOptions>;\n"],"names":["DragEventPointerTypes"],"mappings":"AASO,MAAMA,IAAwB;AAAA,EACnC,OAAO;AAAA,EACP,OAAO;AAAA,EACP,KAAK;AACP;"}
@@ -0,0 +1,5 @@
1
+ const t = (e, r) => !(!r.repeat && e.repeat);
2
+ export {
3
+ t as shouldHandleKeyboardEvent
4
+ };
5
+ //# sourceMappingURL=event-guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-guards.js","sources":["../../src/use-key/event-guards.ts"],"sourcesContent":["/**\n * Determines whether a keyboard event should be handled based on event options.\n *\n * @param {KeyboardEvent} event - The keyboard event to evaluate\n * @param {Object} options - Event handling options\n * @param {boolean} options.repeat - If true, repeated key presses are allowed\n * @returns {boolean} True if the event should be handled, false otherwise\n *\n * @example\n * const shouldHandle = shouldHandleKeyboardEvent(event, {\n * repeat: false\n * });\n */\nexport const shouldHandleKeyboardEvent = (\n event: KeyboardEvent,\n options: {\n repeat: boolean;\n },\n) => {\n if (!options.repeat && event.repeat) {\n return false;\n }\n return true;\n};\n"],"names":["shouldHandleKeyboardEvent","event","options"],"mappings":"AAaO,MAAMA,IAA4B,CACvCC,GACAC,MAII,GAACA,EAAQ,UAAUD,EAAM;"}
@@ -0,0 +1,7 @@
1
+ const a = (e, t, n, o) => {
2
+ o.stopImmediate && e.stopImmediatePropagation(), n(e, t) && e.preventDefault(), o.once && o.onOnce?.();
3
+ };
4
+ export {
5
+ a as invokeKeyAction
6
+ };
7
+ //# sourceMappingURL=invoke-key-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke-key-action.js","sources":["../../src/use-key/invoke-key-action.ts"],"sourcesContent":["/**\n * Invokes a keyboard action callback with optional event modifications.\n *\n * Handles keyboard event processing including preventing default behavior,\n * stopping immediate propagation, and managing one-time event handlers.\n *\n * @param {KeyboardEvent} event - The keyboard event\n * @param {string} key - The normalized key pattern\n * @param {Function} callback - Function to invoke with (event, key). 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 * invokeKeyAction(event, 'shift+a', (e, key) => {\n * console.log(`Pressed ${key}`);\n * return true; // Prevent default\n * }, { stopImmediate: true });\n */\nexport const invokeKeyAction = (\n event: KeyboardEvent,\n key: string,\n callback:\n | ((event: KeyboardEvent, key: string) => boolean)\n | ((event: KeyboardEvent, key: string) => 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, key);\n if (shouldPrevent) {\n event.preventDefault();\n }\n\n if (options.once) {\n options.onOnce?.();\n }\n};\n"],"names":["invokeKeyAction","event","key","callback","options"],"mappings":"AAoBO,MAAMA,IAAkB,CAC7BC,GACAC,GACAC,GAGAC,MAKG;AACH,EAAIA,EAAQ,iBACVH,EAAM,yBAAA,GAGcE,EAASF,GAAOC,CAAG,KAEvCD,EAAM,eAAA,GAGJG,EAAQ,QACVA,EAAQ,SAAA;AAEZ;"}
@@ -0,0 +1,43 @@
1
+ const t = {
2
+ ENTER: "Enter",
3
+ ESC: "Escape",
4
+ ESCAPE: "Escape",
5
+ SPACE: "Space",
6
+ TAB: "Tab",
7
+ SHIFT: "Shift",
8
+ CONTROL: "Control",
9
+ CTRL: "Control",
10
+ ALT: "Alt",
11
+ META: "Meta",
12
+ ARROWUP: "ArrowUp",
13
+ ARROWDOWN: "ArrowDown",
14
+ ARROWLEFT: "ArrowLeft",
15
+ ARROWRIGHT: "ArrowRight",
16
+ BACKSPACE: "Backspace",
17
+ DELETE: "Delete",
18
+ DEL: "Delete",
19
+ INSERT: "Insert",
20
+ HOME: "Home",
21
+ END: "End",
22
+ PAGEUP: "PageUp",
23
+ PAGEDOWN: "PageDown",
24
+ CONTEXTMENU: "ContextMenu",
25
+ CAPSLOCK: "CapsLock",
26
+ NUMLOCK: "NumLock",
27
+ SCROLLLOCK: "ScrollLock",
28
+ ANY: "Any"
29
+ // Special key to match any key in sequences
30
+ }, n = (o) => {
31
+ if (!o)
32
+ return o;
33
+ const e = o.trim(), r = e.toUpperCase();
34
+ return r in t ? t[r] : e.length === 1 ? e.toLowerCase() : e[0].toUpperCase() + e.slice(1).toLowerCase();
35
+ }, E = (o) => o.split(" ").filter(Boolean).map(
36
+ (e) => e.split("+").map((r) => n(r)).join("+")
37
+ ).join(" ");
38
+ export {
39
+ t as SPECIAL_KEYS,
40
+ n as normalizeKey,
41
+ E as normalizeKeySequence
42
+ };
43
+ //# sourceMappingURL=normalize-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-key.js","sources":["../../src/use-key/normalize-key.ts"],"sourcesContent":["/**\n * Map of special key names to their normalized values.\n * Supports various aliases for the same key (e.g., ESC and ESCAPE both map to Escape).\n *\n * @example\n * SPECIAL_KEYS['ENTER'] // 'Enter'\n * SPECIAL_KEYS['ESC'] // 'Escape'\n * SPECIAL_KEYS['CTRL'] // 'Control'\n */\nexport const SPECIAL_KEYS = {\n ENTER: \"Enter\",\n ESC: \"Escape\",\n ESCAPE: \"Escape\",\n SPACE: \"Space\",\n TAB: \"Tab\",\n SHIFT: \"Shift\",\n CONTROL: \"Control\",\n CTRL: \"Control\",\n ALT: \"Alt\",\n META: \"Meta\",\n ARROWUP: \"ArrowUp\",\n ARROWDOWN: \"ArrowDown\",\n ARROWLEFT: \"ArrowLeft\",\n ARROWRIGHT: \"ArrowRight\",\n BACKSPACE: \"Backspace\",\n DELETE: \"Delete\",\n DEL: \"Delete\",\n INSERT: \"Insert\",\n HOME: \"Home\",\n END: \"End\",\n PAGEUP: \"PageUp\",\n PAGEDOWN: \"PageDown\",\n CONTEXTMENU: \"ContextMenu\",\n CAPSLOCK: \"CapsLock\",\n NUMLOCK: \"NumLock\",\n SCROLLLOCK: \"ScrollLock\",\n ANY: \"Any\", // Special key to match any key in sequences\n} as const;\n\ntype SpecialKey = keyof typeof SPECIAL_KEYS;\n\n/**\n * Normalizes a single key string to its standard representation.\n *\n * Special keys are mapped to their standard names (e.g., 'enter' → 'Enter').\n * Single character keys are lowercased (e.g., 'A' → 'a').\n * Multi-character keys are capitalized (e.g., 'numpad1' → 'Numpad1').\n *\n * @param {string} key - The key string to normalize\n * @returns {string} The normalized key\n *\n * @example\n * normalizeKey('enter') // 'Enter'\n * normalizeKey('SHIFT') // 'Shift'\n * normalizeKey('a') // 'a'\n * normalizeKey('F12') // 'F12'\n */\nexport const normalizeKey = (key: string): string => {\n if (!key) {\n return key;\n }\n\n const trimmed = key.trim();\n\n const upper = trimmed.toUpperCase();\n if (upper in SPECIAL_KEYS) {\n return SPECIAL_KEYS[upper as SpecialKey];\n }\n\n if (trimmed.length === 1) {\n return trimmed.toLowerCase();\n }\n\n return trimmed[0].toUpperCase() + trimmed.slice(1).toLowerCase();\n};\n\n/**\n * Normalizes a key sequence or combinations string.\n *\n * Processes sequences separated by spaces and combinations separated by + signs.\n * Each component is individually normalized using normalizeKey().\n *\n * @param {string} sequence - The key sequence or combination to normalize\n * @returns {string} The normalized sequence\n *\n * @example\n * normalizeKeySequence('shift+a') // 'Shift+a'\n * normalizeKeySequence('CTRL+ALT+DEL') // 'Control+Alt+Delete'\n * normalizeKeySequence('a b c') // 'a b c'\n * normalizeKeySequence('Shift+A Enter') // 'Shift+a Enter'\n */\nexport const normalizeKeySequence = (sequence: string): string => {\n return sequence\n .split(\" \")\n .filter(Boolean)\n .map((part) =>\n part\n .split(\"+\")\n .map((key) => normalizeKey(key))\n .join(\"+\"),\n )\n .join(\" \");\n};\n"],"names":["SPECIAL_KEYS","normalizeKey","key","trimmed","upper","normalizeKeySequence","sequence","part"],"mappings":"AASO,MAAMA,IAAe;AAAA,EAC1B,OAAO;AAAA,EACP,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,KAAK;AAAA,EACL,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,aAAa;AAAA,EACb,UAAU;AAAA,EACV,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,KAAK;AAAA;AACP,GAoBaC,IAAe,CAACC,MAAwB;AACnD,MAAI,CAACA;AACH,WAAOA;AAGT,QAAMC,IAAUD,EAAI,KAAA,GAEdE,IAAQD,EAAQ,YAAA;AACtB,SAAIC,KAASJ,IACJA,EAAaI,CAAmB,IAGrCD,EAAQ,WAAW,IACdA,EAAQ,YAAA,IAGVA,EAAQ,CAAC,EAAE,YAAA,IAAgBA,EAAQ,MAAM,CAAC,EAAE,YAAA;AACrD,GAiBaE,IAAuB,CAACC,MAC5BA,EACJ,MAAM,GAAG,EACT,OAAO,OAAO,EACd;AAAA,EAAI,CAACC,MACJA,EACG,MAAM,GAAG,EACT,IAAI,CAACL,MAAQD,EAAaC,CAAG,CAAC,EAC9B,KAAK,GAAG;AAAA,EAEZ,KAAK,GAAG;"}
@@ -0,0 +1,16 @@
1
+ import { normalizeKeySequence as o } from "./normalize-key.js";
2
+ const u = (s) => (Array.isArray(s) ? s : [s]).map((r) => {
3
+ const n = o(r), c = n.split(" ").filter((e) => e.length > 0).map(
4
+ (e) => e.includes("+") ? e.split("+") : e
5
+ );
6
+ return {
7
+ key: n,
8
+ chord: c,
9
+ index: 0,
10
+ sequenceTimeout: null
11
+ };
12
+ });
13
+ export {
14
+ u as parseKeySequences
15
+ };
16
+ //# sourceMappingURL=parse-key-sequences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-key-sequences.js","sources":["../../src/use-key/parse-key-sequences.ts"],"sourcesContent":["import { normalizeKeySequence } from \"./normalize-key\";\nimport { SequenceState, KeyEvent } from \"./use-key.types\";\n\n/**\n * Parses keyboard event patterns into sequence states.\n *\n * Converts key patterns (single keys, combinations, sequences, or arrays thereof)\n * into SequenceState objects with normalized keys and tracking properties.\n * Sequences with spaces are split into arrays.\n *\n * @param {KeyEvent} input - A single key pattern or array of key patterns\n * @returns {SequenceState[]} Array of parsed sequence states\n *\n * @example\n * parseKeySequences('a') // [{ key: 'a', chord: ['a'], index: 0, sequenceTimeout: null }]\n * parseKeySequences('shift+a') // [{ key: 'Shift+a', chord: [['Shift','a']], index: 0, sequenceTimeout: null }]\n * parseKeySequences('a b c') // [{ key: 'a b c', chord: ['a', 'b', 'c'], index: 0, sequenceTimeout: null }]\n * parseKeySequences('shift+a a b c') // [{ key: 'Shift+a a b c', chord: [['Shift','a'], 'a', 'b', 'c'], index: 0, sequenceTimeout: null }]\n * parseKeySequences(['a', 'b']) // [{ ... }, { ... }]\n */\nexport const parseKeySequences = (input: KeyEvent): SequenceState[] => {\n const keys = Array.isArray(input) ? input : [input];\n\n return keys.map((pattern) => {\n const normalizedKey = normalizeKeySequence(pattern);\n\n const sequenceParts = normalizedKey\n .split(\" \")\n .filter((part) => part.length > 0);\n\n const chord = sequenceParts.map((part) =>\n part.includes(\"+\") ? part.split(\"+\") : part,\n );\n\n return {\n key: normalizedKey,\n chord,\n index: 0,\n sequenceTimeout: null,\n };\n });\n};\n"],"names":["parseKeySequences","input","pattern","normalizedKey","normalizeKeySequence","chord","part"],"mappings":";AAoBO,MAAMA,IAAoB,CAACC,OACnB,MAAM,QAAQA,CAAK,IAAIA,IAAQ,CAACA,CAAK,GAEtC,IAAI,CAACC,MAAY;AAC3B,QAAMC,IAAgBC,EAAqBF,CAAO,GAM5CG,IAJgBF,EACnB,MAAM,GAAG,EACT,OAAO,CAACG,MAASA,EAAK,SAAS,CAAC,EAEP;AAAA,IAAI,CAACA,MAC/BA,EAAK,SAAS,GAAG,IAAIA,EAAK,MAAM,GAAG,IAAIA;AAAA,EAAA;AAGzC,SAAO;AAAA,IACL,KAAKH;AAAA,IACL,OAAAE;AAAA,IACA,OAAO;AAAA,IACP,iBAAiB;AAAA,EAAA;AAErB,CAAC;"}
@@ -0,0 +1,25 @@
1
+ const s = (e, o) => {
2
+ const u = { ...e, index: 0, sequenceTimeout: null };
3
+ return e.sequenceTimeout && clearTimeout(e.sequenceTimeout), o.map(
4
+ (n) => n === e ? u : n
5
+ );
6
+ }, T = (e, o, u, n) => {
7
+ const t = {
8
+ ...e,
9
+ index: e.index + 1,
10
+ sequenceTimeout: e.sequenceTimeout
11
+ };
12
+ u && (t.sequenceTimeout && clearTimeout(t.sequenceTimeout), t.sequenceTimeout = setTimeout(
13
+ () => n(t),
14
+ u
15
+ ));
16
+ const m = o.map(
17
+ (i) => i === e ? t : i
18
+ );
19
+ return [t, m];
20
+ };
21
+ export {
22
+ T as advanceSequenceState,
23
+ s as resetSequenceState
24
+ };
25
+ //# sourceMappingURL=sequence-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequence-state.js","sources":["../../src/use-key/sequence-state.ts"],"sourcesContent":["import { SequenceState } from \"./use-key.types\";\n\n/**\n * Resets a sequence state to its initial values.\n *\n * Sets index to 0, clears any pending timeout, and returns a new array\n * with the reset sequence while preserving other sequences.\n *\n * @param {SequenceState} sequence - The sequence to reset\n * @param {SequenceState[]} sequences - The full sequences array\n * @returns {SequenceState[]} New array with the reset sequence\n *\n * @example\n * const sequences = [{ key: 'a', index: 2, sequenceTimeout: id1, ... }];\n * const reset = resetSequenceState(sequences[0], sequences);\n * // reset[0].index === 0 && reset[0].sequenceTimeout === null\n */\nexport const resetSequenceState = (\n sequence: SequenceState,\n sequences: SequenceState[],\n): SequenceState[] => {\n const reset = { ...sequence, index: 0, sequenceTimeout: null };\n\n if (sequence.sequenceTimeout) {\n clearTimeout(sequence.sequenceTimeout);\n }\n\n return sequences.map((candidateSequence) =>\n candidateSequence === sequence ? reset : candidateSequence,\n );\n};\n\n/**\n * Advances a sequence state to the next key in the sequence.\n *\n * Increments the sequence index and optionally sets a timeout for sequence completion.\n * Clears any existing timeout before setting a new one.\n *\n * @param {SequenceState} sequence - The sequence to advance\n * @param {SequenceState[]} sequences - The full sequences array\n * @param {number|undefined} timeout - Timeout duration in milliseconds (falsy = no timeout)\n * @param {Function} onTimeout - Callback invoked when timeout expires\n * @returns {[SequenceState, SequenceState[]]} Tuple of advanced sequence and updated sequences array\n *\n * @example\n * const [nextSeq, newSeqs] = advanceSequenceState(\n * sequence,\n * sequences,\n * 3000,\n * (seq) => console.log('Sequence timed out')\n * );\n * // nextSeq.index === sequence.index + 1\n */\nexport const advanceSequenceState = (\n sequence: SequenceState,\n sequences: SequenceState[],\n timeout: number | undefined,\n onTimeout: (sequence: SequenceState) => void,\n): [SequenceState, SequenceState[]] => {\n const nextSequence: SequenceState = {\n ...sequence,\n index: sequence.index + 1,\n sequenceTimeout: sequence.sequenceTimeout,\n };\n\n if (timeout) {\n if (nextSequence.sequenceTimeout) {\n clearTimeout(nextSequence.sequenceTimeout);\n }\n nextSequence.sequenceTimeout = setTimeout(\n () => onTimeout(nextSequence),\n timeout,\n );\n }\n\n const newSequences = sequences.map((candidateSequence) =>\n candidateSequence === sequence ? nextSequence : candidateSequence,\n );\n\n return [nextSequence, newSequences];\n};\n"],"names":["resetSequenceState","sequence","sequences","reset","candidateSequence","advanceSequenceState","timeout","onTimeout","nextSequence","newSequences"],"mappings":"AAiBO,MAAMA,IAAqB,CAChCC,GACAC,MACoB;AACpB,QAAMC,IAAQ,EAAE,GAAGF,GAAU,OAAO,GAAG,iBAAiB,KAAA;AAExD,SAAIA,EAAS,mBACX,aAAaA,EAAS,eAAe,GAGhCC,EAAU;AAAA,IAAI,CAACE,MACpBA,MAAsBH,IAAWE,IAAQC;AAAA,EAAA;AAE7C,GAuBaC,IAAuB,CAClCJ,GACAC,GACAI,GACAC,MACqC;AACrC,QAAMC,IAA8B;AAAA,IAClC,GAAGP;AAAA,IACH,OAAOA,EAAS,QAAQ;AAAA,IACxB,iBAAiBA,EAAS;AAAA,EAAA;AAG5B,EAAIK,MACEE,EAAa,mBACf,aAAaA,EAAa,eAAe,GAE3CA,EAAa,kBAAkB;AAAA,IAC7B,MAAMD,EAAUC,CAAY;AAAA,IAC5BF;AAAA,EAAA;AAIJ,QAAMG,IAAeP,EAAU;AAAA,IAAI,CAACE,MAClCA,MAAsBH,IAAWO,IAAeJ;AAAA,EAAA;AAGlD,SAAO,CAACI,GAAcC,CAAY;AACpC;"}
@@ -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,8 @@
1
+ const e = {
2
+ KeyUp: "keyup",
3
+ KeyDown: "keydown"
4
+ };
5
+ export {
6
+ e as KeyEventTypes
7
+ };
8
+ //# sourceMappingURL=use-key.types.js.map
@@ -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,7 @@
1
+ const c = (e, t, n, o) => {
2
+ o.stopImmediate && e.stopImmediatePropagation(), n(e, t) && e.preventDefault(), o.once && o.onOnce?.();
3
+ };
4
+ export {
5
+ c as invokePinchAction
6
+ };
7
+ //# sourceMappingURL=invoke-pinch-action.js.map
@@ -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;"}