/** * Layer Detail Panel * * Shows detailed information about the selected layer. */ import React from 'react'; import type { HierarchyNode } from '@/core/model-hierarchy'; import { getLayerColor } from '@/core/layer-geometry'; import styles from './LayerDetailPanel.module.css'; export interface LayerDetailPanelProps { node: HierarchyNode | null; onClose: () => void; } export const LayerDetailPanel: React.FC = ({ node, onClose, }) => { if (!node) return null; const color = getLayerColor(node.category); const layer = node.layerData; return (
{node.category}

{node.displayName}

{node.name}

{/* Type Info */} {layer && (
{layer.type} {layer.trainable ? '[TRAINABLE]' : '[FROZEN]'}
)} {/* Shapes */}
{/* Parameters */}
{formatNumber(node.totalParams)} Total
{node.layerCount > 1 && (
{node.layerCount} Layers
)}
{/* Layer-specific params */} {layer?.params && Object.keys(layer.params).length > 0 && (
{Object.entries(layer.params).map(([key, value]) => (
{formatKey(key)} {formatValue(value)}
))}
)} {/* Children (for groups) */} {node.children.length > 0 && (
{node.children.slice(0, 10).map(child => (
{child.displayName} {child.layerData?.type || child.category}
))} {node.children.length > 10 && (
+ {node.children.length - 10} more...
)}
)} {/* Position Info */}
Level {getLevelName(node.level)}
Depth {node.depth.toFixed(1)}
Channels {node.channelSize}
); }; // Helper Components const Section: React.FC<{ title: string; children: React.ReactNode }> = ({ title, children }) => (

{title}

{children}
); const ShapeRow: React.FC<{ label: string; shape: number[] | null; color: string; }> = ({ label, shape, color }) => (
{label} {shape ? `[${shape.map(d => d === -1 ? '?' : d).join(', ')}]` : 'N/A'}
); // Helper Functions function formatNumber(num: number): string { if (num >= 1e9) return `${(num / 1e9).toFixed(2)}B`; if (num >= 1e6) return `${(num / 1e6).toFixed(2)}M`; if (num >= 1e3) return `${(num / 1e3).toFixed(2)}K`; return num.toLocaleString(); } function formatKey(key: string): string { return key .replace(/_/g, ' ') .replace(/([a-z])([A-Z])/g, '$1 $2') .split(' ') .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(' '); } function formatValue(value: unknown): string { if (value === null || value === undefined) return 'N/A'; if (typeof value === 'boolean') return value ? 'Yes' : 'No'; if (Array.isArray(value)) return `[${value.join(', ')}]`; if (typeof value === 'number') { return Number.isInteger(value) ? value.toString() : value.toFixed(4); } return String(value); } function getLevelName(level: 1 | 2 | 3): string { switch (level) { case 1: return 'Macro (Module)'; case 2: return 'Stage (Block)'; case 3: return 'Layer (Operation)'; } } export default LayerDetailPanel;