Files
suaveplan/packages/ui/react/react-control-surface/src/controls/slider-v/slider-helpers.md
2026-05-27 23:47:53 +01:00

3.1 KiB

slider-helpers (module-private)

Purpose

Shared pure functions for both <SliderV> and <SliderH> so that value resolution, detent snapping, and keyboard stepping are identical across the two orientations. The helpers live under slider-v/ for a stable physical home, and <SliderH> reaches across with a single relative import. They are not re-exported from the package barrel — consumers of the package only see <SliderV> and <SliderH>.

Features

  • clamp / quantize — primitive numeric helpers.
  • applyDetents — within-threshold snap to the nearest detent at.
  • resolveSliderValue — full pipeline: clamp → step quantize → detent snap.
  • fractionForValue — normalize value to 0..1 for thumb-position math.
  • keyboardStep — returns the next value for arrow / Home / End / PageUp / PageDown keys, orientation-aware, Shift-fine-mode aware. Returns null for unrecognised keys.

Usage: Basic

import {
    resolveSliderValue,
    fractionForValue,
} from "./slider-helpers.js";

const next = resolveSliderValue({
    raw: 0.42,
    min: 0,
    max: 1,
    step: 0.05,
});
const pct = fractionForValue(next, 0, 1); // 0.4

Usage: Advanced

Keyboard-driven step with custom fine factor and detents:

import {
    keyboardStep,
    resolveSliderValue,
} from "./slider-helpers.js";

const proposed = keyboardStep({
    key: event.key,
    value: current,
    min: -60,
    max: 12,
    step: 0.5,
    fineFactor: 0.1,
    shiftKey: event.shiftKey,
    orientation: "vertical",
});
if (proposed !== null) {
    const snapped = resolveSliderValue({
        raw: proposed,
        min: -60,
        max: 12,
        step: 0.5,
        detents: [{ at: 0, label: "0 dB" }],
        snapThreshold: 0.5,
    });
    onChange(snapped);
}

API Reference

Function Signature
clamp (value, min, max) => number
quantize (value, step, min) => number
applyDetents (value, detents, threshold) => number
resolveSliderValue ({ raw, min, max, step, detents?, snapThreshold? }) => number
fractionForValue (value, min, max) => number (always clamped to 0..1)
keyboardStep (args) => number | null; returns null for unrecognised keys.

Implementation Notes

applyDetents greedily picks the closest detent within threshold distance; threshold defaults to 2% of the span when not supplied. quantize short-circuits when step <= 0 so consumers can opt out of stepping with step: 0. keyboardStep derives a perceptible per-key delta of max(step, span / 100) so wide ranges still respond to a single arrow key even when step is tiny. The orientation flip between vertical / horizontal is encoded purely in the key mapping; all downstream math is direction-agnostic.