first commit
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
# `<MicrophoneControls>`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`<MicrophoneControls>` is the composed UI for
|
||||
`MicrophoneSimulationPlugin` from
|
||||
`@suaveplan/audio-fx-plugin-microphone`. The plugin itself declares
|
||||
its UI surface via `getUISections()`: a list of grouped controls
|
||||
(frequency, resonance, distortion, noise, dynamics, gain, character,
|
||||
wow/flutter) with their numeric ranges and step sizes. The component
|
||||
mirrors that data-driven structure, rendering one `<fieldset>` per
|
||||
section and one `<input type="range">` per control. Writes go through
|
||||
`plugin.setMicrophoneConfig` with the minimal partial-update.
|
||||
|
||||
Because the UI structure is driven entirely by the plugin's metadata,
|
||||
adding a new control on the plugin automatically shows up here — no
|
||||
React code change required.
|
||||
|
||||
## Features
|
||||
|
||||
- Data-driven layout from `plugin.getUISections()`.
|
||||
- One range input per declared control, with `min` / `max` / `step`
|
||||
taken from the plugin's metadata.
|
||||
- Live readout shown alongside every slider via `aria-live="polite"`.
|
||||
- Non-numeric input ignored to keep the plugin config schema-valid.
|
||||
- `aria-label="Microphone controls"` on the outer section and
|
||||
per-control labels in the form `"<group> <control>"`.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```tsx
|
||||
import { MicrophoneSimulationPlugin } from "@suaveplan/audio-fx-plugin-microphone";
|
||||
import {
|
||||
AudioProvider,
|
||||
MicrophoneControls,
|
||||
} from "@suaveplan/react-audio";
|
||||
|
||||
const plugin = new MicrophoneSimulationPlugin();
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<AudioProvider>
|
||||
<MicrophoneControls plugin={plugin} />
|
||||
</AudioProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```tsx
|
||||
import { MicrophoneSimulationPlugin } from "@suaveplan/audio-fx-plugin-microphone";
|
||||
import {
|
||||
AudioProvider,
|
||||
MicrophoneControls,
|
||||
} from "@suaveplan/react-audio";
|
||||
|
||||
const plugin = new MicrophoneSimulationPlugin({
|
||||
config: {
|
||||
distortion: { drive: 0.4, mix: 0.5 },
|
||||
wowFlutter: {
|
||||
wowRateHz: 0.5,
|
||||
wowDepth: 0.05,
|
||||
flutterRateHz: 8,
|
||||
flutterDepth: 0.02,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export function StudioMic() {
|
||||
return (
|
||||
<AudioProvider>
|
||||
<MicrophoneControls plugin={plugin} className="studio-mic" />
|
||||
</AudioProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
| Prop | Type | Default | Notes |
|
||||
| ----------- | ----------------------------- | ------- | ------------------------------------------- |
|
||||
| `plugin` | `MicrophoneSimulationPlugin` | — | Required. |
|
||||
| `className` | `string \| undef` | — | Forwarded to the outer `<section>`. |
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The component stores a single config snapshot in React state and
|
||||
refreshes it on every successful write. Section / control ids are
|
||||
exposed via `data-section` / per-control keys so consumers can target
|
||||
any cell with CSS without inspecting the plugin's metadata. The
|
||||
`updateField` helper constructs a minimal partial-update of the form
|
||||
`{ [group]: { ...prev[group], [field]: newValue } }`, which keeps
|
||||
unrelated group fields stable across the `setMicrophoneConfig` call;
|
||||
the plugin's own merge logic then folds the partial into its live
|
||||
config tree.
|
||||
Reference in New Issue
Block a user