import { useState, useEffect } from 'react'; import { EditorPluginManager, IEditorPluginMetadata, EditorPluginCategory } from '@esengine/editor-core'; import * as LucideIcons from 'lucide-react'; import { Package, CheckCircle, XCircle, Search, Grid, List, ChevronDown, ChevronRight } from 'lucide-react'; import '../styles/PluginPanel.css'; interface PluginPanelProps { pluginManager: EditorPluginManager; } const categoryIcons: Record = { [EditorPluginCategory.Tool]: 'Wrench', [EditorPluginCategory.Window]: 'LayoutGrid', [EditorPluginCategory.Inspector]: 'Search', [EditorPluginCategory.System]: 'Settings', [EditorPluginCategory.ImportExport]: 'Package' }; const categoryNames: Record = { [EditorPluginCategory.Tool]: 'Tools', [EditorPluginCategory.Window]: 'Windows', [EditorPluginCategory.Inspector]: 'Inspectors', [EditorPluginCategory.System]: 'System', [EditorPluginCategory.ImportExport]: 'Import/Export' }; export function PluginPanel({ pluginManager }: PluginPanelProps) { const [plugins, setPlugins] = useState([]); const [filter, setFilter] = useState(''); const [viewMode, setViewMode] = useState<'grid' | 'list'>('list'); const [expandedCategories, setExpandedCategories] = useState>( new Set(Object.values(EditorPluginCategory)) ); useEffect(() => { const updatePlugins = () => { const allPlugins = pluginManager.getAllPluginMetadata(); setPlugins(allPlugins); }; updatePlugins(); }, [pluginManager]); const togglePlugin = async (name: string, enabled: boolean) => { try { if (enabled) { await pluginManager.disablePlugin(name); } else { await pluginManager.enablePlugin(name); } const allPlugins = pluginManager.getAllPluginMetadata(); setPlugins(allPlugins); } catch (error) { console.error(`Failed to toggle plugin ${name}:`, error); } }; const toggleCategory = (category: EditorPluginCategory) => { const newExpanded = new Set(expandedCategories); if (newExpanded.has(category)) { newExpanded.delete(category); } else { newExpanded.add(category); } setExpandedCategories(newExpanded); }; const filteredPlugins = plugins.filter((plugin) => { if (!filter) return true; const searchLower = filter.toLowerCase(); return ( plugin.name.toLowerCase().includes(searchLower) || plugin.displayName.toLowerCase().includes(searchLower) || plugin.description?.toLowerCase().includes(searchLower) ); }); const pluginsByCategory = filteredPlugins.reduce((acc, plugin) => { if (!acc[plugin.category]) { acc[plugin.category] = []; } acc[plugin.category].push(plugin); return acc; }, {} as Record); const enabledCount = plugins.filter((p) => p.enabled).length; const disabledCount = plugins.filter((p) => !p.enabled).length; const renderPluginCard = (plugin: IEditorPluginMetadata) => { const IconComponent = plugin.icon ? (LucideIcons as any)[plugin.icon] : null; return (
{IconComponent ? : }
{plugin.displayName}
v{plugin.version}
{plugin.description && (
{plugin.description}
)}
{(() => { const CategoryIcon = (LucideIcons as any)[categoryIcons[plugin.category]]; return CategoryIcon ? : null; })()} {categoryNames[plugin.category]} {plugin.installedAt && ( Installed: {new Date(plugin.installedAt).toLocaleDateString()} )}
); }; const renderPluginList = (plugin: IEditorPluginMetadata) => { const IconComponent = plugin.icon ? (LucideIcons as any)[plugin.icon] : null; return (
{IconComponent ? : }
{plugin.displayName} v{plugin.version}
{plugin.description && (
{plugin.description}
)}
{plugin.enabled ? ( Enabled ) : ( Disabled )}
); }; return (
setFilter(e.target.value)} />
{enabledCount} enabled {disabledCount} disabled
{plugins.length === 0 ? (

No plugins installed

) : (
{Object.entries(pluginsByCategory).map(([category, categoryPlugins]) => { const cat = category as EditorPluginCategory; const isExpanded = expandedCategories.has(cat); return (
toggleCategory(cat)} > {(() => { const CategoryIcon = (LucideIcons as any)[categoryIcons[cat]]; return CategoryIcon ? : null; })()} {categoryNames[cat]} {categoryPlugins.length}
{isExpanded && (
{viewMode === 'grid' ? categoryPlugins.map(renderPluginCard) : categoryPlugins.map(renderPluginList)}
)}
); })}
)}
); }