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.
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:
- 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. - Draw from
getSnapshot(), and redraw whensubscribe(listener)calls you. The snapshot is the same object until something changes, so comparing it is cheap. - Send it the input:
presson a primary-buttonpointerdown, which follows the drag on the document until release,attachWheel(element)for the wheel,keyDownfrom the focusable element, andtypefrom a text input'sinputevent. The arguments differ per controller, as each control's page shows. - Tear down with the functions that
subscribeandattachWheelreturn.
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: