Initial Commit
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# `<MeterVU>` — VU meter with IEC 60268-10 ballistics
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`<MeterVU>` renders a single-channel level meter with the classic analogue
|
||||
VU response defined by IEC 60268-10: a 300 ms attack and 300 ms release
|
||||
single-pole low-pass smoothing the displayed needle relative to the
|
||||
instantaneous input level. The component is a pure value-in /
|
||||
DOM-out leaf — consumers feed a normalised level in `[0, 1]` and the
|
||||
meter handles ballistic smoothing on a `requestAnimationFrame` loop.
|
||||
|
||||
Use it for output-bus meters, mixer-strip meters, and any
|
||||
human-readable loudness indication where peak-precise behaviour is
|
||||
less important than the perception of "musical loudness".
|
||||
|
||||
## Features
|
||||
|
||||
- IEC 60268-10 default ballistics (300 ms attack, 300 ms release)
|
||||
- Caller-tunable `attackMs` and `releaseMs` for non-standard ballistics
|
||||
- Pure `BoundControlProps`-compatible value contract (value only)
|
||||
- `role="meter"` with `aria-valuemin` / `aria-valuemax` / `aria-valuenow`
|
||||
- CSS-variable themed fill (`--cs-meter-vu-fill-color`)
|
||||
- RAF-driven smoothing, automatic cleanup on unmount
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```tsx
|
||||
import { MeterVU } from "@suaveplan/react-control-surface";
|
||||
|
||||
<MeterVU value={0.6} label="Master Out" />;
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```tsx
|
||||
import { MeterVU } from "@suaveplan/react-control-surface";
|
||||
|
||||
// Live-driven, fast attack / slow release for a punchy display
|
||||
function LiveMeter({ source }: { source: () => number }) {
|
||||
const [v, setV] = useState(0);
|
||||
useEffect(() => {
|
||||
const id = setInterval(() => setV(source()), 16);
|
||||
return () => clearInterval(id);
|
||||
}, [source]);
|
||||
return <MeterVU value={v} attackMs={40} releaseMs={600} width={260} />;
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ----------- | -------- | ------------- | --------------------------------------------- |
|
||||
| `value` | `number` | required | Source level in `[0, 1]`, clamped on input. |
|
||||
| `attackMs` | `number` | `300` | Single-pole attack time-constant. |
|
||||
| `releaseMs` | `number` | `300` | Single-pole release time-constant. |
|
||||
| `width` | `number` | `160` | Root width in CSS pixels. |
|
||||
| `height` | `number` | `48` | Root height in CSS pixels. |
|
||||
| `label` | `string` | — | Visible + accessible label. |
|
||||
| `ariaLabel` | `string` | derived | Overrides the accessible label. |
|
||||
| `className` | `string` | — | Appended to `rcs-meter-vu`. |
|
||||
|
||||
The exported `stepBallistic(previous, target, dtMs, attackMs, releaseMs)`
|
||||
helper is the single-pole smoothing primitive used internally; it is
|
||||
exported for re-use in custom meters and is exhaustively unit-tested.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The meter holds a `useRef` containing `{ level, last }` so that the
|
||||
ballistic state persists across React renders without forcing a
|
||||
re-render on every smoothing tick. The animation loop is created once
|
||||
on mount and torn down via `cancelAnimationFrame` on unmount. Time
|
||||
deltas are measured with `Date.now()` rather than the RAF callback's
|
||||
high-resolution timestamp to keep the math identical to the
|
||||
`stepBallistic` unit tests, which run without `requestAnimationFrame`.
|
||||
|
||||
The fill bar uses a single absolutely-positioned div whose width is
|
||||
recomputed from the smoothed level on every frame. The `data-level`
|
||||
attribute is provided as a deterministic hook for E2E assertions.
|
||||
Reference in New Issue
Block a user