# VIEW-002: Component X-Ray **View Type:** 📋 Sidebar Panel (opens alongside canvas) ## Overview A summary card view that shows everything important about a component at a glance: what it does, what goes in and out, what it contains, where it's used, and what external calls it makes. Think of it as the "component profile page." **Estimate:** 2-3 days **Priority:** HIGH **Complexity:** Low **Dependencies:** VIEW-000 (Foundation) --- ## The Problem To understand a component today, you have to: 1. Open it in the canvas 2. Scroll around to see all nodes 3. Mentally categorize what's there 4. Check the Component Inputs/Outputs nodes to understand the interface 5. Hunt for REST/Function calls scattered around 6. Go back to the Components Panel to see if it's used elsewhere There's no quick "tell me about this component" view. --- ## The Solution A single-screen summary that answers: - **What does this component do?** (Node breakdown by category) - **What's the interface?** (Inputs and outputs) - **What's inside?** (Subcomponents used) - **Where is it used?** (Parent components) - **What external things does it touch?** (REST, Functions, Events) --- ## User Stories 1. **As a developer reviewing code**, I want to quickly understand what a component does without diving into the canvas. 2. **As a developer debugging**, I want to see all external dependencies (API calls, events) in one place. 3. **As a developer refactoring**, I want to know everywhere this component is used before I change it. 4. **As a new team member**, I want to understand component interfaces (inputs/outputs) without reading the implementation. --- ## UI Design ### X-Ray Card View ``` ┌─────────────────────────────────────────────────────────────────┐ │ Component X-Ray [Open →] │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ 🧩 AuthFlow │ │ │ │ /Components/Auth/AuthFlow │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─ USED IN (3 places) ────────────────────────────────────────┐ │ │ │ 📄 Login Page [→ Open] │ │ │ │ 📄 Settings Page [→ Open] │ │ │ │ 📄 App Shell [→ Open] │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─ INTERFACE ─────────────────────────────────────────────────┐ │ │ │ INPUTS │ OUTPUTS │ │ │ │ ──────── │ ───────── │ │ │ │ → onLoginRequest (signal) │ currentUser (object) → │ │ │ │ → redirectUrl (string) │ authError (string) → │ │ │ │ → initialMode (string) │ isAuthenticated (boolean) → │ │ │ │ │ onSuccess (signal) → │ │ │ │ │ onFailure (signal) → │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─ CONTAINS ──────────────────────────────────────────────────┐ │ │ │ SUBCOMPONENTS │ │ │ │ └─ LoginForm (component) [→ X-Ray] │ │ │ │ └─ SignupForm (component) [→ X-Ray] │ │ │ │ └─ ForgotPassword (component) [→ X-Ray] │ │ │ │ │ │ │ │ NODE BREAKDOWN │ │ │ │ ├─ 📦 Visual 12 nodes (Groups, Text, Images) │ │ │ │ ├─ 💾 Data 5 nodes (Variables, Objects) │ │ │ │ ├─ ⚡ Logic 8 nodes (Conditions, Expressions) │ │ │ │ ├─ 📡 Events 3 nodes (Send/Receive Event) │ │ │ │ └─ 🔧 Other 2 nodes │ │ │ │ ───── │ │ │ │ 30 total │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─ EXTERNAL DEPENDENCIES ─────────────────────────────────────┐ │ │ │ 🌐 REST Calls │ │ │ │ POST /api/auth/login [→ Find] │ │ │ │ POST /api/auth/signup [→ Find] │ │ │ │ POST /api/auth/reset-password [→ Find] │ │ │ │ │ │ │ │ 📨 Events Sent │ │ │ │ "auth:success" [→ Find receivers] │ │ │ │ "auth:failure" [→ Find receivers] │ │ │ │ │ │ │ │ 📩 Events Received │ │ │ │ "app:logout" [→ Find senders] │ │ │ │ │ │ │ │ 🔧 Functions │ │ │ │ validateEmail [→ Find] │ │ │ │ hashPassword [→ Find] │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─ INTERNAL STATE ────────────────────────────────────────────┐ │ │ │ Variables: authMode, errorMessage, isLoading │ │ │ │ Objects: pendingUser, formData │ │ │ │ States: formState (login|signup|reset), loadingState │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` ### Collapsed View (for quick scanning) ``` ┌─────────────────────────────────────────────────────────────────┐ │ 🧩 AuthFlow Used in: 3 | Nodes: 30 | APIs: 3 │ │ ↓ 3 inputs ↑ 5 outputs Contains: LoginForm +2 │ └─────────────────────────────────────────────────────────────────┘ ``` ### Interactions - **[Open →]** - Jump to this component in the canvas - **[→ X-Ray]** - Show X-Ray for that subcomponent - **[→ Find]** - Jump to that node in the canvas - **[→ Find receivers/senders]** - Show all nodes that receive/send that event - **Click "USED IN" item** - Jump to the parent component - **Expand/Collapse sections** - Toggle visibility of sections --- ## Technical Design ### Data Model ```typescript interface ComponentXRay { // Identity name: string; fullName: string; path: string; // Folder path // Usage usedIn: { component: ComponentModel; instanceCount: number; }[]; // Interface inputs: { name: string; type: string; isSignal: boolean; }[]; outputs: { name: string; type: string; isSignal: boolean; }[]; // Contents subcomponents: { name: string; component: ComponentModel; }[]; nodeBreakdown: { category: NodeCategory; count: number; nodeTypes: { type: string; count: number }[]; }[]; totalNodes: number; // External dependencies restCalls: { method: string; endpoint: string; nodeId: string; }[]; eventsSent: { eventName: string; nodeId: string; }[]; eventsReceived: { eventName: string; nodeId: string; }[]; functionCalls: { functionName: string; nodeId: string; }[]; // Internal state variables: { name: string; nodeId: string }[]; objects: { name: string; nodeId: string }[]; statesNodes: { name: string; nodeId: string; states: string[]; }[]; } ``` ### Building X-Ray Data ```typescript function buildComponentXRay( project: ProjectModel, component: ComponentModel ): ComponentXRay { const xray: ComponentXRay = { name: component.name, fullName: component.fullName, path: getComponentPath(component), usedIn: findComponentUsages(project, component.fullName), inputs: getComponentInputs(component), outputs: getComponentOutputs(component), subcomponents: [], nodeBreakdown: [], totalNodes: 0, restCalls: [], eventsSent: [], eventsReceived: [], functionCalls: [], variables: [], objects: [], statesNodes: [] }; // Analyze all nodes in the component component.graph.forEachNode((node) => { xray.totalNodes++; // Check for subcomponents if (isComponentInstance(node)) { xray.subcomponents.push({ name: node.type.name, component: findComponent(project, node.type.name) }); } // Check for REST calls if (node.type.name === 'REST' || node.type.name.includes('REST')) { xray.restCalls.push({ method: node.parameters.method || 'GET', endpoint: node.parameters.endpoint || node.parameters.url, nodeId: node.id }); } // Check for events if (node.type.name === 'Send Event') { xray.eventsSent.push({ eventName: node.parameters.eventName || node.parameters.channel, nodeId: node.id }); } if (node.type.name === 'Receive Event') { xray.eventsReceived.push({ eventName: node.parameters.eventName || node.parameters.channel, nodeId: node.id }); } // Check for functions if (node.type.name === 'Function' || node.type.name === 'Javascript') { xray.functionCalls.push({ functionName: node.label || node.parameters.name || 'Anonymous', nodeId: node.id }); } // Check for state nodes if (node.type.name === 'Variable') { xray.variables.push({ name: node.label || 'Unnamed', nodeId: node.id }); } if (node.type.name === 'Object') { xray.objects.push({ name: node.label || 'Unnamed', nodeId: node.id }); } if (node.type.name === 'States') { xray.statesNodes.push({ name: node.label || 'Unnamed', nodeId: node.id, states: extractStatesFromNode(node) }); } }); // Build category breakdown xray.nodeBreakdown = buildCategoryBreakdown(component); return xray; } ``` --- ## Implementation Phases ### Phase 1: Data Collection (0.5-1 day) 1. Implement `buildComponentXRay()` function 2. Extract inputs/outputs from Component Inputs/Outputs nodes 3. Detect subcomponent usages 4. Find REST, Event, Function nodes 5. Find state-related nodes (Variables, Objects, States) **Verification:** - [ ] All sections populated correctly for test component - [ ] Subcomponent detection works - [ ] External dependencies found ### Phase 2: Basic UI (1 day) 1. Create `ComponentXRayView` React component 2. Implement collapsible sections 3. Style the card layout 4. Add icons for categories **Verification:** - [ ] All sections render correctly - [ ] Sections expand/collapse - [ ] Looks clean and readable ### Phase 3: Interactivity (0.5-1 day) 1. Implement "Open in Canvas" navigation 2. Implement "Find Node" navigation 3. Implement "Show X-Ray" for subcomponents 4. Add "Find receivers/senders" for events 5. Wire up to Analysis Panel context **Verification:** - [ ] All navigation links work - [ ] Can drill into subcomponents - [ ] Event tracking works ### Phase 4: Polish (0.5 day) 1. Add collapsed summary view 2. Improve typography and spacing 3. Add empty state handling 4. Performance optimization **Verification:** - [ ] Collapsed view useful - [ ] Empty sections handled gracefully - [ ] Renders quickly --- ## Files to Create ``` packages/noodl-editor/src/editor/src/views/AnalysisPanel/ └── ComponentXRayView/ ├── index.ts ├── ComponentXRayView.tsx ├── ComponentXRayView.module.scss ├── XRaySection.tsx ├── InterfaceSection.tsx ├── ContentsSection.tsx ├── DependenciesSection.tsx ├── StateSection.tsx └── useComponentXRay.ts ``` --- ## Success Criteria - [ ] Shows accurate usage count - [ ] Shows correct inputs/outputs with types - [ ] Lists all subcomponents - [ ] Finds all REST calls with endpoints - [ ] Finds all Send/Receive Events - [ ] Finds all Function nodes - [ ] Node breakdown by category is accurate - [ ] All navigation links work - [ ] Renders in < 500ms --- ## Future Enhancements - **Diff view** - Compare two components side by side - **History** - See how component changed over time (if git integrated) - **Documentation** - Allow adding/viewing component descriptions - **Complexity score** - Calculate a complexity metric - **Warnings** - Flag potential issues (unused inputs, orphan nodes) --- ## Risks & Mitigations | Risk | Mitigation | |------|------------| | Node type detection misses edge cases | Start with common types, expand based on testing | | Component inputs/outputs detection fails | Test with various component patterns | | Too much information overwhelming | Use collapsible sections, start collapsed | --- ## Dependencies - VIEW-000 Foundation (for traversal and categorization utilities) ## Blocks - None (independent view)