Initial release: dreamknob library + showcase
React + TypeScript knob/fader library with a headless interaction core (rotary, relative-drag and track modes, wheel, keyboard, a11y), SVG primitives, nine prebuilt skins, seven-segment display engine, and a Vite showcase with gallery, live playground and API docs.
This commit is contained in:
commit
60a02cb1db
46 changed files with 6186 additions and 0 deletions
110
packages/dreamknob/README.md
Normal file
110
packages/dreamknob/README.md
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
# dreamknob
|
||||
|
||||
Studio-grade React knobs & faders. Rotary, linear, 2D, 3D, digital and analog — with a
|
||||
headless core, any number range, any decimal precision, and colors you fully control.
|
||||
Zero runtime dependencies.
|
||||
|
||||
```
|
||||
npm install dreamknob
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```tsx
|
||||
import { FlatKnob } from 'dreamknob'
|
||||
|
||||
function Volume() {
|
||||
const [value, setValue] = useState(64)
|
||||
return (
|
||||
<FlatKnob
|
||||
size={90}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
min={0}
|
||||
max={100}
|
||||
step={0.5}
|
||||
label="Volume"
|
||||
unit="%"
|
||||
aria-label="Volume"
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Uncontrolled works too: pass `defaultValue` instead of `value`/`onChange`
|
||||
(it also becomes the double-click reset target).
|
||||
|
||||
## Interaction model
|
||||
|
||||
Every component shares one core:
|
||||
|
||||
| Gesture | Behaviour |
|
||||
| --- | --- |
|
||||
| Drag | `rotary` (grab & turn, follows the pointer angle), `vertical`, `horizontal`, `both`, or absolute `track-*` (faders) |
|
||||
| Scroll wheel | one `step` per notch, `Shift` = fine |
|
||||
| `↑ → / ↓ ←` | ± one step (`Shift` = 10×) |
|
||||
| `PageUp/PageDown` | ± 10 % of range |
|
||||
| `Home/End` | min / max |
|
||||
| Double-click | reset to `defaultValue` |
|
||||
| Touch / pen | pointer capture, `touch-action: none` |
|
||||
|
||||
All knobs render `role="slider"` with `aria-valuemin/max/now/text`.
|
||||
|
||||
## Value handling
|
||||
|
||||
- `min` / `max` — any numbers (negative, fractional, huge).
|
||||
- `step` — decimal snap increments (`0.5`, `0.001`, `1e-7`…) with float-drift-safe
|
||||
rounding; display precision inferred automatically, overridable via `decimals`.
|
||||
- `values={[0.25, 0.5, 1, 2, 4]}` — discrete allowed values.
|
||||
- `steps={5}` — evenly spaced detents (selector knobs).
|
||||
- `taper` — `linearTaper` (default), `logTaper` (frequencies), `powTaper(n)` (gain),
|
||||
or your own `{ toNormalized, fromNormalized }`.
|
||||
- `onChange` / `onChangeStart` / `onChangeEnd` — gesture-aware callbacks.
|
||||
|
||||
## Prebuilt skins
|
||||
|
||||
```tsx
|
||||
import {
|
||||
FlatKnob, // clean 2D arc knob (arcFrom="center" for pan knobs)
|
||||
MetalKnob, // 3D brushed aluminum, knurled rim (tone="silver" | "dark")
|
||||
RubberKnob, // 3D soft-touch synth knob with glow halo
|
||||
VintageKnob, // chicken-head bakelite over a printed scale
|
||||
LEDKnob, // segmented LED ring + true seven-segment readout
|
||||
NeonKnob, // glowing arc for dark UIs
|
||||
SteppedKnob, // detented selector (positions={['LP','BP','HP']})
|
||||
Fader, // linear channel fader, vertical or horizontal
|
||||
LEDFader, // segmented LED meter-fader with color zones
|
||||
SegmentDisplay, // standalone seven-segment numeric display
|
||||
} from 'dreamknob'
|
||||
```
|
||||
|
||||
Every skin takes the core props plus `size`, `label`, `showValue`, `unit`, `format`,
|
||||
and per-part color props (`color`, `trackColor`, `faceColor`, `bodyColor`, …).
|
||||
|
||||
## Compose your own
|
||||
|
||||
```tsx
|
||||
import { Knob, Arc, Pointer, Ticks, KnobValue } from 'dreamknob'
|
||||
|
||||
<Knob size={96} min={-24} max={24} step={0.5} defaultValue={0} aria-label="Trim">
|
||||
<Ticks count={25} activeColor="#ffd23e" />
|
||||
<Arc radius={36} thickness={3} color="#ffd23e" from="center" />
|
||||
<Pointer type="triangle" radius={33} length={9} width={8} color="#ffd23e" />
|
||||
<KnobValue unit=" dB" />
|
||||
</Knob>
|
||||
```
|
||||
|
||||
`<Knob>` also accepts a render function: `{(ctx) => <YourSVG angle={ctx.angle} />}`.
|
||||
|
||||
## Fully headless
|
||||
|
||||
```tsx
|
||||
import { useKnob } from 'dreamknob'
|
||||
|
||||
const { value, normalized, angle, isDragging, bind, setValue } = useKnob({
|
||||
min: 0, max: 11, step: 0.1, defaultValue: 11, 'aria-label': 'Volume',
|
||||
})
|
||||
return <div {...bind}>…your own rendering…</div>
|
||||
```
|
||||
|
||||
MIT
|
||||
Loading…
Add table
Add a link
Reference in a new issue