UNPKG

ruch

Version:

Revolutionary React TypeScript CLI with hexagonal architecture & AI-powered development assistance. Create maintainable, scalable applications with domain-driven design and integrated AI tooling.

154 lines 6.87 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.DomainGraph = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const reactflow_1 = __importStar(require("reactflow")); require("reactflow/dist/style.css"); const DomainNode_1 = require("./DomainNode"); const DependencyEdge_1 = require("./DependencyEdge"); const nodeTypes = { domain: DomainNode_1.DomainNode, }; const edgeTypes = { dependency: DependencyEdge_1.DependencyEdge, }; const DomainGraph = ({ graphData, settings, onNodeClick, onEdgeClick, }) => { const [selectedNode, setSelectedNode] = (0, react_1.useState)(null); const [selectedEdge, setSelectedEdge] = (0, react_1.useState)(null); // Convert graph data to React Flow format const { nodes: initialNodes, edges: initialEdges } = (0, react_1.useMemo)(() => { const nodes = graphData.nodes.map((node, index) => ({ id: node.id, type: 'domain', position: { x: (index % 4) * 250 + 100, y: Math.floor(index / 4) * 200 + 100, }, data: { label: node.label, domainType: node.type || 'feature', isSelected: selectedNode === node.id, settings, }, })); const edges = graphData.edges.map((edge, index) => ({ id: `${edge.source}-${edge.target}-${index}`, source: edge.source, target: edge.target, type: 'dependency', animated: edge.type === 'direct-import', markerEnd: { type: reactflow_1.MarkerType.ArrowClosed, width: 20, height: 20, color: '#64748b', }, data: { dependencyType: edge.type, metadata: edge.metadata, isSelected: selectedEdge === `${edge.source}-${edge.target}-${index}`, settings, }, })); return { nodes, edges }; }, [graphData, selectedNode, selectedEdge, settings]); const [nodes, setNodes, onNodesChange] = (0, reactflow_1.useNodesState)(initialNodes); const [edges, setEdges, onEdgesChange] = (0, reactflow_1.useEdgesState)(initialEdges); const onConnect = (0, react_1.useCallback)((params) => setEdges((eds) => (0, reactflow_1.addEdge)(params, eds)), [setEdges]); const handleNodeClick = (0, react_1.useCallback)((event, node) => { setSelectedNode(node.id); onNodeClick?.(node.id); }, [onNodeClick]); const handleEdgeClick = (0, react_1.useCallback)((event, edge) => { setSelectedEdge(edge.id); onEdgeClick?.(edge.id); }, [onEdgeClick]); // Detect circular dependencies for highlighting const circularDependencies = (0, react_1.useMemo)(() => { const visited = new Set(); const recursionStack = new Set(); const cycles = []; const dfs = (nodeId) => { visited.add(nodeId); recursionStack.add(nodeId); const outgoingEdges = edges.filter((edge) => edge.source === nodeId); for (const edge of outgoingEdges) { if (!visited.has(edge.target)) { if (dfs(edge.target)) { cycles.push(nodeId); return true; } } else if (recursionStack.has(edge.target)) { cycles.push(nodeId); return true; } } recursionStack.delete(nodeId); return false; }; nodes.forEach((node) => { if (!visited.has(node.id)) { dfs(node.id); } }); return cycles; }, [nodes, edges]); // Update nodes with cycle information const nodesWithCycles = (0, react_1.useMemo)(() => { return nodes.map((node) => ({ ...node, data: { ...node.data, isInCycle: settings.highlightCycles && circularDependencies.includes(node.id), }, })); }, [nodes, circularDependencies, settings.highlightCycles]); return ((0, jsx_runtime_1.jsx)("div", { style: { width: '100%', height: '100%' }, children: (0, jsx_runtime_1.jsxs)(reactflow_1.default, { nodes: nodesWithCycles, edges: edges, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, onConnect: onConnect, onNodeClick: handleNodeClick, onEdgeClick: handleEdgeClick, nodeTypes: nodeTypes, edgeTypes: edgeTypes, fitView: true, attributionPosition: "bottom-left", children: [(0, jsx_runtime_1.jsx)(reactflow_1.Controls, {}), (0, jsx_runtime_1.jsx)(reactflow_1.MiniMap, { nodeColor: (node) => { const domainType = node.data?.domainType || 'feature'; switch (domainType) { case 'core': return '#ef4444'; case 'shared': return '#3b82f6'; default: return '#10b981'; } }, nodeStrokeWidth: 3, zoomable: true, pannable: true }), (0, jsx_runtime_1.jsx)(reactflow_1.Background, { variant: reactflow_1.BackgroundVariant.Dots, gap: 12, size: 1 })] }) })); }; exports.DomainGraph = DomainGraph; //# sourceMappingURL=DomainGraph.js.map