clamp, rubberClamp, snapTo, move
A handful of small, dependency-free number and array helpers. They're the
same math useDrag and Reorder use internally for bounds, elastic
edges, and index swapping, exposed directly for when you're wiring up
similar behavior by hand.
clamp
function clamp(value: number, lowerbound: number, upperbound: number): number;
Restricts value to [lowerbound, upperbound]. A hard stop, no bounce.
import { clamp } from 'react-ui-animate';
clamp(150, 0, 100); // 100
clamp(-20, 0, 100); // 0
rubberClamp
function rubberClamp(
value: number,
lowerbound: number,
upperbound: number,
constant?: number // default: 0.15
): number;
Like clamp, but instead of stopping dead at the bounds it lets value
travel past them with resistance, the "rubber band" feel useDrag's
elastic option is built on. Higher constant values resist less (travel
further past the bound for the same input); constant: 0 behaves exactly
like clamp.
import { rubberClamp } from 'react-ui-animate';
rubberClamp(120, 0, 100); // slightly past 100, not clamped flat to it
Reach for this directly when building elastic behavior outside of
useDrag, for example resistance on a custom Gesture.Pan() handler.
The demo below drags with rubberClamp (resistance past the dashed bound)
and settles back with clamp on release, the same pairing useDrag uses
for elastic + hard bounds:
snapTo
function snapTo(value: number, velocity: number, snapPoints: number[]): number;
Given a current value, its velocity, and a list of candidate stopping
points, returns whichever point the value is heading toward. Projects the
value forward slightly using velocity before picking the nearest point,
so a fast flick snaps to the next point in that direction rather than
wherever the pointer happened to release.
import { snapTo, withSpring } from 'react-ui-animate';
const target = snapTo(x.current, velocity, [0, 200, 400]);
setX(withSpring(target));
Typical use: a carousel or paginated drawer, where a drag should settle on one of a few fixed positions instead of anywhere the pointer let go.
move
function move<T>(array: T[], moveIndex: number, toIndex: number): T[];
Returns a new array with the item at moveIndex relocated to toIndex,
shifting everything between the two positions. Doesn't mutate the input.
import { move } from 'react-ui-animate';
move(['a', 'b', 'c', 'd'], 0, 2); // ['b', 'c', 'a', 'd']
This is the array update Reorder calls on every drag frame internally.
Reach for it directly if you're building custom drag-to-reorder logic that
doesn't fit Reorder's component shape.