forked from averyfelts/Lofi_Generator
work in progress implementation of: - mixer with channel strips, faders, pan knobs, level meters - timeline with ruler, playhead, sections, keyframe tracks - pattern and progression pickers for drums/chords - automation lanes and mute tracks - loop bracket for loop region selection - export modal placeholder known issues: - drum pattern changes don't update audio engine - timeline keyframes not connected to scheduler - some UI bugs remain this is a checkpoint commit for further iteration
53 lines
1.2 KiB
TypeScript
53 lines
1.2 KiB
TypeScript
'use client';
|
|
|
|
import { useMemo } from 'react';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
interface LevelMeterProps {
|
|
level: number;
|
|
className?: string;
|
|
orientation?: 'vertical' | 'horizontal';
|
|
}
|
|
|
|
export function LevelMeter({
|
|
level,
|
|
className,
|
|
orientation = 'vertical',
|
|
}: LevelMeterProps) {
|
|
const segments = useMemo(() => {
|
|
const count = 8;
|
|
const filled = Math.round(level * count);
|
|
return Array.from({ length: count }, (_, i) => {
|
|
const segmentLevel = (i + 1) / count;
|
|
const isActive = i < filled;
|
|
let color = 'bg-emerald-500';
|
|
if (segmentLevel > 0.85) color = 'bg-red-500';
|
|
else if (segmentLevel > 0.7) color = 'bg-yellow-500';
|
|
return { isActive, color };
|
|
});
|
|
}, [level]);
|
|
|
|
const isVertical = orientation === 'vertical';
|
|
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'flex gap-0.5',
|
|
isVertical ? 'flex-col-reverse w-2' : 'flex-row h-2 w-16',
|
|
className
|
|
)}
|
|
>
|
|
{segments.map((seg, i) => (
|
|
<div
|
|
key={i}
|
|
className={cn(
|
|
'flex-1 rounded-sm transition-opacity duration-75',
|
|
seg.isActive ? seg.color : 'bg-muted/30',
|
|
seg.isActive ? 'opacity-100' : 'opacity-50'
|
|
)}
|
|
/>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|