import React from 'react'; import { AlphaDisplay, Arc, DreamknobProvider, Fader, FlatKnob, Gauge, ImageKnob, Knob, KnobValue, IndicatorLamp, LabeledField, LampRow, LEDFader, LEDKnob, MetalKnob, Meter, MeterBridge, NeonKnob, Pointer, PushButton, Rack, RubberKnob, ScrubField, SegmentSwitch, SegmentDisplay, SteppedKnob, Ticks, ToggleSwitch, TransportButton, VintageKnob, XYPad, logTaper, } from 'dreamknob'; const PRESETS = [ { name: 'INIT PATCH', cutoff: 50 }, { name: 'WARM PAD', cutoff: 22 }, { name: 'ACID 303', cutoff: 84 }, ]; const PresetDemo: React.FC = () => { const [preset, setPreset] = React.useState(0); return (
undefined} readOnly animateChanges={{ duration: 350 }} color="#3df2ad" label="Cutoff" aria-label="Preset cutoff" />
{PRESETS.map((p, i) => ( on && setPreset(i)} color="#3df2ad" size={34} aria-label={`Preset ${p.name}`} > {String.fromCharCode(65 + i)} ))}
); }; /** Draw a film-strip of a simple hardware knob at runtime (stand-in for a KnobMan PNG). */ const useGeneratedStrip = (frames = 31, fs = 120): string | null => { const [src, setSrc] = React.useState(null); React.useEffect(() => { const canvas = document.createElement('canvas'); canvas.width = fs; canvas.height = fs * frames; const g = canvas.getContext('2d'); if (!g) return; for (let i = 0; i < frames; i++) { const cx = fs / 2; const cy = i * fs + fs / 2; const angle = ((225 + (i / (frames - 1)) * 270) * Math.PI) / 180; const grad = g.createRadialGradient(cx - fs * 0.15, cy - fs * 0.18, fs * 0.05, cx, cy, fs * 0.45); grad.addColorStop(0, '#5c5f69'); grad.addColorStop(0.65, '#26282e'); grad.addColorStop(1, '#0e0f12'); g.fillStyle = grad; g.beginPath(); g.arc(cx, cy, fs * 0.4, 0, Math.PI * 2); g.fill(); g.strokeStyle = 'rgba(0,0,0,0.65)'; g.lineWidth = fs * 0.025; g.stroke(); g.strokeStyle = '#ffd23e'; g.lineWidth = fs * 0.05; g.lineCap = 'round'; g.beginPath(); g.moveTo(cx + Math.sin(angle) * fs * 0.16, cy - Math.cos(angle) * fs * 0.16); g.lineTo(cx + Math.sin(angle) * fs * 0.33, cy - Math.cos(angle) * fs * 0.33); g.stroke(); } setSrc(canvas.toDataURL('image/png')); }, [frames, fs]); return src; }; const MeterDemo: React.FC = () => { const [levels, setLevels] = React.useState<[number, number]>([-18, -20]); React.useEffect(() => { let t = 0; const id = setInterval(() => { t += 0.09; // Occasional hot transient so the clip LED gets to do its job. const spike = Math.random() < 0.04 ? 9 : 0; setLevels([ -13 + Math.sin(t) * 6 + Math.random() * 7 + spike, -14 + Math.sin(t * 1.3 + 1) * 6 + Math.random() * 7 + spike, ]); }, 90); return () => clearInterval(id); }, []); return (
); }; const LampSwitchDemo: React.FC = () => { const [mode, setMode] = React.useState(1); const [armed, setArmed] = React.useState(true); return (
); }; const CommitModeDemo: React.FC = () => { const [commits, setCommits] = React.useState(0); return (
setCommits(n => n + 1)} aria-label="Release commit demo" />
onChange calls
); }; const RESOURCE_ZONES = [ { upTo: 0.75, color: '#3df2ad' }, { upTo: 0.9, color: '#ffd23e' }, { upTo: 1, color: '#ff4d6b' }, ]; const GaugeDemo: React.FC = () => { const [load, setLoad] = React.useState<[number, number]>([38, 61]); React.useEffect(() => { let t = 0; const id = setInterval(() => { t += 0.12; setLoad([ Math.max(2, Math.min(100, 45 + Math.sin(t) * 30 + Math.random() * 12)), Math.max(2, Math.min(100, 62 + Math.sin(t * 0.7 + 2) * 26 + Math.random() * 10)), ]); }, 140); return () => clearInterval(id); }, []); return (
); }; const SmallReadoutDemo: React.FC = () => { const [t, setT] = React.useState(0); React.useEffect(() => { const id = setInterval(() => setT(v => v + 1), 1000); return () => clearInterval(id); }, []); const hh = String(Math.floor(t / 3600) % 100).padStart(2, '0'); const mm = String(Math.floor(t / 60) % 60).padStart(2, '0'); const ss = String(t % 60).padStart(2, '0'); return (
); }; const PanelDemo: React.FC = () => { const [fresh, setFresh] = React.useState(true); const [mode, setMode] = React.useState(0); const [playing, setPlaying] = React.useState(false); const [armed, setArmed] = React.useState(false); return (
setPlaying(p => !p)} size={34} /> setPlaying(false)} size={34} /> setArmed(a => !a)} size={34} /> { setPlaying(false); setArmed(false); }} size={34} />
); }; const ImageKnobDemo: React.FC = () => { const src = useGeneratedStrip(); if (!src) return null; return ( ); }; const Card: React.FC<{ title: string; desc: string; tag: string; children: React.ReactNode; }> = ({ title, desc, tag, children }) => (

{title}

{desc}
{children}
{tag}
); export const Gallery: React.FC = () => ( );