99 lines
2.6 KiB
TypeScript
99 lines
2.6 KiB
TypeScript
/**
|
||
* FxInsertSlot — a single FX insert on a channel strip.
|
||
*
|
||
* Shows:
|
||
* - Plugin name
|
||
* - Bypass toggle button
|
||
* - Wet/dry mix slider
|
||
* - Remove button
|
||
*/
|
||
import React, { useCallback } from 'react';
|
||
import type { FxInsert } from '../../hooks/useFxInserts';
|
||
import './FxInsertPanel.css';
|
||
|
||
interface FxInsertSlotProps {
|
||
insert: FxInsert;
|
||
accentColor: string;
|
||
onToggleBypass: (id: string, currentBypassed: boolean) => void;
|
||
onWetDryChange: (id: string, wetDry: number) => void;
|
||
onRemove: (id: string) => void;
|
||
}
|
||
|
||
const FxInsertSlot: React.FC<FxInsertSlotProps> = ({
|
||
insert,
|
||
accentColor,
|
||
onToggleBypass,
|
||
onWetDryChange,
|
||
onRemove,
|
||
}) => {
|
||
const handleBypass = useCallback(() => {
|
||
onToggleBypass(insert.id, insert.bypassed);
|
||
}, [insert.id, insert.bypassed, onToggleBypass]);
|
||
|
||
const handleWetDry = useCallback(
|
||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||
onWetDryChange(insert.id, parseFloat(e.target.value));
|
||
},
|
||
[insert.id, onWetDryChange],
|
||
);
|
||
|
||
const handleRemove = useCallback(() => {
|
||
onRemove(insert.id);
|
||
}, [insert.id, onRemove]);
|
||
|
||
const wetDryPercent = Math.round(insert.wet_dry_mix * 100);
|
||
|
||
return (
|
||
<div
|
||
className={`fx-insert-slot ${insert.bypassed ? 'bypassed' : ''}`}
|
||
style={
|
||
{
|
||
'--fx-accent': accentColor,
|
||
} as React.CSSProperties
|
||
}
|
||
>
|
||
{/* Header: plugin name + bypass + remove */}
|
||
<div className="fx-insert-header">
|
||
<span
|
||
className={`fx-insert-bypass-btn ${insert.bypassed ? 'active' : ''}`}
|
||
onClick={handleBypass}
|
||
title={insert.bypassed ? 'Enable insert' : 'Bypass insert'}
|
||
>
|
||
{insert.bypassed ? 'OFF' : 'ON'}
|
||
</span>
|
||
<span className="fx-insert-name" title={insert.plugin_name}>
|
||
{insert.plugin_name}
|
||
</span>
|
||
<button
|
||
className="fx-insert-remove"
|
||
onClick={handleRemove}
|
||
title="Remove insert"
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
|
||
{/* Wet/dry mix slider */}
|
||
{!insert.bypassed && (
|
||
<div className="fx-insert-wetdry">
|
||
<label className="fx-insert-wetdry-label">Mix</label>
|
||
<input
|
||
type="range"
|
||
min="0"
|
||
max="1"
|
||
step="0.01"
|
||
value={insert.wet_dry_mix}
|
||
onChange={handleWetDry}
|
||
className="fx-insert-wetdry-slider"
|
||
title={`Wet/Dry: ${wetDryPercent}%`}
|
||
/>
|
||
<span className="fx-insert-wetdry-readout">{wetDryPercent}%</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export { FxInsertSlot };
|
||
export default FxInsertSlot;
|