@zeey4d/react-native-gesture-engine 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,246 @@
1
+ # @zeey4d/react-native-gesture-engine
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@zeey4d/react-native-gesture-engine.svg)](https://www.npmjs.com/package/@zeey4d/react-native-gesture-engine)
4
+ [![license](https://img.shields.io/npm/l/@zeey4d/react-native-gesture-engine.svg)](https://opensource.org/licenses/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
6
+
7
+ A **modular, production-ready 6-layer event-driven gesture engine** for React Native. Supports touch, sensor, hardware, and sequence-based gestures with conflict resolution, action dispatch, and multi-modal feedback.
8
+
9
+ ## โœจ Features
10
+
11
+ - ๐Ÿ—๏ธ **6-Layer Architecture** โ€” Input โ†’ Processing โ†’ Recognition โ†’ Conflict Resolution โ†’ Action โ†’ Feedback
12
+ - ๐ŸŽฏ **12 Built-in Recognizers** โ€” Tap, DoubleTap, Pan, Pinch, Rotation, EdgeSwipe, Corner, Shake, Tilt, WristFlick, Sequence, Symbol ($1 Unistroke)
13
+ - โšก **Event-Driven** โ€” Typed pub/sub EventBus with compile-time channelโ†’payload safety
14
+ - ๐Ÿ”’ **Conflict Resolution** โ€” Priority queue + exclusive lock manager for gesture arbitration
15
+ - ๐Ÿ“ฑ **Sensor Support** โ€” Accelerometer & Gyroscope via expo-sensors with configurable intervals
16
+ - ๐ŸŽฎ **Haptic Feedback** โ€” expo-haptics with Vibration fallback
17
+ - โ™ฟ **Accessibility** โ€” Automatic screen reader announcements
18
+ - ๐Ÿช **React Hooks** โ€” `useGestureEngine`, `useShakeGesture`, `useEdgeSwipe`, `useGestureSequence`
19
+ - ๐Ÿงฉ **Extensible** โ€” Create custom recognizers by extending `BaseRecognizer`
20
+ - ๐Ÿ”‹ **Battery-Conscious** โ€” Throttled sensors, lazy initialization, ring buffer eviction
21
+
22
+ ## ๐Ÿ“ฆ Installation
23
+
24
+ ```bash
25
+ npm install @zeey4d/react-native-gesture-engine
26
+ ```
27
+
28
+ ### Peer Dependencies
29
+
30
+ ```bash
31
+ npm install react-native-gesture-handler react-native-reanimated expo-sensors
32
+ # Optional:
33
+ npm install expo-haptics
34
+ ```
35
+
36
+ | Package | Version |
37
+ |---------|---------|
38
+ | `react` | >=18.0.0 |
39
+ | `react-native` | >=0.70.0 |
40
+ | `react-native-gesture-handler` | >=2.20.0 |
41
+ | `react-native-reanimated` | >=3.0.0 |
42
+ | `expo-sensors` | >=13.0.0 |
43
+ | `expo-haptics` | >=13.0.0 *(optional)* |
44
+
45
+ ## ๐Ÿš€ Quick Start
46
+
47
+ ```tsx
48
+ import {
49
+ GestureEngine,
50
+ ShakeRecognizer,
51
+ EdgeSwipeRecognizer,
52
+ CustomAction,
53
+ HapticFeedback,
54
+ } from '@zeey4d/react-native-gesture-engine';
55
+
56
+ // Create engine
57
+ const engine = new GestureEngine({
58
+ sensorInterval: 100,
59
+ hapticEnabled: true,
60
+ });
61
+
62
+ // Register recognizers
63
+ const shake = new ShakeRecognizer(engine.eventBus, { threshold: 1.5 });
64
+ engine.registerRecognizer(shake);
65
+
66
+ const edgeSwipe = new EdgeSwipeRecognizer(engine.eventBus, {
67
+ edge: 'left',
68
+ minDistance: 50,
69
+ screenWidth: 400,
70
+ });
71
+ engine.registerRecognizer(edgeSwipe);
72
+
73
+ // Register actions
74
+ engine.registerAction('shake', new CustomAction('log', () => {
75
+ console.log('Device shaken!');
76
+ }));
77
+
78
+ // Add feedback
79
+ engine.registerFeedback(new HapticFeedback());
80
+
81
+ // Start
82
+ engine.start();
83
+ ```
84
+
85
+ ## ๐Ÿช React Hooks
86
+
87
+ ### useGestureEngine
88
+
89
+ ```tsx
90
+ import { useGestureEngine, ShakeRecognizer } from '@zeey4d/react-native-gesture-engine';
91
+
92
+ function App() {
93
+ const { engine, isReady } = useGestureEngine({
94
+ sensorInterval: 100,
95
+ hapticEnabled: true,
96
+ recognizers: [new ShakeRecognizer(eventBus, { threshold: 1.5 })],
97
+ actions: { 'shake': [new CustomAction('alert', () => alert('Shaken!'))] },
98
+ });
99
+
100
+ return <View>{isReady && <Text>Engine Ready</Text>}</View>;
101
+ }
102
+ ```
103
+
104
+ ### useShakeGesture
105
+
106
+ ```tsx
107
+ useShakeGesture({
108
+ threshold: 1.5,
109
+ cooldownMs: 1000,
110
+ onShake: () => console.log('Device shaken!'),
111
+ });
112
+ ```
113
+
114
+ ### useEdgeSwipe
115
+
116
+ ```tsx
117
+ useEdgeSwipe({
118
+ edge: 'left',
119
+ minDistance: 50,
120
+ onSwipe: (event) => navigation.goBack(),
121
+ });
122
+ ```
123
+
124
+ ### useGestureSequence
125
+
126
+ ```tsx
127
+ useGestureSequence({
128
+ sequence: ['tap', 'tap', 'edge-swipe-right'],
129
+ timeoutMs: 800,
130
+ onComplete: () => console.log('Secret gesture unlocked!'),
131
+ });
132
+ ```
133
+
134
+ ## ๐Ÿ›๏ธ Architecture
135
+
136
+ ```mermaid
137
+ graph TD
138
+ A["Layer 1: Input"] -->|InputEvent| B["Layer 2: Processing"]
139
+ B -->|ProcessedSample| C["Layer 3: Recognition"]
140
+ C -->|GestureEvent| D["Layer 4: Conflict Resolution"]
141
+ D -->|Resolved GestureEvent| E["Layer 5: Actions"]
142
+ E -->|Dispatched GestureEvent| F["Layer 6: Feedback"]
143
+
144
+ A1["TouchInputProvider"] --> A
145
+ A2["SensorInputProvider"] --> A
146
+ A3["HardwareInputProvider"] --> A
147
+
148
+ B1["NoiseFilter"] --> B
149
+ B2["VelocityCalculator"] --> B
150
+ B3["AngleDetector"] --> B
151
+ B4["StreamBuffer"] --> B
152
+
153
+ C1["TapRecognizer"] --> C
154
+ C2["ShakeRecognizer"] --> C
155
+ C3["EdgeSwipeRecognizer"] --> C
156
+ C4["SymbolRecognizer"] --> C
157
+
158
+ D1["PriorityQueue"] --> D
159
+ D2["LockManager"] --> D
160
+
161
+ E1["NavigationAction"] --> E
162
+ E2["CustomAction"] --> E
163
+
164
+ F1["HapticFeedback"] --> F
165
+ F2["AccessibilityFeedback"] --> F
166
+
167
+ style A fill:#4CAF50,color:#fff
168
+ style B fill:#2196F3,color:#fff
169
+ style C fill:#FF9800,color:#fff
170
+ style D fill:#F44336,color:#fff
171
+ style E fill:#9C27B0,color:#fff
172
+ style F fill:#00BCD4,color:#fff
173
+ ```
174
+
175
+ ## ๐Ÿ“‹ Recognizer Reference
176
+
177
+ | Recognizer | Type | Name | Key Config |
178
+ |------------|------|------|------------|
179
+ | `TapRecognizer` | Discrete | `tap` | `maxDuration`, `maxDistance` |
180
+ | `DoubleTapRecognizer` | Discrete | `double-tap` | `maxInterval`, `maxDistance` |
181
+ | `PanRecognizer` | Continuous | `pan` | `minDistance` |
182
+ | `PinchRecognizer` | Continuous | `pinch` | `minScale` |
183
+ | `RotationRecognizer` | Continuous | `rotation` | `minRotation` |
184
+ | `EdgeSwipeRecognizer` | Spatial | `edge-swipe-{edge}` | `edge`, `edgeZoneWidth`, `minDistance`, `minVelocity` |
185
+ | `CornerRecognizer` | Spatial | `corner-{corner}` | `corner`, `cornerZoneSize` |
186
+ | `ShakeRecognizer` | Sensor | `shake` | `threshold`, `consecutiveSamples`, `cooldownMs` |
187
+ | `TiltRecognizer` | Sensor | `tilt` | `tiltThreshold`, `cooldownMs` |
188
+ | `WristFlickRecognizer` | Sensor | `wrist-flick` | `angularVelocityThreshold`, `cooldownMs` |
189
+ | `SequenceRecognizer` | Sequence | `sequence:{names}` | `sequence[]`, `timeoutMs` |
190
+ | `SymbolRecognizer` | Symbolic | `symbol` | `templates`, `minConfidence` |
191
+
192
+ ## ๐Ÿงฉ Custom Recognizer Guide
193
+
194
+ Extend `BaseRecognizer` to create your own:
195
+
196
+ ```typescript
197
+ import { BaseRecognizer, ProcessedSample, IEventBus } from '@zeey4d/react-native-gesture-engine';
198
+
199
+ class LongPressRecognizer extends BaseRecognizer {
200
+ private timer: ReturnType<typeof setTimeout> | null = null;
201
+ private durationMs: number;
202
+
203
+ constructor(eventBus: IEventBus, durationMs = 500) {
204
+ super('long-press', eventBus, { priority: 15, isExclusive: true });
205
+ this.durationMs = durationMs;
206
+ }
207
+
208
+ onProcessedSample(sample: ProcessedSample): void {
209
+ if (!this.enabled) return;
210
+ // Your recognition logic here...
211
+ // Use: this.transitionToPossible(), this.transitionToBegan({ ... }), etc.
212
+ }
213
+
214
+ override reset(): void {
215
+ super.reset();
216
+ if (this.timer) clearTimeout(this.timer);
217
+ }
218
+ }
219
+ ```
220
+
221
+ ### Available state transitions:
222
+ - `transitionToPossible()` โ€” Gesture might be starting
223
+ - `transitionToBegan(metadata)` โ€” Gesture recognized, emit event
224
+ - `transitionToChanged(metadata)` โ€” Continuous gesture update
225
+ - `transitionToEnded(metadata)` โ€” Gesture completed
226
+ - `transitionToFailed()` โ€” Gesture didn't match
227
+ - `transitionToCancelled()` โ€” Gesture interrupted
228
+
229
+ ## โšก Performance Tips
230
+
231
+ 1. **Sensor interval**: Use 100ms (10Hz) for battery efficiency. Only go to 16ms (60Hz) for real-time tracking.
232
+ 2. **Lazy providers**: Sensor providers only subscribe when `start()` is called.
233
+ 3. **Ring buffer**: `StreamBuffer` auto-evicts samples older than 400ms โ€” O(1) per operation.
234
+ 4. **Exclusive locks**: Conflict resolver stops redundant parallel processing.
235
+ 5. **Ref-based hooks**: Engine lives outside React tree via `useRef` โ€” no unnecessary re-renders.
236
+
237
+ ## ๐Ÿงช Testing
238
+
239
+ ```bash
240
+ npm test # Run tests
241
+ npm run test:coverage # Run with coverage report
242
+ ```
243
+
244
+ ## ๐Ÿ“„ License
245
+
246
+ MIT ยฉ [zeey4d](https://github.com/zeey4d)