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 ?? [], 3000)), 0) }, [inputs, nodes, 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() let paths: string[] = [] 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 paths.push(createPath(plane.getBoundingClientRect(), startNode.getBoundingClientRect(), endNode.getBoundingClientRect())) }) }) plane.querySelectorAll('[data-hidden="true"][data-outputs]').forEach(elem => { if (!(elem instanceof HTMLElement)) return paths.push(drawLine(plane.getBoundingClientRect(), elem.getBoundingClientRect())) }) const path = document.createElementNS('http://www.w3.org/2000/svg',"path") path.setAttributeNS(null, 'd', paths.join(' ')) svg.appendChild(path) }) return {rows.map((row, colIdx) => ( { row.map((uid) => { const node = nodeMap[uid] return ( !isAdditionalNode(node) ? 0}> : node.___type === 'h' ? : node.___type === 'i' ? : ); }) } ))} }