4.6 KiB
4.6 KiB
@suaveplan/react-control-surface — 2D atomic controls + runtime
- Target path:
packages/ui/react/react-control-surface/ - Tier: browser/react
- Date: 2026-05-23
- Status: PROPOSED
Why
@suaveplan/control-surface-schema defines the JSON; @suaveplan/audio-fx-plugin-base defines the parameter machinery; @suaveplan/react-audio provides useParameter for chain-driven automation. What's missing is the actual atomic React components — <Knob>, <Slider>, <Button>, <Meter>, etc. — plus a runtime that walks a ControlSurface document and renders the live DOM tree, wiring every control's onChange to its bound consumer (plugin parameter, MIDI CC, transport state, DMX channel).
This is the 2D renderer. The 3D R3F sibling (@suaveplan/r3f-control-surface) reads the same schema; both stay in lock-step via the shared BoundControlProps contract.
What changes
- NEW package
@suaveplan/react-control-surfaceatpackages/ui/react/react-control-surface/. BoundControlProps— the shape every control component implements:{ value: number; onChange: (v: number) => void; min: number; max: number; step?: number; default?: number; disabled?: boolean; label?: string; ariaLabel?: string; renderHint?: "auto" | "2d" }. Pure value-in / value-out — no audio knowledge.- Atomic controls (each is a feature directory with
.tsx+.types.ts+.test.tsx+.stories.tsx+.md):<Knob>— rotary, drag-vertical-to-change, double-click-resets, keyboard-arrow-step, fine-mode (Shift), aria-slider, range mapping viacurve(linear/log/exp/custom)<SliderV>,<SliderH>— vertical/horizontal sliders with detents<ButtonMomentary>,<ButtonLatching>— press-and-hold / toggle behaviours<Switch2>,<Switch3>— two- and three-position toggles<LED>— output indicator (boolean or 0..1 brightness)<DigitalDisplay>— 7-segment or LCD-style readout for numeric / text / scrolling<MeterVU>,<MeterPeak>— single-channel level meters with optional peak-hold + ballistic curves<MeterSpectral>— multi-band spectrum visualisation (consumes@suaveplan/audio-analysis-spectrumdata)<XYPad>— 2-axis touch surface<JogWheel>— endless rotary with velocity<PianoKey>— single piano key with state (idle/pressed/highlighted)<DrumPad>— velocity-sensitive pad with optional aftertouch via pointer pressure<TextLabel>,<Image>— static decorative elements
- Grouping primitives —
<Group>,<Rack>,<Panel>. Provide layout (grid/absolute/stack) and aria-labelling. - Runtime —
<Surface schema={ControlSurface} bindings={BindingRegistry} />. Walks the schema, renders each node via the atomic component for itskind, and wires each control'sonChangeto its binding consumer via the registry. BindingRegistry— discriminated dispatcher consumers register handlers with:pluginParam→ callsuseParameterfrom@suaveplan/react-audiotransport→ calls transport hooksmidiOut→ callsuseMidiOutputfrom@suaveplan/react-midimidiIn→ subscribes viauseMidiInput, drives the control'svaluebackdmx→ calls into a@suaveplan/react-dmxhook (deferred — gated by feature flag)compound→ fans out to multiple handlers
- Skin contract —
<SurfaceSkinProvider id="native-instruments">injects CSS variables consumed by every atomic control. Skin packages (control-surface-skin-*) supply the variables. - Accessibility — every control is keyboard-operable, ARIA-labelled, supports
prefers-reduced-motion, exposesrole="slider"/role="switch"/ etc. with properaria-valuenow/aria-valuetext. - Error codes —
REACT_CONTROL_SURFACE.{UNKNOWN_KIND, BINDING_HANDLER_MISSING, INVALID_SCHEMA}viadefineCodes. - OTel — counter
control_surface_interactions_total{kind}, histogramcontrol_surface_render_duration_ms.
Impact
- New browser-tier React package; depends on
@suaveplan/control-surface-schema@workspace:^,@suaveplan/react-audio@workspace:^,@suaveplan/react-midi@workspace:^, React 19 peer. - Unblocks:
react-control-surface-editor,r3f-control-surface(mirrors this surface 1:1 in R3F), every downstream DAW/instrument UI. - The 3D sibling reuses
BoundControlProps,BindingRegistry, and the schema — only the rendering layer differs.
Out of scope
- 3D atomic controls —
r3f-control-surface(Wave 2b). - Drag-and-drop layout editor —
react-control-surface-editor(Wave 4). - Skin packages — separate per-device families.
- Network replication —
network-control-surface(Wave 3).