feat(viz): bit display primitive

This commit is contained in:
2025-09-04 00:22:32 +01:00
parent af0ba5c13e
commit edfa3d456c

View File

@@ -0,0 +1,84 @@
'use client';
import { motion } from 'framer-motion';
import { cn } from '@/lib/utils';
import type { BitState } from '@/lib/visualizations/types';
interface BitDisplayProps {
bit: BitState;
bitWidth?: number;
showLabel?: boolean;
showDecimal?: boolean;
className?: string;
}
const STATE_CLASSES = {
normal: 'bg-[var(--muted)] border-[var(--border)] text-[var(--foreground)]',
highlighted: 'bg-[var(--primary)]/20 border-[var(--primary)] text-[var(--primary)]',
comparing: 'bg-amber-500/20 border-amber-500 text-amber-500 shadow-[0_0_8px_rgba(245,158,11,0.4)]',
result: 'bg-green-500/20 border-green-500 text-green-500',
cancelled: 'bg-[var(--muted)]/30 border-[var(--border)]/50 text-[var(--muted-foreground)] opacity-40',
} as const;
export function BitDisplay({
bit,
bitWidth = 8,
showLabel = true,
showDecimal = true,
className,
}: BitDisplayProps) {
// Pad the bits string to the desired width
const paddedBits = bit.bits.padStart(bitWidth, '0');
return (
<div className={cn('flex flex-col items-center gap-1', className)}>
{/* Label (e.g., "result", "num") */}
{showLabel && bit.label && (
<span className="text-xs font-medium text-[var(--muted-foreground)]">
{bit.label}
</span>
)}
{/* Decimal value display */}
{showDecimal && (
<span
className={cn(
'text-sm font-mono font-medium mb-1',
bit.state === 'cancelled'
? 'text-[var(--muted-foreground)] line-through opacity-50'
: 'text-[var(--foreground)]'
)}
>
{bit.value}
</span>
)}
{/* Binary representation - individual bit cells */}
<motion.div
layout
initial={false}
animate={{
scale: bit.state === 'highlighted' || bit.state === 'comparing' ? 1.02 : 1,
}}
transition={{ duration: 0.2 }}
className={cn(
'flex items-center rounded-lg border-2 overflow-hidden',
STATE_CLASSES[bit.state]
)}
>
{paddedBits.split('').map((bitChar, index) => (
<div
key={index}
className={cn(
'w-6 h-8 flex items-center justify-center font-mono text-sm font-medium',
index > 0 && 'border-l border-[var(--border)]/30',
bit.state === 'cancelled' && 'line-through'
)}
>
{bitChar}
</div>
))}
</motion.div>
</div>
);
}