import {FC, HTMLProps, PropsWithChildren, useEffect, useRef, useState} from "react"; import styles from './ProducingGraph.module.css' import {EntityIcon} from "../../home/EntityIcon/EntityIcon"; import {createPath, drawLine} from "../../../src/svg"; import {AdditionalNode, GraphNode, GraphNodeWithIds, isAdditionalNode} from "../../../src/graph-untangle/types"; import {graphUntangled} from "../../../src/graph-untangle"; import {Dict} from "../../../src/types"; interface Props { nodes: GraphNode[] inputs: string[] outputs?: string[] childType: FC & {node: GraphNode}> } export const ProducingGraph = ,>({nodes, inputs, outputs, childType: ChildType}: PropsWithChildren>) => { const planeRef = useRef(null) const [[rows, nodeMap], setGraph] = useState<[string[][], Dict>]>([[], {}]) useEffect(() => { setGraph(graphUntangled(nodes, inputs, outputs ?? [])) setTimeout(() => setGraph(graphUntangled(nodes, inputs, outputs ?? [], 5000)), 0) }, [inputs, nodes, outputs]) /*const rowsWithInOut: (GraphNode|AdditionalNode)[][] = useMemo(() => { const addedInputs = new Set() const res: (GraphNode|AdditionalNode)[][] = deepcopy([[], ...rows, []]) for (let i = 0; i < rows.length; i++) { const rowOutputs = uniquify(rows[i].flatMap(row => row.outputs)) for (let rowOutput of rowOutputs) { outputs?.includes(rowOutput) && res[i+2].push({___type: 'o', value: rowOutput}) } const rowInputs = uniquify(rows[i].flatMap(row => row.inputs)) for (let rowInput of rowInputs) { if (addedInputs.has(rowInput)) !res[i].some(node => isAdditionalNode(node) && node.value === rowInput) && res[i].push({___type: 'h', value: rowInput}) else if (inputs.includes(rowInput)) res[i].push({___type: 'i', value: rowInput}) addedInputs.add(rowInput) } } return res }, [rows, inputs, outputs])*/ useEffect(() => { if (!planeRef.current) return const plane = planeRef.current function createSvgElement() { const elem = document.createElementNS("http://www.w3.org/2000/svg", "svg") elem.id = 'arrows' elem.setAttribute('style', 'position: absolute; inset: 0 0 0 0; pointer-events: none; z-index: -10;') elem.setAttributeNS(null, 'stroke', 'black') elem.setAttributeNS(null, 'fill', 'none') plane.appendChild(elem) return elem } const svg = document.getElementById('arrows') ?? createSvgElement() const width = Math.round(plane.getBoundingClientRect().width) const height = Math.round(plane.getBoundingClientRect().height) svg.setAttribute('width', `${width}`) svg.setAttribute('height', `${height}`) svg.setAttributeNS(null, 'viewBox', `0 0 ${width} ${height}`) svg.replaceChildren() plane.querySelectorAll('[data-outputs]').forEach(startNode => { if (!(startNode instanceof HTMLElement)) return (startNode.dataset.outputs?.split(' ') ?? []).forEach(output => { const endNode = plane.querySelector(`[data-name="${output}"]`) if (!(endNode instanceof HTMLElement)) return const path = document.createElementNS('http://www.w3.org/2000/svg',"path") path.setAttributeNS(null, 'd', createPath(plane.getBoundingClientRect(), startNode.getBoundingClientRect(), endNode.getBoundingClientRect())) svg.appendChild(path) }) }) plane.querySelectorAll('[data-hidden][data-outputs]').forEach(elem => { if (!(elem instanceof HTMLElement)) return const path = document.createElementNS('http://www.w3.org/2000/svg',"path") path.setAttributeNS(null, 'd', drawLine(plane.getBoundingClientRect(), elem.getBoundingClientRect())) svg.appendChild(path) }) }) return {rows.map((row, colIdx) => ( { row.map((uid) => { const node = nodeMap[uid] return ( !isAdditionalNode(node) ? : node.___type === 'h' ? : node.___type === 'i' ? : ); }) } ))} }