3.5 KiB
<MeterVU> — VU meter with IEC 60268-10 ballistics
(no submodules)
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
attackMsandreleaseMsfor non-standard ballistics - Pure
BoundControlProps-compatible value contract (value only) role="meter"witharia-valuemin/aria-valuemax/aria-valuenow- CSS-variable themed fill (
--cs-meter-vu-fill-color) - RAF-driven smoothing, automatic cleanup on unmount
Usage: Basic
import { MeterVU } from "@suaveplan/react-control-surface";
<MeterVU value={0.6} label="Master Out" />;
Usage: Advanced
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.