# `` — VU meter with IEC 60268-10 ballistics _(no submodules)_ ## Purpose `` 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"; ; ``` ## 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 ; } ``` ## 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.