Added padding around effects device rack and gap between effect cards for better visual integration and spacing. Changes: - Added p-3 padding to effects rack container - Added gap-3 between effect device cards - Improves visual consistency and readability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
129 lines
4.3 KiB
TypeScript
129 lines
4.3 KiB
TypeScript
'use client';
|
|
|
|
import * as React from 'react';
|
|
import { Plus, ChevronDown, ChevronRight } from 'lucide-react';
|
|
import type { Track as TrackType } from '@/types/track';
|
|
import { Button } from '@/components/ui/Button';
|
|
import { cn } from '@/lib/utils/cn';
|
|
import { EffectDevice } from '@/components/effects/EffectDevice';
|
|
import { EffectBrowser } from '@/components/effects/EffectBrowser';
|
|
import type { EffectType } from '@/lib/audio/effects/chain';
|
|
|
|
export interface TrackExtensionsProps {
|
|
track: TrackType;
|
|
onUpdateTrack: (trackId: string, updates: Partial<TrackType>) => void;
|
|
onToggleEffect?: (effectId: string) => void;
|
|
onRemoveEffect?: (effectId: string) => void;
|
|
onUpdateEffect?: (effectId: string, parameters: any) => void;
|
|
onAddEffect?: (effectType: EffectType) => void;
|
|
}
|
|
|
|
export function TrackExtensions({
|
|
track,
|
|
onUpdateTrack,
|
|
onToggleEffect,
|
|
onRemoveEffect,
|
|
onUpdateEffect,
|
|
onAddEffect,
|
|
}: TrackExtensionsProps) {
|
|
const [effectBrowserOpen, setEffectBrowserOpen] = React.useState(false);
|
|
|
|
// Don't render if track is collapsed
|
|
if (track.collapsed) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<>
|
|
{/* Effects Section (Collapsible, Full Width) */}
|
|
<div className="bg-muted/50 border-b border-border/50">
|
|
{/* Effects Header - clickable to toggle */}
|
|
<div
|
|
className="flex items-center gap-2 px-3 py-1.5 cursor-pointer hover:bg-accent/30 transition-colors"
|
|
onClick={() => {
|
|
onUpdateTrack(track.id, {
|
|
showEffects: !track.showEffects,
|
|
});
|
|
}}
|
|
>
|
|
{track.showEffects ? (
|
|
<ChevronDown className="h-3.5 w-3.5 text-muted-foreground flex-shrink-0" />
|
|
) : (
|
|
<ChevronRight className="h-3.5 w-3.5 text-muted-foreground flex-shrink-0" />
|
|
)}
|
|
|
|
{/* Show mini effect chain when collapsed */}
|
|
{!track.showEffects && track.effectChain.effects.length > 0 ? (
|
|
<div className="flex-1 flex items-center gap-1 overflow-x-auto custom-scrollbar">
|
|
{track.effectChain.effects.map((effect) => (
|
|
<div
|
|
key={effect.id}
|
|
className={cn(
|
|
'px-2 py-0.5 rounded text-[10px] font-medium flex-shrink-0',
|
|
effect.enabled
|
|
? 'bg-primary/20 text-primary border border-primary/30'
|
|
: 'bg-muted/30 text-muted-foreground border border-border'
|
|
)}
|
|
>
|
|
{effect.name}
|
|
</div>
|
|
))}
|
|
</div>
|
|
) : (
|
|
<span className="text-xs font-medium text-muted-foreground">
|
|
Devices ({track.effectChain.effects.length})
|
|
</span>
|
|
)}
|
|
|
|
<Button
|
|
variant="ghost"
|
|
size="icon-sm"
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
setEffectBrowserOpen(true);
|
|
}}
|
|
title="Add effect"
|
|
className="h-5 w-5 flex-shrink-0"
|
|
>
|
|
<Plus className="h-3 w-3" />
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Horizontal scrolling device rack - expanded state */}
|
|
{track.showEffects && (
|
|
<div className="h-48 overflow-x-auto custom-scrollbar bg-muted/70 p-3">
|
|
<div className="flex h-full gap-3">
|
|
{track.effectChain.effects.length === 0 ? (
|
|
<div className="text-xs text-muted-foreground text-center py-8 w-full">
|
|
No devices. Click + to add an effect.
|
|
</div>
|
|
) : (
|
|
track.effectChain.effects.map((effect) => (
|
|
<EffectDevice
|
|
key={effect.id}
|
|
effect={effect}
|
|
onToggleEnabled={() => onToggleEffect?.(effect.id)}
|
|
onRemove={() => onRemoveEffect?.(effect.id)}
|
|
onUpdateParameters={(params) => onUpdateEffect?.(effect.id, params)}
|
|
/>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Effect Browser Dialog */}
|
|
<EffectBrowser
|
|
open={effectBrowserOpen}
|
|
onClose={() => setEffectBrowserOpen(false)}
|
|
onSelectEffect={(effectType) => {
|
|
if (onAddEffect) {
|
|
onAddEffect(effectType);
|
|
}
|
|
}}
|
|
/>
|
|
</>
|
|
);
|
|
}
|