| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 | import { useCallback } from 'react'import ELK from 'elkjs/lib/elk.bundled.js'import {  useReactFlow,  useStoreApi,} from 'reactflow'import { cloneDeep } from 'lodash-es'import type {  Edge,  Node,} from '../types'import { useWorkflowStore } from '../store'import { AUTO_LAYOUT_OFFSET } from '../constants'import { useNodesSyncDraft } from './use-nodes-sync-draft'const layoutOptions = {  'elk.algorithm': 'layered',  'elk.direction': 'RIGHT',  'elk.layered.spacing.nodeNodeBetweenLayers': '60',  'elk.spacing.nodeNode': '40',  'elk.layered.nodePlacement.strategy': 'SIMPLE',}const elk = new ELK()export const getLayoutedNodes = async (nodes: Node[], edges: Edge[]) => {  const graph = {    id: 'root',    layoutOptions,    children: nodes.map((n) => {      return {        ...n,        width: n.width ?? 150,        height: n.height ?? 50,        targetPosition: 'left',        sourcePosition: 'right',      }    }),    edges: cloneDeep(edges),  }  const layoutedGraph = await elk.layout(graph as any)  const layoutedNodes = nodes.map((node) => {    const layoutedNode = layoutedGraph.children?.find(      lgNode => lgNode.id === node.id,    )    return {      ...node,      position: {        x: (layoutedNode?.x ?? 0) + AUTO_LAYOUT_OFFSET.x,        y: (layoutedNode?.y ?? 0) + AUTO_LAYOUT_OFFSET.y,      },    }  })  return {    layoutedNodes,  }}export const useNodesLayout = () => {  const store = useStoreApi()  const reactflow = useReactFlow()  const workflowStore = useWorkflowStore()  const { handleSyncWorkflowDraft } = useNodesSyncDraft()  const handleNodesLayout = useCallback(async () => {    workflowStore.setState({ nodeAnimation: true })    const {      getNodes,      edges,      setNodes,    } = store.getState()    const { setViewport } = reactflow    const nodes = getNodes()    const {      layoutedNodes,    } = await getLayoutedNodes(nodes, edges)    setNodes(layoutedNodes)    const zoom = 0.7    setViewport({      x: 0,      y: 0,      zoom,    })    setTimeout(() => {      handleSyncWorkflowDraft()    })  }, [store, reactflow, handleSyncWorkflowDraft, workflowStore])  return {    handleNodesLayout,  }}
 |