UNPKG

@hitachivantara/uikit-react-lab

Version:

Contributed React components for the NEXT UI Kit.

205 lines (204 loc) 6.64 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const jsxRuntime = require("react/jsx-runtime"); const react = require("react"); const core = require("@dnd-kit/core"); const react$1 = require("@emotion/react"); const reactflow = require("reactflow"); const uid = require("uid"); const uikitReactCore = require("@hitachivantara/uikit-react-core"); const base = require("./base.cjs"); const Flow_styles = require("./Flow.styles.cjs"); const NodeMetaContext = require("./FlowContext/NodeMetaContext.cjs"); const useFlowInstance = require("./hooks/useFlowInstance.cjs"); const getNode = (nodes, nodeId) => { return nodes.find((n) => n.id === nodeId); }; const validateEdge = (nodes, edges, connection, nodeMetaRegistry) => { const { source: sourceId, sourceHandle, target: targetId, targetHandle } = connection; if (!sourceHandle || !targetHandle || !sourceId || !targetId) return false; const sourceNode = getNode(nodes, sourceId); const targetNode = getNode(nodes, targetId); if (!sourceNode || !targetNode) return false; const sourceType = sourceNode.type; const targetType = targetNode.type; if (!sourceType || !targetType) return false; const inputs = nodeMetaRegistry[targetId]?.inputs || []; const outputs = nodeMetaRegistry[sourceId]?.outputs || []; const source = outputs.flatMap((out) => out.outputs || out).find((out) => out.id === sourceHandle); const target = inputs.flatMap((inp) => inp.inputs || inp).find((inp) => inp.id === targetHandle); const sourceProvides = source?.provides || ""; const targetAccepts = target?.accepts || []; const sourceMaxConnections = source?.maxConnections; const targetMaxConnections = target?.maxConnections; let isValid = targetAccepts.length === 0 || targetAccepts.includes(sourceProvides); if (isValid && targetMaxConnections != null) { const targetConnections = edges.filter( (edg) => edg.target === targetId && edg.targetHandle === targetHandle ).length; isValid = targetConnections < targetMaxConnections; } if (isValid && sourceMaxConnections != null) { const sourceConnections = edges.filter( (edg) => edg.source === sourceId && edg.sourceHandle === sourceHandle ).length; isValid = sourceConnections < sourceMaxConnections; } return isValid; }; const HvDroppableFlow = ({ id, className, children, onFlowChange, onDndDrop, classes: classesProp, nodes: initialNodes = [], edges: initialEdges = [], onConnect: onConnectProp, onNodesChange: onNodesChangeProp, onEdgesChange: onEdgesChangeProp, defaultEdgeOptions: defaultEdgeOptionsProp, nodeTypes, ...others }) => { const { classes, cx } = Flow_styles.useClasses(classesProp); const elementId = uikitReactCore.useUniqueId(id); const reactFlowInstance = useFlowInstance.useFlowInstance(); const [nodes, setNodes] = react.useState(initialNodes); const [edges, setEdges] = react.useState(initialEdges); const nodesRef = react.useRef(initialNodes); const edgesRef = react.useRef(initialEdges); const updateNodes = (nds) => { setNodes(nds); nodesRef.current = nds; }; const updateEdges = (eds) => { setEdges(eds); edgesRef.current = eds; }; const { setNodeRef } = core.useDroppable({ id: elementId }); const handleDragEnd = react.useCallback( (event) => { if (event.over?.id !== elementId) return; const hvFlow = event.active.data.current?.hvFlow; const type = hvFlow?.type; if (!type || !nodeTypes?.[type]) { return; } const position = reactFlowInstance.screenToFlowPosition({ x: hvFlow?.x || 0, y: hvFlow?.y || 0 }); const data = { nodeLabel: hvFlow?.label, ...hvFlow?.data }; const newNode = { id: uid.uid(), position, data, type }; if (onDndDrop) { onDndDrop(event, newNode); return; } updateNodes(nodes.concat(newNode)); }, [elementId, nodeTypes, nodes, onDndDrop, reactFlowInstance] ); core.useDndMonitor({ onDragEnd: handleDragEnd }); const handleFlowChange = react.useCallback( (nds, eds) => { const isDragging = nds.find((node) => node.dragging); if (!isDragging) { onFlowChange?.(nds, eds); } }, [onFlowChange] ); const handleConnect = react.useCallback( (connection) => { const eds = reactflow.addEdge(connection, edgesRef.current); updateEdges(eds); handleFlowChange(nodesRef.current, eds); onConnectProp?.(connection); }, [handleFlowChange, onConnectProp] ); const handleNodesChange = react.useCallback( (changes) => { const nds = reactflow.applyNodeChanges(changes, nodesRef.current); updateNodes(nds); handleFlowChange(nds, edgesRef.current); onNodesChangeProp?.(changes); }, [handleFlowChange, onNodesChangeProp] ); const handleEdgesChange = react.useCallback( (changes) => { const eds = reactflow.applyEdgeChanges(changes, edgesRef.current); updateEdges(eds); handleFlowChange(nodesRef.current, eds); onEdgesChangeProp?.(changes); }, [handleFlowChange, onEdgesChangeProp] ); const { registry } = NodeMetaContext.useNodeMetaRegistry(); const isValidConnection = (connection) => validateEdge(nodes, edges, connection, registry); const defaultEdgeOptions = { markerEnd: { type: reactflow.MarkerType.ArrowClosed, height: 20, width: 20 }, type: "smoothstep", pathOptions: { borderRadius: 40 }, ...defaultEdgeOptionsProp }; return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [ /* @__PURE__ */ jsxRuntime.jsx(react$1.Global, { styles: base.flowStyles }), /* @__PURE__ */ jsxRuntime.jsx( "div", { id: elementId, ref: setNodeRef, className: cx(classes.root, className), children: /* @__PURE__ */ jsxRuntime.jsx( reactflow.ReactFlow, { nodes, edges, nodeTypes, onNodesChange: handleNodesChange, onEdgesChange: handleEdgesChange, onConnect: handleConnect, isValidConnection, defaultEdgeOptions, snapGrid: [1, 1], snapToGrid: true, onError: (code, message) => { }, ...others, children } ) } ) ] }); }; exports.flowClasses = Flow_styles.staticClasses; exports.HvDroppableFlow = HvDroppableFlow; exports.getNode = getNode;