first commit
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
# `<PluginParameterKnob>`
|
||||
|
||||
Rotary-knob primitive for a single `AudioFxPlugin` parameter. The knob
|
||||
implements the full keyboard contract mandated by the
|
||||
`<PluginSlot>` 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.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
The `<PluginParameterKnob>` 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 <PluginParameterKnob plugin={plugin} parameter={param} />;
|
||||
}
|
||||
```
|
||||
|
||||
## 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 (
|
||||
<div className="grid grid-cols-4 gap-4">
|
||||
{plugin.parameters.map((p) => (
|
||||
<PluginParameterKnob
|
||||
key={p.id}
|
||||
plugin={plugin}
|
||||
parameter={p}
|
||||
label={p.name.toUpperCase()}
|
||||
className="ring-1 ring-zinc-700 rounded-md p-2"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 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 `<PluginParameterSlider>` 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.
|
||||
Reference in New Issue
Block a user