# Controllers

> The logic under each primitive, from @audio-ui/core: one controller per control, with the same contract whatever draws it. A React part is one adapter of it; a plain DOM page, Vue or Svelte can be another.

Every primitive, React's and the custom elements alike, is a view over a controller from `@audio-ui/core`. The controller holds the value, the gesture, the keys and the formatting, and says nothing about how the control is drawn. Use it directly to drive a control from any framework, or from no framework at all.

```ts
import { createFaderController } from "@audio-ui/core/fader";

const fader = createFaderController({ value: 0.5, onValueCommitted: (value) => save(value) });
```

## The contract

Every controller follows the same steps, whatever the control:

1. **Create it once** per mounted control, with its options: `create<Name>Controller(options)`. `setOptions(options)` replaces every option later and notifies no one, so redraw yourself afterwards.
2. **Draw from `getSnapshot()`**, and redraw when `subscribe(listener)` calls you. The snapshot is the same object until something changes, so comparing it is cheap.
3. **Send it the input**: `press` on a primary-button `pointerdown`, which follows the drag on the document until release, `attachWheel(element)` for the wheel, `keyDown` from the focusable element, and `type` from a text input's `input` event. The arguments differ per controller, as each control's page shows.
4. **Tear down** with the functions that `subscribe` and `attachWheel` return.

The value moves in two steps. `onValueChange` reports every change during a drag, and `onValueCommitted` fires once when the gesture ends. Both carry a `reason` (a drag, a key, the wheel, a typed value, a reset) and the event that caused them, and each controller's `*EventReason` type lists its own. Save to the second one.

The primitives of `@audio-ui/react` and `@audio-ui/elements` are its reference adapters: the part that owns an element is the one that attaches its listeners and attributes.

## Next

Each control's page has its options and its input:

- Values on a travel: [knob](/docs/core/knob), [fader](/docs/core/fader), [xypad](/docs/core/xypad).
- Points and curves: [envelope](/docs/core/envelope), [plot](/docs/core/plot).
- Notes and strikes: [piano](/docs/core/piano), [pad](/docs/core/pad), [sequencer](/docs/core/sequencer), [piano-roll](/docs/core/piano-roll).
- Time and audio: [timeline](/docs/core/timeline), [waveform](/docs/core/waveform).
- [meter](/docs/core/meter) has no gesture, so no controller: a scale, ballistics and a painter.
