# useRobotMotion

The clock every machine runs on and the handle you grab it by: a rate-limited scalar, pointer-capture dragging, and keyboard steps — all parked by a reduced-motion preference.

> For the complete index, see [llms.txt](https://robocn.dev/llms.txt). A Markdown version of any page is available by appending `.md` to its URL or by sending an `Accept: text/markdown` header.

## Install

```bash
bunx --bun shadcn@latest add https://robocn.dev/r/use-robot-motion.json
```

Registry item: `use-robot-motion` · [`https://robocn.dev/r/use-robot-motion.json`](https://robocn.dev/r/use-robot-motion.json)

## Notes

- Every uncontrolled robocn machine runs on this hook, which is why they all park together under a reduced-motion preference and all resume from where you left them.
- The goal is a function of the clock, so a behaviour is a pure function that can be sampled in a test at a fixed phase rather than driven by a timer.

## Usage

```tsx
const motion = useRobotScalar((clock) => Math.sin(clock * Math.PI * 2) * 90, {
  rate: 210,        // degrees per second on the way back
  hold: dragging,   // pin it while the pointer has it
  speed: 0.25,      // cycles per second
})

const dragging = useRobotDrag(svgRef, {
  enabled: interactive,
  onDrag: useCallback((unit) => setAngle(unit.x * 360 - 180), []),
})
```

## API

| name | type | default | description |
| --- | --- | --- | --- |
| `useRobotClock` | `(options?) => number` | — | Seconds × speed since mount, offset by phase. Parks at phase when animation is off or reduced motion is preferred, and holds where it stands while paused. |
| `useRobotScalar` | `(goal, options?) => { value, clock }` | — | One frame loop that advances the clock and rate-limits a value toward goal(clock). hold pins the value while the clock keeps running underneath, so releasing a grabbed machine eases back into the cycle instead of snapping to it. |
| `useRobotDrag` | `(ref, options) => boolean` | — | Pointer capture on press, unit coordinates on every move, and the drag state back for the cursor. Pressing rather than hovering is what gives a touch device the same control a mouse has. |
| `approach` | `(value, goal, step) => number` | — | The rate limiter itself. Pure, so a component can use it directly. |
| `arrowStep` | `(key, step, large?) => number` | — | Arrow and page keys as a signed delta; zero for keys that are not ours. |
| `useReducedMotion` | `() => boolean` | — | Subscribes to the preference, so a change takes effect without a reload. |

## Source

- `src/hooks/use-robot-motion.ts`
