Enhance FM synthesis + cleaning code architecture
This commit is contained in:
74
src/components/ui/Slider.tsx
Normal file
74
src/components/ui/Slider.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
import { useStore } from '@nanostores/react'
|
||||
import { mappingMode } from '../../stores/mappingMode'
|
||||
|
||||
interface SliderProps {
|
||||
label: string
|
||||
value: number
|
||||
min: number
|
||||
max: number
|
||||
step: number
|
||||
unit?: string
|
||||
onChange: (value: number) => void
|
||||
formatValue?: (id: string, value: number) => string
|
||||
valueId?: string
|
||||
paramId?: string
|
||||
onMapClick?: (paramId: string, activeLFO: number) => void
|
||||
mappedLFOs?: number[]
|
||||
}
|
||||
|
||||
export function Slider({
|
||||
label,
|
||||
value,
|
||||
min,
|
||||
max,
|
||||
step,
|
||||
unit,
|
||||
onChange,
|
||||
formatValue,
|
||||
valueId,
|
||||
paramId,
|
||||
onMapClick,
|
||||
mappedLFOs = []
|
||||
}: SliderProps) {
|
||||
const mappingModeState = useStore(mappingMode)
|
||||
const displayValue = formatValue && valueId ? formatValue(valueId, value) : `${value}${unit || ''}`
|
||||
const isInMappingMode = !!(mappingModeState.isActive && paramId)
|
||||
const hasMappings = mappedLFOs.length > 0
|
||||
|
||||
const handleClick = () => {
|
||||
if (isInMappingMode && paramId && mappingModeState.activeLFO !== null && onMapClick) {
|
||||
onMapClick(paramId, mappingModeState.activeLFO)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-col gap-2 ${isInMappingMode ? 'cursor-pointer' : ''}`}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<div className="flex justify-between items-baseline">
|
||||
<label className={`font-mono text-[10px] tracking-[0.2em] ${
|
||||
isInMappingMode ? 'text-white animate-pulse' : hasMappings ? 'text-white' : 'text-white'
|
||||
}`}>
|
||||
{label.toUpperCase()}
|
||||
{hasMappings && <span className="ml-1 text-[8px]">●</span>}
|
||||
</label>
|
||||
<span className="font-mono text-[10px] text-white">
|
||||
{displayValue}
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
value={value}
|
||||
onChange={(e) => onChange(Number(e.target.value))}
|
||||
className={`w-full h-[2px] appearance-none cursor-pointer slider ${
|
||||
hasMappings ? 'bg-white opacity-80' : 'bg-white'
|
||||
}`}
|
||||
disabled={isInMappingMode}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user