One control, every scale
Drag past the ring and it keeps accelerating. A 2 mm nudge and a 300 mm shove, no modifier key and no mode switch.
The maths is exported
speedFor, deflection, computeDelta and the rest are pure, unit-tested and importable. Check the numbers yourself, or drive a dial with them.
Touch-first
Pointer capture, touch-action none, pointercancel handled. A drag survives your finger leaving the stick; a system gesture releases it cleanly.
Nothing renders until asked
Default is one operation and no switcher. A furniture app has no use for extrude, and a dead mode is worse than a hidden one.
Headless option
useJoystick gives every behaviour with none of the pixels — pointer capture, tap-vs-drag, keyboard, the ring clamp.
Zero dependencies
No runtime deps. React 17+. One CSS file you can override or ignore.
If it drives real hardware, put limits between
This emits a direction and a speed. It has no idea whether that becomes a preview on a canvas or a machine axis moving. If something physical is on the other end — a spindle, a robot, a camera rig — the limits, interlocks and validation are yours to add.
Provided as is, without warranty. It is a UI input, not a safety system.