mihirmithani
Add Kernel Convolution Visualizer - Phase 1 complete
80bcac8
Raw History Blame
4.88 kB
'use client'
import { useAppStore } from '@/store'
import { PADDING_MODES } from '@/lib/kernels'
import { Select, Card, CardContent, Slider, Button } from '@/components/ui'
import { cn } from '@/utils/helpers'
import { Settings, Layers, Grid } from 'lucide-react'
export function OverlayControls() {
const { settings, updateSettings, toggleOverlay, setPadding } = useAppStore()
const { showOverlay, padding } = settings
return (
<Card className="w-full">
<CardContent className="p-4 space-y-4">
<h3 className="font-medium flex items-center gap-2">
<Settings className="h-4 w-4" />
Visualization Overlays
</h3>
<div className="grid grid-cols-2 gap-2">
{Object.entries(showOverlay).map(([key, value]) => (
<label key={key} className="flex items-center gap-2 cursor-pointer">
<input
type="checkbox"
checked={value}
onChange={() => toggleOverlay(key as keyof typeof showOverlay)}
className="rounded border-gray-300"
/>
<span className="text-sm capitalize">{key.replace(/([A-Z])/g, ' $1')}</span>
</label>
))}
</div>
</CardContent>
</Card>
)
}
export function PaddingControls() {
const { settings, setPadding } = useAppStore()
const { padding } = settings
return (
<Card className="w-full">
<CardContent className="p-4 space-y-4">
<h3 className="font-medium flex items-center gap-2">
<Grid className="h-4 w-4" />
Padding Strategy
</h3>
<Select
value={padding}
onChange={(e) => setPadding(e.target.value as typeof padding)}
options={PADDING_MODES.map((p) => ({ value: p.value, label: p.label }))}
placeholder="Select padding mode"
/>
<div className="text-sm text-gray-500 dark:text-gray-400">
{PADDING_MODES.find((p) => p.value === padding)?.description}
</div>
{/* Padding visualization would go here */}
</CardContent>
</Card>
)
}
export function KernelInfoPanel() {
const { selectedKernel } = useAppStore()
if (!selectedKernel) {
return (
<Card className="w-full">
<CardContent className="p-4 text-center text-gray-500">
No kernel selected
</CardContent>
</Card>
)
}
const { name, category, matrix, size, normalize, description, formula, reference } = selectedKernel
return (
<Card className="w-full">
<CardContent className="p-4 space-y-4">
<div className="flex items-start justify-between gap-4">
<div>
<h3 className="font-medium">{name}</h3>
<div className="flex items-center gap-2 mt-1">
<span className="px-2 py-0.5 text-xs bg-blue-100 text-blue-800 rounded dark:bg-blue-900/30 dark:text-blue-300">
{category}
</span>
<span className="px-2 py-0.5 text-xs bg-gray-100 text-gray-800 rounded dark:bg-gray-800 dark:text-gray-300">
{size}×{size}
</span>
{normalize && (
<span className="px-2 py-0.5 text-xs bg-green-100 text-green-800 rounded dark:bg-green-900/30 dark:text-green-300">
Normalized
</span>
)}
</div>
</div>
</div>
<p className="text-sm text-gray-600 dark:text-gray-400">{description}</p>
{formula && (
<div className="p-3 bg-gray-50 dark:bg-gray-800 rounded font-mono text-sm">
<span className="text-gray-500">Formula: </span>
<span>{formula}</span>
</div>
)}
<div className="space-y-2">
<h4 className="text-sm font-medium">Kernel Matrix</h4>
<div className="grid gap-1" style={{ gridTemplateColumns: `repeat(${size}, 1fr)` }}>
{matrix.map((row, i) =>
row.map((val, j) => (
<div
key={`${i}-${j}`}
className={cn(
'p-2 text-center text-sm font-mono rounded',
val > 0 ? 'bg-green-50 text-green-800 dark:bg-green-900/30 dark:text-green-300' : 'bg-red-50 text-red-800 dark:bg-red-900/30 dark:text-red-300'
)}
>
{val.toFixed(val === Math.round(val) ? 0 : 2)}
</div>
))
)}
</div>
</div>
{reference && (
<a
href={reference}
target="_blank"
rel="noopener noreferrer"
className="text-sm text-blue-600 hover:underline flex items-center gap-1"
>
<Layers className="h-3 w-3" />
Reference
</a>
)}
</CardContent>
</Card>
)
}