feat(viz): bit display primitive
This commit is contained in:
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user