lynx-gesture-reanimated
v0.1.0
Published
High-performance gesture and animation library for Lynx JS — zero-bridge, 120fps, pure MTS
Downloads
96
Maintainers
Readme
lynx-gesture-reanimated
🚀 The missing gesture & animation engine for Lynx JS — 120fps, zero-bridge, pure MTS.
Bringing the power of React Native Reanimated & React Native Gesture Handler to the Lynx JS ecosystem. Built from the ground up for Lynx's dual-thread architecture using pure TypeScript and Main Thread Script (MTS).
✨ Features / Why this library?
⚡ Zero-Bridge Communication
Traditional cross-thread animations require serializing data over a JavaScript bridge — introducing latency and frame drops. lynx-gesture-reanimated runs entirely on Lynx's Main Thread via the main-thread: MTS namespace. Gesture state and animation frames never cross the JS-to-UI bridge, eliminating the #1 cause of jank.
🎯 MTS-Powered 120fps Animations
By leveraging requestAnimationFrame loops and shared value primitives that live directly on the main thread, every animation frame is resolved in < 8ms — achieving a stable 120fps on capable hardware without a single native C++ binding.
🔒 No C++ PAPI Bindings, No GC Clashes
Unlike bindings that interact directly with PrimJS's garbage collector (causing unpredictable GC pauses mid-animation), this library is implemented in pure TypeScript + MTS. There are no native modules to link, no C++ to compile, and no GC pressure from crossing the managed/unmanaged boundary.
🧩 Familiar API — React Native Developer Friendly
If you've used react-native-reanimated or react-native-gesture-handler, you're already home. The API surface is intentionally designed to mirror those libraries.
| Concept | React Native | lynx-gesture-reanimated |
| ------------------ | --------------------- | ----------------------- |
| Shared values | useSharedValue | useLynxSharedValue |
| Animated component | Animated.View | <Animated.View> |
| Spring animation | withSpring | withSpring |
| Timing animation | withTiming | withTiming |
| Pan gesture | PanGestureHandler | Gesture.Pan() |
| Pinch gesture | PinchGestureHandler | Gesture.Pinch() |
📦 Installation
# npm
npm install lynx-gesture-reanimated
# yarn
yarn add lynx-gesture-reanimated
# pnpm
pnpm add lynx-gesture-reanimatedRequirement: Lynx JS
>= 0.2.0. No native linking or pod install required.
🚀 Quick Start
Draggable Box with Spring-Back
A box you can drag freely. When released, it springs back to the origin with a satisfying bounce.
import React from "react";
import {
Animated,
Gesture,
useLynxSharedValue,
withSpring,
} from "lynx-gesture-reanimated";
export default function DraggableBox() {
const translateX = useLynxSharedValue(0);
const translateY = useLynxSharedValue(0);
// Track offset so drags accumulate correctly across gestures
const offsetX = useLynxSharedValue(0);
const offsetY = useLynxSharedValue(0);
const panGesture = Gesture.Pan()
.onBegin(() => {
offsetX.value = translateX.value;
offsetY.value = translateY.value;
})
.onUpdate((event) => {
translateX.value = offsetX.value + event.translationX;
translateY.value = offsetY.value + event.translationY;
})
.onEnd(() => {
// Spring back to origin on release
translateX.value = withSpring(0);
translateY.value = withSpring(0);
});
return (
<Animated.View
gesture={panGesture}
style={{
width: 100,
height: 100,
backgroundColor: "#6C63FF",
borderRadius: 16,
transform: [{ translateX: translateX }, { translateY: translateY }],
}}
/>
);
}📖 API Overview
Hooks
| Hook | Description |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| useLynxSharedValue(initialValue) | Creates a reactive value that lives on the main thread. Mutations to .value are applied synchronously in MTS — no bridge round-trip. |
Gesture Builders
| API | Description |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| Gesture.Pan() | Recognizes single-pointer pan/drag gestures. Provides translationX, translationY, velocityX, velocityY. |
| Gesture.Pinch() | Recognizes two-finger pinch gestures using Euclidean distance. Provides scale. |
| Gesture.Tap() | Recognizes single or multi-tap gestures with configurable hitSlop. |
| Gesture.Simultaneous(...gestures) | Composes multiple gestures for conflict-free simultaneous recognition (e.g., pan + pinch together). |
Animation Functions
| Function | Description |
| ------------------------------ | ----------------------------------------------------------------------------------------------------- |
| withSpring(toValue, config?) | Animates a shared value using a physics-based spring model. Supports stiffness, damping, mass. |
| withTiming(toValue, config?) | Animates a shared value over a fixed duration with an easing function. Supports duration, easing. |
Components
| Component | Description |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <Animated.View> | A wrapper around Lynx's <view> element. Accepts shared values in style props and a gesture prop to attach gesture recognizers. Translates animated values into MTS directives at the binding layer. |
🏗️ Architecture Note
Why pure MTS instead of C++ bindings?
Lynx JS runs on PrimJS — a lightweight JS engine. When native C++ code interacts with PrimJS objects, those objects become ineligible for the engine's Garbage Collector until the native call returns. In an animation loop running at 120fps (one frame every ~8ms), this creates a predictable GC stutter window that manifests as dropped frames.
lynx-gesture-reanimated avoids this entirely by staying within the JavaScript/MTS layer:

Gesture events are emitted from the background thread to establish gesture handlers, but once registered, all animation execution happens exclusively on the main thread — the background JS thread is never in the critical path of a running animation.
📁 Project Structure
src/
├── useLynxSharedValue.ts # Shared value primitive
├── Animated.tsx # <Animated.View> component
├── Gesture.ts # Gesture builder factory
├── GestureRegistry.ts # Gesture conflict resolution & composition
├── PanGesture.ts # Pan gesture state machine
├── PinchGesture.ts # Pinch gesture (Euclidean distance)
├── spring.ts # Spring physics engine (rAF-based)
├── timing.ts # Timing animation engine (rAF-based)
└── index.ts # Public API exports🗺️ Roadmap
- [ ]
Gesture.Rotation()— two-finger rotation recognizer - [ ]
withDecay()— momentum-based decay animation - [ ]
withSequence()/withDelay()— animation composition - [ ]
useAnimatedStyle()— derived style hook - [ ] DevTools plugin for Lynx Inspector
🤝 Contributing
Contributions, issues, and feature requests are welcome! Please read CONTRIBUTING.md before submitting a PR.
- Fork the repository
- Create your feature branch:
git checkout -b feat/your-feature - Commit following Conventional Commits
- Push and open a Pull Request
📄 License
MIT © 2026 — see LICENSE for details.
