first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
# `<SliderH>`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Horizontal slider control — the X-axis counterpart of `<SliderV>`.
Every behavioural decision is delegated to the shared
`slider-helpers` module so the two orientations stay in lockstep:
detent snapping, step quantization, keyboard delta sizing, fine-mode
factor, and clamp logic are all identical to `<SliderV>`. The only
differences are: arrow-key mapping (`ArrowLeft` / `ArrowRight` instead
of `ArrowDown` / `ArrowUp`), pointer math reads `clientX` against the
rect width, and the SVG rendering is horizontal.
## Features
- Pointer capture for drag past the SVG bounds.
- Detent snapping (shared with `<SliderV>`).
- Keyboard accessibility: arrow keys, Home, End, PageUp, PageDown,
Shift fine-mode.
- `aria-slider` with `aria-orientation="horizontal"`.
- CSS-variable theming reuses the same `--cs-slider-*` tokens as
`<SliderV>`.
- Auto-rendered detent ticks on the track.
- Step-quantized output via `step` (default `0.01`).
## Usage: Basic
```tsx
import { useState } from "react";
import { SliderH } from "@suaveplan/react-control-surface";
export function PanSlider() {
const [v, setV] = useState(0);
return (
<SliderH
value={v}
onChange={setV}
min={-1}
max={1}
step={0.01}
label="Pan"
/>
);
}
```
## Usage: Advanced
A blend slider with a centre detent, wider track, custom snap radius:
```tsx
import { useState } from "react";
import { SliderH } from "@suaveplan/react-control-surface";
export function DryWetBlend() {
const [mix, setMix] = useState(0.5);
return (
<SliderH
value={mix}
onChange={setMix}
min={0}
max={1}
step={0.001}
label="Dry / Wet"
detents={[{ at: 0.5, label: "50%" }]}
snapThreshold={0.02}
trackPx={280}
thicknessPx={28}
fineModeFactor={0.05}
/>
);
}
```
## API Reference
| Prop | Type | Default |
| ---------------- | --------------------- | -------- |
| `value` | `number` | required |
| `onChange` | `(v: number) => void` | required |
| `min` | `number` | required |
| `max` | `number` | required |
| `step` | `number` | `0.01` |
| `disabled` | `boolean` | `false` |
| `label` | `string` | — |
| `ariaLabel` | `string` | — |
| `detents` | `SliderDetent[]` | — |
| `snapThreshold` | `number` | 2% span |
| `trackPx` | `number` | `160` |
| `thicknessPx` | `number` | `24` |
| `fineModeFactor` | `number` | `0.1` |
## Implementation Notes
`<SliderH>` imports its helpers from `../slider-v/slider-helpers.js`
rather than from the package root so the helper module remains
package-private and never leaks into the public barrel. The pointer
math reads the rendered rect width so a `width: 100%` host container
behaves correctly — value tracks the actual on-screen geometry rather
than the configured `trackPx`. When the rect collapses to width 0
(offscreen / display:none), the math falls back to `trackPx`.