123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- 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,
- }
- }
|