82 lines
3.0 KiB
TypeScript
82 lines
3.0 KiB
TypeScript
import { parameterRegistry } from '../../domain/modulation/ParameterRegistry'
|
|
|
|
interface Mapping {
|
|
targetParam: string
|
|
depth: number
|
|
}
|
|
|
|
interface MappingEditorProps {
|
|
lfoIndex: number
|
|
mappings: Mapping[]
|
|
onUpdateDepth: (paramId: string, depth: number) => void
|
|
onRemoveMapping: (paramId: string) => void
|
|
onClose: () => void
|
|
}
|
|
|
|
export function MappingEditor({ lfoIndex, mappings, onUpdateDepth, onRemoveMapping, onClose }: MappingEditorProps) {
|
|
return (
|
|
<>
|
|
<div className="fixed inset-0 z-50" onClick={onClose} />
|
|
<div className="fixed inset-0 pointer-events-none flex items-center justify-center z-50">
|
|
<div
|
|
className="bg-black border-2 border-white p-4 min-w-[300px] max-w-[400px] pointer-events-auto"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className="flex justify-between items-center mb-4">
|
|
<h2 className="font-mono text-sm tracking-[0.15em] text-white">
|
|
LFO {lfoIndex + 1} MAPPINGS
|
|
</h2>
|
|
<button
|
|
onClick={onClose}
|
|
className="font-mono text-xs text-white hover:bg-white hover:text-black px-2 py-1 border-2 border-white"
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
|
|
{mappings.length === 0 ? (
|
|
<div className="font-mono text-xs text-white text-center py-4">
|
|
NO MAPPINGS
|
|
</div>
|
|
) : (
|
|
<div className="space-y-3">
|
|
{mappings.map((mapping) => {
|
|
const meta = parameterRegistry.getMetadata(mapping.targetParam)
|
|
return (
|
|
<div key={mapping.targetParam} className="border-2 border-white p-2">
|
|
<div className="flex justify-between items-center mb-2">
|
|
<span className="font-mono text-xs text-white tracking-[0.1em]">
|
|
{meta?.label ?? mapping.targetParam}
|
|
</span>
|
|
<button
|
|
onClick={() => onRemoveMapping(mapping.targetParam)}
|
|
className="font-mono text-[10px] text-white hover:bg-white hover:text-black px-1 border border-white"
|
|
>
|
|
REMOVE
|
|
</button>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<input
|
|
type="range"
|
|
min="0"
|
|
max="100"
|
|
step="1"
|
|
value={mapping.depth}
|
|
onChange={(e) => onUpdateDepth(mapping.targetParam, Number(e.target.value))}
|
|
className="flex-1 h-[2px] appearance-none cursor-pointer slider bg-white"
|
|
/>
|
|
<span className="font-mono text-xs text-white w-12 text-right">
|
|
{mapping.depth}%
|
|
</span>
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|