# `` Rotary-knob primitive for a single `AudioFxPlugin` parameter. The knob implements the full keyboard contract mandated by the `` accessibility requirement, exposes `role="slider"` with ARIA range metadata derived from the parameter's `min`/`max`/`unit` declaration, and supports an `Enter`-to-edit type-in affordance. _(no submodules)_ ## Purpose The `` is the rotary half of the generic parameter-control surface. Specialised plugin UIs (an EQ panel, a compressor panel) often wrap the knob with their own visual chrome while reusing the keyboard, ARIA, and value-management logic. The knob is therefore deliberately presentational: the entire keyboard keymap, value clamping, and typed-edit flow live here, while the caller supplies the plugin and parameter declaration. The knob subscribes to the parameter via the Phase-1 `useParameter` hook, so every change is reflected at the provider's declared `sampleRateHz` — by default 60 Hz, matching one tick per animation frame. ## Features - `role="slider"`, `aria-valuemin`, `aria-valuemax`, `aria-valuenow`, `aria-valuetext` (unit-aware via `formatAriaValueText`). - `←`/`→` fine step (1 % of range), `↑`/`↓` coarse step (10 %), `PageUp`/`PageDown` ×100 page step, `Home`/`End` jump to range endpoints. - `Shift` ×10, `Alt` ÷10 modifier multipliers. - `Enter` opens a numeric type-edit input; `Enter` commits, `Escape` reverts, blur commits. - `data-parameter-id` attribute on the wrapper so plugin authors can target specific knobs from a stylesheet. - Pure CSS-class API (`rax-knob`, `rax-knob__dial`, `rax-knob__readout`, `rax-knob__input`) — no styling assumptions baked in. ## Usage: Basic ```tsx import { PluginParameterKnob } from "@suaveplan/react-audio/components/plugin-parameter-knob"; function GainKnob({ plugin }) { const param = plugin.parameterIndex.get("gain")!; return ; } ``` ## Usage: Advanced ```tsx // Iterate every parameter on a plugin, rendering each with a custom label // override and theming via the className API. function PluginPanel({ plugin }) { return (
{plugin.parameters.map((p) => ( ))}
); } ``` ## API Reference ### Props - `plugin: AudioFxPlugin` — the plugin instance whose parameter is bound. - `parameter: PluginParameter` — the declaration to render. The parameter MUST be present in `plugin.parameterIndex`; otherwise the underlying `useParameter` hook throws `REACT_AUDIO.UNKNOWN_PARAMETER`. - `label?: string` — optional visible label override; defaults to `parameter.name`. - `className?: string` — optional CSS class appended to the wrapper. ### Behaviour - Each parameter update flows through `param.set(...)`, which delegates to `plugin.setParameter`. Value subscriptions go through the Phase-1 `useParameter` hook. - The typed-edit input is rendered only when the user presses `Enter` on the knob; it auto-focuses, supports `Enter`/`Escape`/blur, and clamps the parsed value to the declared range. ## Implementation Notes - The keyboard handler delegates to the pure `resolveParameterKeyboardChange` helper, which is shared with `` to guarantee identical step semantics between the two primitives. - `formatAriaValueText` is called with `signedDb: true` so dB readouts carry the `+` sign — matching the convention used by every other audio tool that ships unit-aware screen-reader text. - No animation libraries are imported; visual rotation should be composed by the consumer via CSS. The component respects `prefers-reduced-motion` by virtue of being CSS-only.