import React, { useEffect, useMemo, useRef } from 'react'; import ReactFlow, { Controls, Background } from 'reactflow'; import 'reactflow/dist/style.css'; import { debounce } from 'lodash'; import { useFlowChart } from './FlowChartComponents/useFlowChart'; import { useNodeHandlers } from './FlowChartComponents/useNodeHandlers'; import { useDataParser } from './FlowChartComponents/DataParser'; import NodeWrapper from './FlowChartComponents/NodeWrapper'; const nodeTypes = { customNode: NodeWrapper }; const FlowChart = ({ data }) => { const { nodes, edges, nodePositions, setNodes, setEdges, onNodesChange, onEdgesChange, setNodePositions, collapsedNodes, toggleNodeCollapse } = useFlowChart(data); const { parseData } = useDataParser(nodePositions, collapsedNodes); const initialized = useRef(false); const debouncedSetNodePositions = useMemo( () => debounce(setNodePositions, 100), [setNodePositions] ); const { onNodeDrag, onNodeDragStop } = useNodeHandlers(debouncedSetNodePositions); useEffect(() => { const { nodes: initialNodes, edges: initialEdges } = parseData(data); setNodes(initialNodes); setEdges(initialEdges); // Автоматически сворачиваем узлы, которые являются родителями последнего уровня if (!initialized.current && data) { const findAndCollapseLastLevelParents = (items) => { items.forEach(item => { if (item.items && item.items.length > 0) { const hasGrandchildren = item.items.some(child => child.items && child.items.length > 0 ); if (!hasGrandchildren) { toggleNodeCollapse(item.id); } else { findAndCollapseLastLevelParents(item.items); } } }); }; findAndCollapseLastLevelParents(data.items || []); initialized.current = true; } }, [data, parseData, setNodes, setEdges, toggleNodeCollapse]); const onNodeClick = (event, node) => { if (node.data.hasChildren) { toggleNodeCollapse(node.id); } }; useEffect(() => { return () => { debouncedSetNodePositions.cancel(); }; }, [debouncedSetNodePositions]); return (
); }; export default React.memo(FlowChart);