UNPKG

circuit-bricks

Version:

A modular, Lego-style SVG circuit component system for React (ALPHA - Not for production use)

1,173 lines (955 loc) 34.7 kB
# Circuit-Bricks A React + TypeScript library for creating SVG-based electrical circuit diagrams with a Lego-style component system. > **⚠️ DEVELOPMENT STATUS:** This library is currently in early development stage and not recommended for production use. APIs may change, features might be incomplete, and there could be significant bugs. Use at your own risk. ## 🤖 Perfect for LLM Integration Circuit-Bricks is designed from the ground up to work seamlessly with Large Language Models. Create intelligent circuit design applications where users can describe circuits in natural language and see them rendered instantly. **Quick Start:** Jump to [Quick Start for LLM Integration](#quick-start-for-llm-integration) to get up and running in minutes. **Key Benefits for LLM Integration:** - 📋 **Schema-Driven**: Comprehensive component schemas for LLM context - 🎨 **Instant Visualization**: Real-time circuit rendering with CircuitCanvas - 🔧 **Validation Built-in**: Automatic circuit validation and error handling - 🎯 **Educational Focus**: Perfect for learning applications and circuit explanation - 🌙 **Dark Theme Ready**: Optimized for modern dark UI themes ## Features - **Modular Component System**: Each electrical element is a self-contained SVG "brick" - **Infinite Canvas**: Free-flowing design with pan and zoom capabilities for circuits of any size - **Pure Rendering Core**: Focuses on rendering with optional editing UI components - **AI-First Design**: Comprehensive LLM integration API for component discovery and circuit generation - **TypeScript Support**: Fully typed API for better developer experience - **SVG-Based Rendering**: Vector graphics for crisp rendering at any scale - **Component Registry**: Extensible system for creating custom circuit elements - **Customizable UI Components**: Optional UI elements for circuit editing - **Headless UI Components**: Unstyled components for complete styling flexibility - **Dual Package Format**: Supports both ESM and CommonJS - **Runtime Validation**: ZOD schema validation for component schemas and circuit states ## Installation ```bash # npm npm install circuit-bricks # yarn yarn add circuit-bricks # pnpm pnpm add circuit-bricks ``` ## Quick Start for LLM Integration If you're here to integrate Circuit-Bricks with LLMs, here's the fastest way to get started: ### 1. Install Dependencies ```bash npm install circuit-bricks ai @openrouter/ai-sdk-provider react-markdown ``` ### 2. Create API Route ```typescript // app/api/chat/route.ts import { streamText } from 'ai'; import { createOpenRouter } from '@openrouter/ai-sdk-provider'; import { getAllComponentSchemas } from 'circuit-bricks/llm'; const openrouter = createOpenRouter({ apiKey: process.env.OPENROUTER_API_KEY, }); export async function POST(req: Request) { const { messages } = await req.json(); const schemas = getAllComponentSchemas(); const result = await streamText({ model: openrouter('mistralai/mistral-7b-instruct:free'), messages, system: `You are an electrical engineering expert. Use these schemas: ${JSON.stringify(schemas)}. Wrap circuit JSON in "circuit" tags.`, }); return result.toDataStreamResponse(); } ``` ### 3. Create Frontend Component ```tsx // components/CircuitChat.tsx import { useChat } from 'ai/react'; import { CircuitCanvas } from 'circuit-bricks'; export default function CircuitChat() { const [circuit, setCircuit] = useState(null); const { messages, input, handleInputChange, handleSubmit } = useChat({ api: '/api/chat', onFinish: (message) => { const match = message.content.match(/circuit\s*\n([\s\S]*?)\ncircuit/); if (match) setCircuit(JSON.parse(match[1])); } }); return ( <div className="flex h-screen"> <div className="w-2/5 p-4"> {/* Chat interface */} <form onSubmit={handleSubmit}> <input value={input} onChange={handleInputChange} placeholder="Create an LED circuit..." /> </form> </div> <div className="w-3/5"> {circuit && ( <CircuitCanvas components={circuit.components} wires={circuit.wires} width="100%" height="100%" /> )} </div> </div> ); } ``` That's it! You now have a working LLM-powered circuit designer. See the [LLM Integration API](#llm-integration-api) section for more details. ## Development Status **Circuit-Bricks is currently in active development and should NOT be used in production environments.** - **Alpha Stage**: The API is subject to change without notice - **Limited Testing**: While we have tests, real-world usage is limited - **Incomplete Features**: Some advanced features may still be in development - **Possible Bugs**: You may encounter unexpected issues - **Performance Tuning**: Optimizations are still ongoing We welcome contributors and early adopters to help shape the future of the library, but please be aware of the current limitations before integrating it into critical projects. For the latest updates on stability and roadmap, please check our [GitHub repository](https://github.com/sphere-labs/circuit-bricks). ## Security Circuit-Bricks is designed with security in mind: - No external dependencies in the production build - Regular security audits on all dependencies - Complete type safety with TypeScript - Runtime validation with ZOD schemas - Content Security Policy (CSP) compatible - no inline scripts or styles - All SVG content is properly sanitized To verify the security of the package: ```bash # Run a security audit npm audit --production # Check for outdated dependencies npm outdated ``` ## Quick Start Here's a simple example to get you started: ```tsx import React from 'react'; import { CircuitCanvas, useCircuit } from 'circuit-bricks'; const SimpleCircuitExample = () => { const [state, actions] = useCircuit(); // Add a battery, resistor and LED on mount React.useEffect(() => { const batteryId = actions.addComponent({ type: 'battery', position: { x: 100, y: 150 }, props: { voltage: 9 } }); const resistorId = addComponent({ type: 'resistor', position: { x: 250, y: 100 }, props: { resistance: 1000 } }); const ledId = addComponent({ type: 'led', position: { x: 400, y: 150 }, props: { color: '#ff0000' } }); const groundId = addComponent({ type: 'ground', position: { x: 250, y: 200 }, props: {} }); // Connect components addWire({ from: { componentId: batteryId, portId: 'positive' }, to: { componentId: resistorId, portId: 'left' } }); addWire({ from: { componentId: resistorId, portId: 'right' }, to: { componentId: ledId, portId: 'anode' } }); addWire({ from: { componentId: ledId, portId: 'cathode' }, to: { componentId: groundId, portId: 'terminal' } }); addWire({ from: { componentId: batteryId, portId: 'negative' }, to: { componentId: groundId, portId: 'terminal' } }); }, [addComponent, addWire]); return ( <div style={{ width: '100%', height: '500px' }}> <CircuitCanvas components={components} wires={wires} onComponentClick={(id) => setSelectedComponent(id)} showGrid={true} /> </div> ); }; ``` ## Available Components The library includes a variety of built-in electrical components: ### Basic Components - Resistor - Capacitor - Switch - Ground ### Power Sources - Battery - Voltage Source ### Semiconductors - Diode - LED - Transistor (NPN) ### Advanced - Integrated Circuit (generic) ## Component System Components in Circuit-Bricks are defined by JSON schemas that specify their appearance, connection points, and configurable properties. ### Component Schema ```typescript interface ComponentSchema { id: string; // Unique identifier for the component type name: string; // Human-readable name for display category: string; // Category grouping for UI organization description: string; // Description of the component defaultWidth: number; // Default width in SVG units defaultHeight: number; // Default height in SVG units ports: PortSchema[]; // Connection points definition properties: PropertySchema[]; // Configurable properties svgPath: string; // SVG path data or complete SVG markup } ``` ### Custom Components You can create and register your own components: ```tsx import { registerComponent, validateComponentSchema } from 'circuit-bricks'; const customComponent = { id: 'custom-op-amp', name: 'Op-Amp', category: 'integrated', description: 'Operational Amplifier', defaultWidth: 60, defaultHeight: 60, ports: [ { id: 'in+', x: 0, y: 20, type: 'input', label: '+' }, { id: 'in-', x: 0, y: 40, type: 'input', label: '-' }, { id: 'out', x: 60, y: 30, type: 'output' }, { id: 'vcc', x: 30, y: 0, type: 'input' }, { id: 'gnd', x: 30, y: 60, type: 'input' } ], properties: [ { key: 'gain', label: 'Gain', type: 'number', default: 100000 } ], svgPath: 'M10,25 h80' // SVG path data }); // Validate the component schema before registering const validationResult = validateComponentSchema(customComponent); if (validationResult.success) { registerComponent(customComponent); } else { console.error('Invalid component schema:', validationResult.error); } ``` ## Main Components ### CircuitCanvas The main container component that renders a circuit: ```tsx <CircuitCanvas components={componentMap} wires={wireMap} width={800} height={600} showGrid={true} gridSize={20} onComponentClick={(id) => {}} onWireClick={(id) => {}} onCanvasClick={() => {}} /> ``` ### Headless UI Components Circuit-Bricks provides headless (unstyled) versions of all UI components, allowing you to fully customize the appearance using your preferred styling method: ```tsx import { HeadlessPropertyPanel, HeadlessComponentPalette, HeadlessCircuitToolbar } from 'circuit-bricks'; // Use with custom styling <HeadlessPropertyPanel component={selectedComponent} onPropertyChange={handlePropertyChange} className="custom-panel" classNames={{ header: "custom-header", title: "custom-title" }} style={{ backgroundColor: '#ffffff' }} styles={{ header: { padding: '16px' }, title: { fontSize: '18px' } }} /> ``` Headless components provide all the functionality without any styling, giving you complete control over the appearance while maintaining accessibility and behavior. See the [Headless Components](./Docs/HEADLESS-COMPONENTS.md) documentation for more details. ### Hooks and State Management Circuit-Bricks provides a powerful hook for managing circuit state: ```tsx const { // Circuit state components, // Map of component instances wires, // Map of wire connections selectedComponent, // Selected component ID selectedWire, // Selected wire ID // Actions addComponent, // Add a new component updateComponent, // Update an existing component removeComponent, // Remove a component addWire, // Add a new wire updateWire, // Update a wire removeWire, // Remove a wire setSelectedComponent, // Select a component setSelectedWire, // Select a wire clearSelection, // Clear all selections validateCircuit, // Validate circuit and return issues // Validation utilities validateComponentSchema, // Validate component schema with ZOD validateComponentInstance, // Validate component instance with ZOD validateWire, // Validate wire with ZOD validateCircuitState // Validate circuit state with ZOD } = useCircuit(); ``` ### UI Components Optional UI components for circuit editing: ```tsx // Component property editor <PropertyPanel component={componentInstance} onPropertyChange={(key, value) => {}} /> // Component selection palette <ComponentPalette onSelectComponent={(type) => {}} filter={['basic', 'passive']} /> // Circuit operation toolbar <CircuitToolbar onAction={(action) => {}} hasSelection={true} /> ``` ## Complete Example: Interactive Circuit Editor Here's a complete example of an interactive circuit editor: ```tsx import React from 'react'; import { CircuitCanvas, useCircuit, PropertyPanel, ComponentPalette, CircuitToolbar } from 'circuit-bricks'; const CircuitEditor = () => { const { components, wires, addComponent, updateComponent, removeComponent, addWire, removeWire, selectedComponent, selectedWire, setSelectedComponent, setSelectedWire, clearSelection } = useCircuit(); const handleAction = (action) => { switch (action) { case 'delete': if (selectedComponent) { removeComponent(selectedComponent); } else if (selectedWire) { removeWire(selectedWire); } break; case 'rotate': if (selectedComponent) { const currentRotation = components[selectedComponent].rotation || 0; updateComponent(selectedComponent, { rotation: (currentRotation + 90) % 360 }); } break; default: break; } }; return ( <div style={{ display: 'flex', height: '100vh', flexDirection: 'column' }}> <div style={{ padding: '10px', borderBottom: '1px solid #ccc' }}> <CircuitToolbar onAction={handleAction} hasSelection={!!(selectedComponent || selectedWire)} /> </div> <div style={{ display: 'flex', flex: 1 }}> <div style={{ width: '200px', borderRight: '1px solid #ccc', overflow: 'auto' }}> <ComponentPalette onSelectComponent={(type) => { addComponent({ type, position: { x: 200, y: 200 }, props: {} }); }} /> </div> <div style={{ flex: 1, position: 'relative' }}> <CircuitCanvas components={components} wires={wires} showGrid={true} onComponentClick={(id) => { setSelectedComponent(id); setSelectedWire(null); }} onWireClick={(id) => { setSelectedWire(id); setSelectedComponent(null); }} onCanvasClick={() => { clearSelection(); }} /> </div> <div style={{ width: '250px', borderLeft: '1px solid #ccc', padding: '10px' }}> {selectedComponent && ( <PropertyPanel component={components[selectedComponent]} onPropertyChange={(key, value) => { updateComponent(selectedComponent, { props: { ...components[selectedComponent].props, [key]: value } }); }} /> )} {!selectedComponent && !selectedWire && ( <div className="empty-panel"> <p>Select a component or wire to view properties</p> </div> )} </div> </div> </div> ); }; ``` ## Examples and Demos Circuit-Bricks comes with several ready-to-use example circuits that showcase different features and use cases: ### Simple Circuit Example A basic circuit with a battery, resistor, and LED - perfect for getting started. ```tsx import { SimpleCircuitExample } from 'circuit-bricks'; const App = () => ( <div style={{ width: '800px', height: '600px' }}> <SimpleCircuitExample /> </div> ); ``` ### Interactive Circuit Editor A complete circuit editor with component palette, property panel, and circuit validation. ```tsx import { InteractiveCircuitExample } from 'circuit-bricks'; const App = () => ( <div style={{ width: '100%', height: '800px' }}> <InteractiveCircuitExample /> </div> ); ``` ### Voltage Regulator Circuit A 7805 voltage regulator circuit that converts 9V to 5V with input and output capacitors. ```tsx import { VoltageRegulatorExample } from 'circuit-bricks'; const App = () => ( <div style={{ width: '100%', height: '500px' }}> <VoltageRegulatorExample /> </div> ); ``` ### 555 Timer LED Blinker An astable multivibrator circuit using the 555 timer IC to blink an LED. ```tsx import { TimerCircuitExample } from 'circuit-bricks'; const App = () => ( <div style={{ width: '100%', height: '600px' }}> <TimerCircuitExample /> </div> ); ``` Each example is fully interactive and can be used as a starting point for your own circuits. You can also find these examples in the CodeSandbox demos. ## LLM Integration API Circuit-Bricks provides a comprehensive API specifically designed for Large Language Models (LLMs) to discover components and generate circuits programmatically. This section shows you how to integrate Circuit-Bricks with LLMs to create intelligent circuit design applications. ### Quick Start for LLMs ```typescript import { getAllComponentSchemas } from 'circuit-bricks/llm'; // Get all component schemas for LLM context const schemas = getAllComponentSchemas(); // Use schemas to provide context to your LLM const prompt = ` Available component schemas: ${JSON.stringify(schemas)} Create a circuit for: LED with current limiting resistor `; ``` ### Complete Integration Example Here's a complete example showing how to integrate Circuit-Bricks with an LLM API and render the results: #### 1. Backend API Route (Next.js) ```typescript // pages/api/chat/route.ts or app/api/chat/route.ts import { createOpenRouter } from '@openrouter/ai-sdk-provider'; import { streamText } from 'ai'; import { getAllComponentSchemas } from 'circuit-bricks/llm'; const openrouter = createOpenRouter({ apiKey: process.env.OPENROUTER_API_KEY, }); export async function POST(req: Request) { const { messages } = await req.json(); const userQuestion = messages[messages.length - 1]?.content; // Get component schemas for LLM context const schemas = getAllComponentSchemas(); const systemPrompt = ` You are an electrical engineering expert. Use these component schemas: ${JSON.stringify(schemas)} Create circuit diagrams based on user questions. Return your response with: 1. Educational explanation of the circuit 2. Circuit schema wrapped in "circuit" tags Example circuit format: circuit { "components": [ { "id": "battery_1", "type": "battery", "position": { "x": 100, "y": 200 }, "props": { "voltage": 9 } } ], "wires": [ { "id": "wire_1", "from": { "componentId": "battery_1", "portId": "positive" }, "to": { "componentId": "resistor_1", "portId": "left" } } ] } circuit `; const result = await streamText({ model: openrouter('mistralai/mistral-7b-instruct:free'), messages, system: systemPrompt, temperature: 0.3, }); return result.toDataStreamResponse(); } ``` #### 2. Frontend Integration ```tsx // components/CircuitChat.tsx import React, { useState } from 'react'; import { useChat } from 'ai/react'; import { CircuitCanvas } from 'circuit-bricks'; import ReactMarkdown from 'react-markdown'; const CircuitChat = () => { const [circuit, setCircuit] = useState(null); const { messages, input, handleInputChange, handleSubmit } = useChat({ api: '/api/chat', onFinish: (message) => { // Extract circuit from LLM response const circuitMatch = message.content.match(/circuit\s*\n([\s\S]*?)\ncircuit/); if (circuitMatch) { try { const circuitData = JSON.parse(circuitMatch[1]); setCircuit(circuitData); } catch (error) { console.error('Failed to parse circuit:', error); } } } }); return ( <div className="flex h-screen bg-gray-900 text-white"> {/* Chat Panel */} <div className="w-2/5 flex flex-col border-r border-gray-700"> <div className="flex-1 overflow-y-auto p-4 space-y-4"> {messages.map((message) => ( <div key={message.id} className={`${ message.role === 'user' ? 'text-blue-300' : 'text-gray-100' }`}> <div className="font-semibold mb-1"> {message.role === 'user' ? 'You' : 'Assistant'} </div> <ReactMarkdown className="prose prose-invert"> {message.content.replace(/circuit\s*\n[\s\S]*?\ncircuit/g, '[Circuit Generated]')} </ReactMarkdown> </div> ))} </div> <form onSubmit={handleSubmit} className="p-4 border-t border-gray-700"> <input value={input} onChange={handleInputChange} placeholder="Ask about circuits... (e.g., 'Create an LED circuit')" className="w-full p-2 bg-gray-800 border border-gray-600 rounded" /> </form> </div> {/* Circuit Visualization Panel */} <div className="w-3/5 flex flex-col"> <div className="p-4 border-b border-gray-700"> <h2 className="text-lg font-semibold">Circuit Diagram</h2> </div> <div className="flex-1 bg-gray-800"> {circuit ? ( <CircuitCanvas components={circuit.components || []} wires={circuit.wires || []} width="100%" height="100%" showGrid={true} gridSize={20} /> ) : ( <div className="flex items-center justify-center h-full text-gray-400"> Ask a question to generate a circuit diagram </div> )} </div> </div> </div> ); }; export default CircuitChat; ``` ### Key LLM Integration Functions **Schema Access:** - `getAllComponentSchemas()` - Get all component schemas for LLM context **Component Discovery:** - `listAvailableComponents()` - Get all available components - `searchComponents(query)` - Search components by name/description - `getComponentDetails(id)` - Get detailed component information **Validation:** - `validateCircuitDesign(circuit)` - Validate circuits with clear error messages - `validateComponentInstance(component)` - Validate individual components ### Best Practices for LLM Integration 1. **Provide Schema Context**: Always include component schemas in your LLM prompts 2. **Use Structured Output**: Request circuits in JSON format for easy parsing 3. **Handle Errors Gracefully**: Implement error boundaries for circuit rendering 4. **Validate Generated Circuits**: Use validation functions before rendering 5. **Educational Focus**: Combine circuit generation with educational explanations ### Environment Setup ```bash # Install required dependencies npm install ai @openrouter/ai-sdk-provider react-markdown # Set up environment variables OPENROUTER_API_KEY=your_api_key_here ``` For comprehensive LLM integration documentation, see the [AI Agent Guide](./Docs/AI-AGENT-GUIDE.md). ## CircuitCanvas for LLM-Generated Circuits The `CircuitCanvas` component is perfect for rendering circuits generated by LLMs. Here are specific patterns and tips for LLM integration: ### Dynamic Circuit Rendering ```tsx import React, { useState, useEffect } from 'react'; import { CircuitCanvas } from 'circuit-bricks'; const LLMCircuitRenderer = ({ circuitData, error }) => { const [components, setComponents] = useState([]); const [wires, setWires] = useState([]); const [renderError, setRenderError] = useState(null); useEffect(() => { if (circuitData) { try { // Validate and set circuit data setComponents(circuitData.components || []); setWires(circuitData.wires || []); setRenderError(null); } catch (err) { setRenderError('Failed to parse circuit data'); console.error('Circuit parsing error:', err); } } }, [circuitData]); if (error || renderError) { return ( <div className="flex items-center justify-center h-full bg-red-900/20 border border-red-800"> <div className="text-center"> <div className="text-red-400 mb-2">⚠️</div> <p className="text-red-300 font-medium">Circuit Error</p> <p className="text-red-400 text-sm mt-1">{error || renderError}</p> </div> </div> ); } return ( <div className="w-full h-full bg-gray-900"> <CircuitCanvas components={components} wires={wires} width="100%" height="100%" showGrid={true} gridSize={20} onComponentClick={(id) => console.log('Component clicked:', id)} onWireClick={(id) => console.log('Wire clicked:', id)} /> </div> ); }; ``` ### Split-Screen Layout (Recommended) ```tsx const CircuitChatApp = () => { return ( <div className="flex h-screen bg-gray-900"> {/* Chat Panel - 40% */} <div className="w-2/5 border-r border-gray-700"> <ChatInterface /> </div> {/* Circuit Panel - 60% */} <div className="w-3/5"> <CircuitCanvas components={generatedComponents} wires={generatedWires} width="100%" height="100%" showGrid={true} /> </div> </div> ); }; ``` ### Loading States and Error Handling ```tsx const CircuitVisualization = ({ isGenerating, circuit, error }) => { if (isGenerating) { return ( <div className="flex items-center justify-center h-full"> <div className="text-center"> <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 mx-auto mb-2"></div> <p className="text-gray-400">Generating circuit...</p> </div> </div> ); } if (error) { return ( <div className="flex items-center justify-center h-full bg-red-900/20"> <div className="text-center"> <p className="text-red-300">Failed to generate circuit</p> <p className="text-red-400 text-sm mt-1">{error}</p> </div> </div> ); } if (!circuit) { return ( <div className="flex items-center justify-center h-full text-gray-400"> Ask a question to generate a circuit diagram </div> ); } return ( <CircuitCanvas components={circuit.components} wires={circuit.wires} width="100%" height="100%" showGrid={true} /> ); }; ``` ### Circuit Validation Before Rendering ```tsx import { validateCircuitDesign } from 'circuit-bricks/llm'; const ValidatedCircuitRenderer = ({ circuitData }) => { const [validationResult, setValidationResult] = useState(null); useEffect(() => { if (circuitData) { const validation = validateCircuitDesign(circuitData); setValidationResult(validation); } }, [circuitData]); if (validationResult && !validationResult.isValid) { return ( <div className="p-4 bg-yellow-900/20 border border-yellow-800"> <h3 className="text-yellow-300 font-medium mb-2">Circuit Validation Issues</h3> <ul className="text-yellow-400 text-sm space-y-1"> {validationResult.errors.map((error, index) => ( <li key={index}>• {error}</li> ))} </ul> </div> ); } return ( <CircuitCanvas components={circuitData.components} wires={circuitData.wires} width="100%" height="100%" showGrid={true} /> ); }; ``` ### Styling Tips for Dark Themes Circuit-Bricks works great with dark themes. The default wire color is white, which provides good contrast: ```css /* Custom styling for dark theme integration */ .circuit-container { background-color: #0c0c0c; /* Dark background */ border: 1px solid #374151; /* Gray border */ } /* Grid styling for dark themes */ .circuit-canvas svg { background-color: transparent; } ``` ## Documentation For comprehensive documentation, please check these files: - [Technical Design](./TECHNICAL-DESIGN.md): Architecture and implementation details - [Component Schemas](./COMPONENT-SCHEMAS.md): Component schema reference and examples - [ZOD Schemas](./ZOD-SCHEMAS.md): ZOD schema validation reference and examples - [Documentation](./DOCUMENTATION.md): Complete API reference and usage guide - [Headless Components](./Docs/HEADLESS-COMPONENTS.md): Guide to using unstyled components ## Project Structure ``` src/ ├─ index.ts # Main exports ├─ schemas/ # ZOD schema definitions (single source of truth) └─ componentSchema.ts # ZOD schemas and derived TypeScript types ├─ core/ # Core rendering components ├─ BaseComponent.tsx # Base SVG rendering ├─ Brick.tsx # Schema to component mapper ├─ Port.tsx # Port rendering ├─ WirePath.tsx # Wire path rendering └─ CircuitCanvas.tsx # Main canvas component ├─ registry/ # Component schema registry ├─ index.ts # Registry API └─ components/ # Component schema definitions ├─ resistor.json # Example component schema └─ ... ├─ hooks/ # React hooks ├─ useCircuit.ts # Circuit state management └─ usePortPosition.ts # Port position tracking ├─ ui/ # Optional UI components ├─ PropertyPanel.tsx # Component property editor ├─ ComponentPalette.tsx # Component selection palette ├─ CircuitToolbar.tsx # Actions toolbar └─ headless/ # Headless (unstyled) components ├─ HeadlessPropertyPanel.tsx ├─ HeadlessComponentPalette.tsx └─ HeadlessCircuitToolbar.tsx └─ utils/ # Utility functions ├─ getPortPosition.ts # DOM position helpers ├─ circuitValidation.ts # Circuit validation utilities └─ zodValidation.ts # ZOD schema validation utilities ``` ## Roadmap - [x] Core circuit rendering components - [x] Component palette and property editor UI - [x] Wire drawing and connection management - [x] Circuit validation and error checking - [x] Example circuits and documentation - [x] ZOD schema validation for components and circuits - [ ] Circuit simulation capabilities - [ ] Export/import functionality (JSON, SVG) - [ ] Additional component libraries (digital logic, microcontrollers) - [ ] Integration with popular EDA tools - [ ] Complete demo application - [ ] CodeSandbox examples - [ ] Advanced wire routing algorithms - [ ] Circuit simulation capabilities - [ ] Virtualization for large circuits - [ ] Grouping and subcircuit creation ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. ## License MIT License Copyright (c) 2025 Harshith Paupuleti Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Performance Optimization Circuit-Bricks is designed with performance in mind, particularly for rendering large circuits with many components and wires. ### Bundle Size The core library is lightweight: - Minified: ~64KB - Gzipped: ~22KB ### Rendering Optimization For optimal performance when rendering complex circuits: 1. **Component Memoization**: All components use React.memo to prevent unnecessary re-renders 2. **Virtualization**: For large circuits, consider using a virtualization library to render only visible components 3. **Lazy Loading**: Examples and UI components can be imported using dynamic imports 4. **SVG Optimization**: All SVG paths are optimized for performance and size Example of optimized rendering for large circuits: ```tsx import React, { useState, useEffect } from 'react'; import { CircuitCanvas } from 'circuit-bricks'; const OptimizedCircuitView = ({ components, wires }) => { // Only re-render visible components based on viewport const [visibleArea, setVisibleArea] = useState({ x: 0, y: 0, width: 1000, height: 800 }); // Filter to show only components in the viewport const visibleComponents = components.filter(component => isInViewport(component.position, visibleArea) ); return ( <CircuitCanvas components={visibleComponents} wires={wires} width="100%" height="800px" /> ); }; // Helper function to check if a component is in the viewport function isInViewport(position, viewport) { return ( position.x >= viewport.x - 50 && position.x <= viewport.x + viewport.width + 50 && position.y >= viewport.y - 50 && position.y <= viewport.y + viewport.height + 50 ); } ``` ## Testing The Circuit-Bricks library has a comprehensive testing suite to verify component rendering and circuit functionality: ```bash # Run all tests npm test # Run tests with coverage report npm run test:coverage ``` We've added several documentation files to help with testing: - [TESTING-CHECKLIST.md](./TESTING-CHECKLIST.md): A checklist for manual and automated testing - [TESTING-SETUP.md](./TESTING-SETUP.md): Documentation of the testing environment setup The test suite includes: - Component rendering tests - Hook functionality tests - Registry validation tests - Complex circuit tests - Circuit validation tests - ZOD schema validation tests For more details, see the [TESTING-SETUP.md](./TESTING-SETUP.md) document. --- This library is under active development. More features and components will be added soon!