@flowgram.ai/free-layout-core 0.4.13 → 0.4.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/workflow-commands.ts","../src/hooks/index.ts","../src/hooks/use-node-render.tsx","../src/service/workflow-select-service.ts","../src/utils/index.ts","../src/utils/build-group-json.ts","../src/utils/get-line-center.ts","../src/utils/nanoid.ts","../src/utils/compose.ts","../src/utils/fit-view.ts","../src/utils/get-anti-overlap-position.ts","../src/utils/statics.ts","../src/entities/workflow-node-entity.ts","../src/entities/workflow-line-entity.ts","../src/entity-datas/workflow-node-ports-data.ts","../src/entities/workflow-port-entity.ts","../src/entity-datas/workflow-node-lines-data.ts","../src/entity-datas/workflow-line-render-data.ts","../src/service/workflow-hover-service.ts","../src/service/workflow-drag-service.ts","../src/workflow-lines-manager.ts","../src/workflow-document-option.ts","../src/utils/flow-node-form-data.ts","../src/typings/workflow-json.ts","../src/typings/workflow-line.ts","../src/typings/workflow-operation.ts","../src/typings/index.ts","../src/workflow-document.ts","../src/layout/free-layout.ts","../src/service/workflow-reset-layout-service.ts","../src/utils/layout-to-positions.ts","../src/service/workflow-operation-base-service.ts","../src/hooks/use-playground-readonly-state.ts","../src/hooks/use-current-dom-node.ts","../src/hooks/use-current-entity.ts","../src/hooks/use-workflow-document.ts","../src/constants.ts","../src/workflow-document-container-module.ts","../src/workflow-document-contribution.ts","../src/utils/get-url-params.ts"],"sourcesContent":["/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport * from './workflow-commands';\nexport * from './hooks';\nexport * from './utils';\nexport * from './typings';\nexport * from './entities';\nexport * from './constants';\nexport * from './entity-datas';\nexport * from './service';\nexport * from './workflow-document';\nexport * from './workflow-document-container-module';\nexport * from './workflow-lines-manager';\nexport * from './workflow-document-option';\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport enum WorkflowCommands {\n DELETE_NODES = 'DELETE_NODES',\n COPY_NODES = 'COPY_NODES',\n PASTE_NODES = 'PASTE_NODES',\n ZOOM_IN = 'ZOOM_IN',\n ZOOM_OUT = 'ZOOM_OUT',\n UNDO = 'UNDO',\n REDO = 'REDO',\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport {\n useConfigEntity,\n useService,\n usePlayground,\n useListenEvents,\n usePlaygroundContainer,\n usePlaygroundContext,\n useEntities,\n useEntityFromContext,\n useEntityDataFromContext,\n useRefresh,\n usePlaygroundLatest,\n} from '@flowgram.ai/core';\nexport * from './typings';\nexport * from './use-node-render';\nexport * from './use-current-dom-node';\nexport * from './use-current-entity';\nexport * from './use-workflow-document';\nexport * from './use-playground-readonly-state';\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport type React from 'react';\nimport { useCallback, useEffect, useRef, useState, useContext, useMemo } from 'react';\n\nimport { useObserve } from '@flowgram.ai/reactive';\nimport { getNodeForm } from '@flowgram.ai/node';\nimport { FlowNodeRenderData } from '@flowgram.ai/document';\nimport {\n MouseTouchEvent,\n PlaygroundEntityContext,\n useListenEvents,\n useService,\n} from '@flowgram.ai/core';\n\nimport { WorkflowDragService, WorkflowSelectService } from '../service';\nimport { WorkflowNodePortsData } from '../entity-datas';\nimport { type WorkflowNodeEntity } from '../entities';\nimport { usePlaygroundReadonlyState } from './use-playground-readonly-state';\nimport { type NodeRenderReturnType } from './typings';\n\nfunction checkTargetDraggable(el: any): boolean {\n return (\n el &&\n el.tagName !== 'INPUT' &&\n el.tagName !== 'TEXTAREA' &&\n !el.closest('.flow-canvas-not-draggable')\n );\n}\n/**\n * - 下面的 firefox 为了修复一个 bug\n * - firefox 下 draggable 属性会影响节点 input 内容 focus:https://jsfiddle.net/Aydar/ztsvbyep/3/\n * - 该 bug 在 firefox 浏览器上存在了很久,需要作兼容:https://bugzilla.mozilla.org/show_bug.cgi?id=739071\n */\nconst isFirefox = navigator?.userAgent?.includes?.('Firefox');\n\nexport function useNodeRender(nodeFromProps?: WorkflowNodeEntity): NodeRenderReturnType {\n const node = nodeFromProps || useContext<WorkflowNodeEntity>(PlaygroundEntityContext);\n const renderData = node.getData(FlowNodeRenderData)!;\n const portsData = node.getData(WorkflowNodePortsData)!;\n const readonly = usePlaygroundReadonlyState();\n const dragService = useService<WorkflowDragService>(WorkflowDragService);\n const selectionService = useService<WorkflowSelectService>(WorkflowSelectService);\n const isDragging = useRef(false);\n const [formValueVersion, updateFormValueVersion] = useState<number>(0);\n const formValueDependRef = useRef(false);\n formValueDependRef.current = false;\n const nodeRef = useRef<HTMLDivElement | null>(null);\n const [linkingNodeId, setLinkingNodeId] = useState('');\n\n useEffect(() => {\n const disposable = dragService.onDragLineEventChange(({ type, onDragNodeId }) => {\n if (type === 'onDrag') {\n setLinkingNodeId(onDragNodeId || '');\n } else {\n setLinkingNodeId('');\n }\n });\n\n return () => {\n disposable.dispose();\n };\n }, []);\n\n const startDrag = useCallback(\n (e: React.MouseEvent) => {\n MouseTouchEvent.preventDefault(e);\n if (!selectionService.isSelected(node.id)) {\n selectNode(e);\n }\n if (!MouseTouchEvent.isTouchEvent(e as unknown as React.TouchEvent)) {\n // 输入框不能拖拽\n if (!checkTargetDraggable(e.target) || !checkTargetDraggable(document.activeElement)) {\n return;\n }\n }\n isDragging.current = true;\n // 拖拽选中的节点\n dragService.startDragSelectedNodes(e)?.finally(() =>\n setTimeout(() => {\n isDragging.current = false;\n })\n );\n },\n [dragService, node]\n );\n /**\n * 单选节点\n */\n const selectNode = useCallback(\n (e: React.MouseEvent) => {\n // 触发了拖拽就不要再触发单选\n if (isDragging.current) {\n return;\n }\n // 追加选择\n if (e.shiftKey) {\n selectionService.toggleSelect(node);\n } else {\n selectionService.selectNode(node);\n }\n if (e.target) {\n (e.target as HTMLDivElement).focus();\n }\n },\n [node]\n );\n const deleteNode = useCallback(() => node.dispose(), [node]);\n // 监听端口变化\n useListenEvents(portsData.onDataChange);\n\n const onFocus = useCallback(() => {\n if (isFirefox) {\n nodeRef.current?.setAttribute('draggable', 'false');\n }\n }, []);\n const onBlur = useCallback(() => {\n if (isFirefox) {\n nodeRef.current?.setAttribute('draggable', 'true');\n }\n }, []);\n const getExtInfo = useCallback(() => node.getExtInfo() as any, [node]);\n const updateExtInfo = useCallback(\n (data: any) => {\n node.updateExtInfo(data);\n },\n [node]\n );\n const form = useMemo(() => getNodeForm(node), [node]);\n // Listen FormState change\n const formState = useObserve<any>(form?.state);\n const toggleExpand = useCallback(() => {\n renderData.toggleExpand();\n }, [renderData]);\n const selected = selectionService.isSelected(node.id);\n const activated = selectionService.isActivated(node.id);\n const expanded = renderData.expanded;\n useEffect(() => {\n const toDispose = form?.onFormValuesChange(() => {\n if (formValueDependRef.current) {\n updateFormValueVersion((v) => v + 1);\n }\n });\n return () => toDispose?.dispose();\n }, [form]);\n\n return useMemo(\n () => ({\n id: node.id,\n type: node.flowNodeType,\n get data() {\n if (form) {\n formValueDependRef.current = true;\n return form.values;\n }\n return getExtInfo();\n },\n updateData(values: any) {\n if (form) {\n form.updateFormValues(values);\n } else {\n updateExtInfo(values);\n }\n },\n node,\n selected,\n activated,\n expanded,\n startDrag,\n get ports() {\n return portsData.allPorts;\n },\n deleteNode,\n selectNode,\n readonly,\n linkingNodeId,\n nodeRef,\n onFocus,\n onBlur,\n getExtInfo,\n updateExtInfo,\n toggleExpand,\n get form() {\n if (!form) return undefined;\n return {\n ...form,\n get values() {\n formValueDependRef.current = true;\n return form.values!;\n },\n get state() {\n return formState;\n },\n };\n },\n }),\n [\n node,\n selected,\n activated,\n expanded,\n startDrag,\n deleteNode,\n selectNode,\n readonly,\n linkingNodeId,\n nodeRef,\n onFocus,\n onBlur,\n getExtInfo,\n updateExtInfo,\n toggleExpand,\n formValueVersion,\n ]\n );\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { inject, injectable } from 'inversify';\nimport {\n type Entity,\n Playground,\n SelectionService,\n TransformData,\n type PlaygroundConfigRevealOpts,\n} from '@flowgram.ai/core';\nimport { type Event, Rectangle, SizeSchema } from '@flowgram.ai/utils';\n\nimport { delay } from '../utils';\nimport { WorkflowNodeEntity } from '../entities';\nimport { type WorkfloEntityHoverable } from './workflow-hover-service';\n\n@injectable()\nexport class WorkflowSelectService {\n @inject(SelectionService) protected selectionService: SelectionService;\n\n @inject(Playground) protected playground: Playground;\n\n get onSelectionChanged(): Event<void> {\n return this.selectionService.onSelectionChanged;\n }\n\n get selection(): Entity[] {\n return this.selectionService.selection;\n }\n\n set selection(entities: Entity[]) {\n this.selectionService.selection = entities;\n }\n\n /**\n * 当前激活的节点只能有一个\n */\n get activatedNode(): WorkflowNodeEntity | undefined {\n const { selectedNodes } = this;\n if (selectedNodes.length !== 1) {\n return undefined;\n }\n return selectedNodes[0];\n }\n\n isSelected(id: string): boolean {\n return this.selectionService.selection.some(s => s.id === id);\n }\n\n isActivated(id: string): boolean {\n return this.activatedNode?.id === id;\n }\n\n /**\n * 选中的节点\n */\n get selectedNodes(): WorkflowNodeEntity[] {\n return this.selectionService.selection.filter(\n n => n instanceof WorkflowNodeEntity,\n ) as WorkflowNodeEntity[];\n }\n\n /**\n * 选中\n * @param node\n */\n selectNode(node: WorkflowNodeEntity): void {\n this.selectionService.selection = [node];\n }\n\n toggleSelect(node: WorkflowNodeEntity): void {\n if (this.selectionService.selection.includes(node)) {\n this.selectionService.selection = this.selectionService.selection.filter(n => n !== node);\n } else {\n this.selectionService.selection = this.selectionService.selection.concat(node);\n }\n }\n\n select(node: WorkfloEntityHoverable): void {\n this.selectionService.selection = [node];\n }\n\n clear(): void {\n this.selectionService.selection = [];\n }\n\n /**\n * 选中并滚动到节点\n * @param node\n */\n async selectNodeAndScrollToView(node: WorkflowNodeEntity, fitView?: boolean): Promise<void> {\n this.selectNodeAndFocus(node);\n const DELAY_TIME = 30;\n // 等待节点渲染完成(一般用于刚添加的节点)\n await delay(DELAY_TIME);\n\n const scrollConfig: PlaygroundConfigRevealOpts = {\n entities: [node],\n };\n\n if (fitView) {\n const bounds = Rectangle.enlarge([node.getData<TransformData>(TransformData).bounds]).pad(\n 30,\n 30,\n ); // 留出 30 像素的边界\n\n const viewport = this.playground.config.getViewport(false);\n\n const zoom = SizeSchema.fixSize(bounds, viewport);\n\n scrollConfig.zoom = zoom;\n scrollConfig.scrollToCenter = true;\n scrollConfig.easing = true;\n }\n\n return this.playground.config.scrollToView(scrollConfig);\n }\n\n selectNodeAndFocus(node: WorkflowNodeEntity): void {\n // 新添加的节点需要被选中\n this.select(node);\n // 拖进来需要让画布聚焦, 才能使用快捷键删除\n this.playground.node.focus();\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { bindConfigEntity } from '@flowgram.ai/core';\nexport { delay } from '@flowgram.ai/utils';\n\n/**\n * 让 entity 可以注入到类中\n *\n * @example\n * ```\n * class SomeClass {\n * @inject(PlaygroundConfigEntity) playgroundConfig: PlaygroundConfigEntity\n * }\n * ```\n * @param bind\n * @param entityRegistry\n */\nexport { bindConfigEntity };\n\nexport { buildGroupJSON } from './build-group-json';\nexport { getLineCenter } from './get-line-center';\nexport * from './nanoid';\nexport * from './compose';\nexport * from './fit-view';\nexport * from './get-anti-overlap-position';\nexport * from './statics';\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { FlowNodeBaseType } from '@flowgram.ai/document';\n\nimport { WorkflowJSON, WorkflowNodeJSON } from '../typings';\n\ninterface WorkflowGroupJSON extends WorkflowNodeJSON {\n data: {\n parentID?: string;\n blockIDs?: string[];\n };\n}\n\nexport const buildGroupJSON = (json: WorkflowJSON): WorkflowJSON => {\n const { nodes, edges } = json;\n const groupJSONs = nodes.filter(\n (nodeJSON) => nodeJSON.type === FlowNodeBaseType.GROUP\n ) as WorkflowGroupJSON[];\n\n const nodeJSONMap = new Map<string, WorkflowNodeJSON>(nodes.map((n) => [n.id, n]));\n const groupNodeJSONs = groupJSONs.map((groupJSON): WorkflowNodeJSON => {\n const groupBlocks = (groupJSON.data.blockIDs ?? [])\n .map((blockID) => nodeJSONMap.get(blockID))\n .filter(Boolean) as WorkflowNodeJSON[];\n const groupEdges = edges?.filter((edge) =>\n groupBlocks.some((block) => block.id === edge.sourceNodeID || block.id === edge.targetNodeID)\n );\n const groupNodeJSON: WorkflowNodeJSON = {\n ...groupJSON,\n blocks: groupBlocks,\n edges: groupEdges,\n };\n return groupNodeJSON;\n });\n\n const groupBlockSet = new Set(groupJSONs.map((groupJSON) => groupJSON.data.blockIDs).flat());\n const processedNodes = nodes\n .filter((nodeJSON) => !groupBlockSet.has(nodeJSON.id))\n .concat(groupNodeJSONs);\n return {\n nodes: processedNodes,\n edges,\n };\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { IPoint, Rectangle } from '@flowgram.ai/utils';\n\nimport { LineCenterPoint } from '../typings';\n\nexport function getLineCenter(\n from: IPoint,\n to: IPoint,\n bbox: Rectangle,\n linePadding: number\n): LineCenterPoint {\n return {\n x: bbox.center.x,\n y: bbox.center.y,\n labelX: bbox.center.x - bbox.x + linePadding,\n labelY: bbox.center.y - bbox.y + linePadding,\n };\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { nanoid as nanoidOrigin } from 'nanoid';\n\nexport function nanoid(n?: number): string {\n return nanoidOrigin(n);\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport { compose, composeAsync } from '@flowgram.ai/utils';\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Rectangle } from '@flowgram.ai/utils';\nimport { type PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\n\nimport { type WorkflowDocument } from '../workflow-document';\n\nexport const fitView = (\n doc: WorkflowDocument,\n playgroundConfig: PlaygroundConfigEntity,\n easing = true\n) => {\n const bounds = Rectangle.enlarge(\n doc.getAllNodes().map((node) => node.getData<TransformData>(TransformData).bounds)\n );\n // 留出 30 像素的边界\n return playgroundConfig.fitView(bounds, easing, 30);\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { TransformData } from '@flowgram.ai/core';\nimport { type IPoint } from '@flowgram.ai/utils';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport { WorkflowNodeEntity } from '../entities';\n\n/**\n * 获取没有碰撞的位置\n * 距离很小时,xy 各偏移 30\n * @param position\n */\nexport function getAntiOverlapPosition(\n doc: WorkflowDocument,\n position: IPoint,\n containerNode?: WorkflowNodeEntity,\n): IPoint {\n let { x, y } = position;\n const nodes = containerNode ? containerNode.collapsedChildren : doc.getAllNodes();\n const positions = nodes\n .map(n => {\n const transform = n.getData<TransformData>(TransformData)!;\n return { x: transform.position.x, y: transform.position.y };\n })\n .sort((a, b) => a.y - b.y);\n const minDistance = 3;\n for (const pos of positions) {\n const { x: posX, y: posY } = pos;\n if (y - posY < -minDistance) {\n break;\n }\n const deltaX = Math.abs(x - posX);\n const deltaY = Math.abs(y - posY);\n if (deltaX <= minDistance && deltaY <= minDistance) {\n x += 30;\n y += 30;\n }\n }\n return { x, y };\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Rectangle } from '@flowgram.ai/utils';\n\nimport { type WorkflowNodeEntity } from '../entities/workflow-node-entity';\nexport type WorkflowPortType = 'input' | 'output';\n\nexport const getPortEntityId = (\n node: WorkflowNodeEntity,\n portType: WorkflowPortType,\n portID: string | number = '',\n): string => `port_${portType}_${node.id}_${portID}`;\n\nexport const WORKFLOW_LINE_ENTITY = 'WorkflowLineEntity';\n\nexport function domReactToBounds(react: DOMRect): Rectangle {\n return new Rectangle(react.x, react.y, react.width, react.height);\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { FlowNodeEntity } from '@flowgram.ai/document';\n\nexport type WorkflowNodeEntity = FlowNodeEntity;\nexport const WorkflowNodeEntity = FlowNodeEntity;\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { isEqual } from 'lodash-es';\nimport { domUtils, type IPoint, Rectangle, Emitter } from '@flowgram.ai/utils';\nimport { Entity, type EntityOpts } from '@flowgram.ai/core';\n\nimport { type WorkflowLinesManager } from '../workflow-lines-manager';\nimport { type WorkflowDocument } from '../workflow-document';\nimport { WORKFLOW_LINE_ENTITY } from '../utils/statics';\nimport {\n LineRenderType,\n type LinePosition,\n LinePoint,\n LineCenterPoint,\n} from '../typings/workflow-line';\nimport { type WorkflowEdgeJSON } from '../typings';\nimport { WorkflowNodePortsData } from '../entity-datas/workflow-node-ports-data';\nimport { WorkflowLineRenderData } from '../entity-datas';\nimport { type WorkflowPortEntity } from './workflow-port-entity';\nimport { type WorkflowNodeEntity } from './workflow-node-entity';\n\nexport const LINE_HOVER_DISTANCE = 8; // 线条 hover 的最小检测距离\nexport const POINT_RADIUS = 10;\n\nexport interface WorkflowLinePortInfo {\n from: string; // 前置节点 id\n to?: string; // 后置节点 id\n fromPort?: string | number; // 连线的 port 位置\n toPort?: string | number; // 连线的 port 位置\n data?: any;\n}\n\nexport interface WorkflowLineEntityOpts extends EntityOpts, WorkflowLinePortInfo {\n document: WorkflowDocument;\n linesManager: WorkflowLinesManager;\n drawingTo?: LinePoint;\n}\n\nexport interface WorkflowLineInfo extends WorkflowLinePortInfo {\n drawingTo?: LinePoint; // 正在画中的元素\n}\n\nexport interface WorkflowLineUIState {\n /**\n * 是否出错\n */\n hasError: boolean;\n /**\n * 流动\n */\n flowing: boolean;\n /**\n * 禁用\n */\n disabled: boolean;\n /**\n * 箭头反转\n */\n reverse: boolean;\n /**\n * 隐藏箭头\n */\n hideArrow: boolean;\n /**\n * 线条宽度\n * @default 2\n */\n strokeWidth?: number;\n /**\n * 选中后的线条宽度\n * @default 3\n */\n strokeWidthSelected?: number;\n /**\n * 收缩\n * @default 10\n */\n shrink: number;\n /**\n * @deprecated use `lockedColor` instead\n */\n highlightColor: string;\n /**\n * 曲率\n * only for Bezier,\n * @default 0.25\n */\n curvature: number;\n /**\n * Line locked color\n */\n lockedColor: string;\n /**\n * React className\n */\n className?: string;\n /**\n * React style\n */\n style?: React.CSSProperties;\n}\n\n/**\n * 线条\n */\nexport class WorkflowLineEntity extends Entity<WorkflowLineEntityOpts> {\n static type = WORKFLOW_LINE_ENTITY;\n\n /**\n * 转成线条 id\n * @param info\n */\n static portInfoToLineId(info: WorkflowLinePortInfo): string {\n const { from, to, fromPort, toPort } = info;\n return `${from}_${fromPort || ''}-${to || ''}_${toPort || ''}`;\n }\n\n private _onLineDataChangeEmitter = new Emitter<{ oldValue: any; newValue: any }>();\n\n readonly document: WorkflowDocument;\n\n readonly linesManager: WorkflowLinesManager;\n\n readonly onLineDataChange = this._onLineDataChangeEmitter.event;\n\n private _from: WorkflowNodeEntity;\n\n private _to?: WorkflowNodeEntity;\n\n private _lineData: any;\n\n private _uiState: WorkflowLineUIState = {\n hasError: false,\n flowing: false,\n disabled: false,\n hideArrow: false,\n reverse: false,\n shrink: 10,\n curvature: 0.25,\n highlightColor: '',\n lockedColor: '',\n };\n\n /**\n * 线条的 UI 状态\n */\n get uiState(): WorkflowLineUIState {\n return this._uiState;\n }\n\n /**\n * 更新线条的 ui 状态\n * @param newState\n */\n updateUIState(newState: Partial<WorkflowLineUIState>): void {\n let changed = false;\n Object.keys(newState).forEach((key: string) => {\n const value: any = newState[key as keyof WorkflowLineUIState] as any;\n if (this._uiState[key as keyof WorkflowLineUIState] !== value) {\n (this._uiState as any)[key as keyof WorkflowLineUIState] = value;\n changed = true;\n }\n });\n if (changed) {\n this.fireChange();\n }\n }\n\n /**\n * 线条的扩展数据\n */\n get lineData(): any {\n return this._lineData;\n }\n\n /**\n * 更新线条扩展数据\n * @param data\n */\n set lineData(newValue: any) {\n const oldValue = this._lineData;\n if (!isEqual(oldValue, newValue)) {\n this._lineData = newValue;\n this._onLineDataChangeEmitter.fire({ oldValue, newValue });\n this.fireChange();\n }\n }\n\n public stackIndex = 0;\n\n /**\n * 线条数据\n */\n info: WorkflowLineInfo = {\n from: '',\n };\n\n readonly isDrawing: boolean;\n\n /**\n * 线条 Portal 挂载的 div\n */\n private _node?: HTMLDivElement;\n\n constructor(opts: WorkflowLineEntityOpts) {\n super(opts);\n this.document = opts.document;\n this.linesManager = opts.linesManager;\n // 初始化\n this.initInfo({\n from: opts.from,\n to: opts.to,\n drawingTo: opts.drawingTo,\n fromPort: opts.fromPort,\n toPort: opts.toPort,\n data: opts.data,\n });\n if (opts.drawingTo) {\n this.isDrawing = true;\n }\n this.onEntityChange(() => {\n this.fromPort?.validate();\n this.toPort?.validate();\n });\n this.onDispose(() => {\n this.fromPort?.validate();\n this.toPort?.validate();\n });\n this.toDispose.push(this._onLineDataChangeEmitter);\n // this.onDispose(() => {\n // this._infoDispose.dispose();\n // });\n }\n\n /**\n * 获取线条的前置节点\n */\n get from(): WorkflowNodeEntity {\n return this._from;\n }\n\n /**\n * 获取线条的后置节点\n */\n get to(): WorkflowNodeEntity | undefined {\n return this._to;\n }\n\n get isHidden(): boolean {\n return this.highlightColor === this.linesManager.lineColor.hidden;\n }\n\n get inContainer(): boolean {\n const nodeInContainer = (node?: WorkflowNodeEntity) =>\n !!node?.parent && node.parent.flowNodeType !== 'root';\n return nodeInContainer(this.from) || nodeInContainer(this.to);\n }\n\n /**\n * 获取是否 testrun processing\n * @deprecated use `flowing` instead\n */\n get processing(): boolean {\n return this._uiState.flowing;\n }\n\n /**\n * 设置 testrun processing 状态\n * @deprecated use `flowing` instead\n */\n set processing(status: boolean) {\n this.flowing = status;\n }\n\n // 获取连线是否为错误态\n get hasError() {\n return this.uiState.hasError;\n }\n\n // 设置连线的错误态\n set hasError(hasError: boolean) {\n this.updateUIState({\n hasError,\n });\n if (this._node) {\n this._node.dataset.hasError = this.hasError ? 'true' : 'false';\n }\n }\n\n /**\n * 设置线条的后置节点\n */\n setToPort(toPort?: WorkflowPortEntity) {\n // 只有绘制中的线条才允许设置 port, 主要用于吸附到点\n if (!this.isDrawing) {\n throw new Error('[setToPort] only support drawing line.');\n }\n if (this.toPort === toPort) {\n return;\n }\n const prePort = this.toPort;\n if (\n toPort &&\n toPort.portType === 'input' &&\n this.linesManager.canAddLine(this.fromPort, toPort, true)\n ) {\n const { node, portID } = toPort;\n this._to = node;\n this.info.drawingTo = undefined;\n this.info.to = node.id;\n this.info.toPort = portID;\n } else {\n this._to = undefined;\n this.info.to = undefined;\n this.info.toPort = '';\n }\n /**\n * 移动到端口又快速移出,需要更新 prePort 的状态\n */\n if (prePort) {\n prePort.validate();\n }\n this.fireChange();\n }\n\n /**\n * 设置线条画线时的目标位置\n */\n set drawingTo(pos: LinePoint | undefined) {\n const oldDrawingTo = this.info.drawingTo;\n if (!pos) {\n this.info.drawingTo = undefined;\n this.fireChange();\n return;\n }\n if (!oldDrawingTo || pos.x !== oldDrawingTo.x || pos.y !== oldDrawingTo.y) {\n this.info.to = undefined;\n this.info.drawingTo = pos;\n this.fireChange();\n }\n }\n\n /**\n * 获取线条正在画线的位置\n */\n get drawingTo(): LinePoint | undefined {\n return this.info.drawingTo;\n }\n\n get highlightColor(): string {\n return this.uiState.highlightColor || '';\n }\n\n set highlightColor(highlightColor) {\n this.updateUIState({\n highlightColor,\n });\n }\n\n get lockedColor(): string {\n return this.uiState.lockedColor;\n }\n\n set lockedColor(lockedColor: string) {\n this.updateUIState({\n lockedColor,\n });\n }\n\n /**\n * 获取线条的边框位置大小\n */\n get bounds(): Rectangle {\n return this.getData(WorkflowLineRenderData).bounds;\n }\n\n get center(): LineCenterPoint {\n return this.getData(WorkflowLineRenderData).center;\n }\n\n /**\n * 获取点和线最接近的距离\n */\n getHoverDist(pos: IPoint): number {\n return this.getData(WorkflowLineRenderData).calcDistance(pos);\n }\n\n get fromPort(): WorkflowPortEntity {\n return this.from\n .getData(WorkflowNodePortsData)\n .getPortEntityByKey('output', this.info.fromPort);\n }\n\n get toPort(): WorkflowPortEntity | undefined {\n if (!this.to) {\n return undefined;\n }\n return this.to.getData(WorkflowNodePortsData).getPortEntityByKey('input', this.info.toPort);\n }\n\n /**\n * 获取线条真实的输入输出节点坐标\n */\n get position(): LinePosition {\n return this.getData(WorkflowLineRenderData).position;\n }\n\n /** 是否反转箭头 */\n get reverse(): boolean {\n return this.linesManager.isReverseLine(this, this.uiState.reverse);\n }\n\n /** 是否隐藏箭头 */\n get hideArrow(): boolean {\n return this.linesManager.isHideArrowLine(this, this.uiState.hideArrow);\n }\n\n /** 是否流动 */\n get flowing(): boolean {\n return this.linesManager.isFlowingLine(this, this.uiState.flowing);\n }\n\n set flowing(flowing: boolean) {\n if (this._uiState.flowing !== flowing) {\n this._uiState.flowing = flowing;\n this.fireChange();\n }\n }\n\n /** 是否禁用 */\n get disabled(): boolean {\n return this.linesManager.isDisabledLine(this, this.uiState.disabled);\n }\n\n /**\n * @deprecated\n */\n get vertical(): boolean {\n const fromLocation = this.fromPort.location;\n const toLocation = this.toPort?.location;\n if (toLocation) {\n return toLocation === 'top';\n } else {\n return fromLocation === 'bottom';\n }\n }\n\n /** 获取线条渲染器类型 */\n get renderType(): LineRenderType | undefined {\n return this.linesManager.setLineRenderType(this);\n }\n\n /** 获取线条样式 */\n get className(): string {\n return [this.linesManager.setLineClassName(this), this._uiState.className]\n .filter((s) => !!s)\n .join(' ');\n }\n\n get color(): string | undefined {\n return this.linesManager.getLineColor(this);\n }\n\n /**\n * 初始化线条\n * @param info 线条信息\n */\n protected initInfo(info: WorkflowLineInfo): void {\n if (!isEqual(info, this.info)) {\n this.info = info;\n this._from = this.document.getNode(info.from)!;\n this._to = info.to ? this.document.getNode(info.to) : undefined;\n this._lineData = info.data;\n this.fireChange();\n }\n }\n\n // 校验连线是否为错误态\n validate() {\n this.validateSelf();\n }\n\n /**\n * use `validate` instead\n * @deprecated\n */\n protected validateSelf() {\n const { fromPort, toPort } = this;\n\n if (fromPort) {\n this.hasError = this.linesManager.isErrorLine(fromPort, toPort, this.uiState.hasError);\n }\n }\n\n is(line: WorkflowLineEntity | WorkflowLinePortInfo): boolean {\n if (line instanceof WorkflowLineEntity) {\n return this === line;\n }\n return WorkflowLineEntity.portInfoToLineId(line as WorkflowLinePortInfo) === this.id;\n }\n\n canRemove(newLineInfo?: Required<WorkflowLinePortInfo>): boolean {\n return this.linesManager.canRemove(this, newLineInfo);\n }\n\n get node(): HTMLDivElement {\n if (this._node) return this._node;\n this._node = domUtils.createDivWithClass('gedit-flow-activity-line');\n this._node.dataset.testid = 'sdk.workflow.canvas.line';\n this._node.dataset.lineId = this.id;\n this._node.dataset.fromNodeId = this.from.id;\n this._node.dataset.fromPortId = this.fromPort?.id ?? '';\n this._node.dataset.toNodeId = this.to?.id ?? '';\n this._node.dataset.toPortId = this.toPort?.id ?? '';\n this._node.dataset.hasError = this.hasError ? 'true' : 'false';\n return this._node;\n }\n\n toJSON(): WorkflowEdgeJSON {\n const json: WorkflowEdgeJSON = {\n sourceNodeID: this.info.from,\n targetNodeID: this.info.to!,\n sourcePortID: this.info.fromPort,\n targetPortID: this.info.toPort,\n };\n if (this._lineData !== undefined) {\n json.data = this._lineData;\n }\n if (!json.sourcePortID) {\n delete json.sourcePortID;\n }\n if (!json.targetPortID) {\n delete json.targetPortID;\n }\n return json;\n }\n\n /** 触发线条渲染 */\n fireRender(): void {\n this.fireChange();\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { isEqual } from 'lodash-es';\nimport { FlowNodeRenderData } from '@flowgram.ai/document';\nimport { EntityData, SizeData } from '@flowgram.ai/core';\n\nimport { type WorkflowPortType, getPortEntityId } from '../utils/statics';\nimport { type LinePoint, LinePointLocation, type WorkflowNodeMeta } from '../typings';\nimport { WorkflowPortEntity } from '../entities/workflow-port-entity';\nimport { type WorkflowNodeEntity, type WorkflowPort, type WorkflowPorts } from '../entities';\n\n/**\n * 节点的点位信息\n * portsData 只监听点位的数目和类型,不监听点位的 position 变化\n */\nexport class WorkflowNodePortsData extends EntityData {\n public static readonly type = 'WorkflowNodePortsData';\n\n public readonly entity: WorkflowNodeEntity;\n\n /** 静态的 ports 数据 */\n protected _staticPorts: WorkflowPorts = [];\n\n /** 存储 port 实体的 id,用于判断 port 是否存在 */\n protected _portIDSet = new Set<string>();\n\n /** 上一次的 ports 数据,用于判断 ports 是否发生变化 */\n protected _prePorts: WorkflowPorts;\n\n constructor(entity: WorkflowNodeEntity) {\n super(entity);\n this.entity = entity;\n const meta = entity.getNodeMeta<WorkflowNodeMeta>();\n // 动态模式默认为空, 非动态模式默认左右两个点位\n const defaultPorts: WorkflowPorts = meta.useDynamicPort\n ? []\n : [{ type: 'input' }, { type: 'output' }];\n this._staticPorts = meta.defaultPorts?.slice() || defaultPorts;\n this.updatePorts(this._staticPorts);\n if (meta.useDynamicPort) {\n this.toDispose.push(\n // 只需要监听节点的大小,因为算的是相对位置\n entity.getData!(SizeData)!.onDataChange(() => {\n // 有可能节点被销毁了\n if (entity.getData!(SizeData).width && entity.getData!(SizeData).height) {\n this.updateDynamicPorts();\n }\n })\n );\n }\n this.onDispose(() => {\n this.allPorts.forEach((port) => port.dispose());\n });\n }\n\n public getDefaultData(): any {\n return {};\n }\n\n /**\n * Update all ports data, includes static ports and dynamic ports\n * @param ports\n */\n public updateAllPorts(ports?: WorkflowPorts) {\n const meta = this.entity.getNodeMeta<WorkflowNodeMeta>();\n if (ports) {\n this._staticPorts = ports;\n }\n if (meta.useDynamicPort) {\n this.updateDynamicPorts();\n } else {\n this.updatePorts(this._staticPorts);\n }\n }\n\n /**\n * @deprecated use `updateAllPorts` instead\n */\n public updateStaticPorts(ports: WorkflowPorts): void {\n this.updateAllPorts(ports);\n }\n\n /**\n * 动态计算点位,通过 dom 的 data-port-key\n */\n public updateDynamicPorts(): void {\n const domNode = this.entity.getData(FlowNodeRenderData)!.node;\n const elements = domNode.querySelectorAll<HTMLDivElement>('[data-port-id]');\n const staticPorts: WorkflowPorts = this._staticPorts;\n const dynamicPorts: WorkflowPorts = [];\n if (elements.length > 0) {\n dynamicPorts.push(\n ...Array.from(elements).map((element) => ({\n portID: element.getAttribute('data-port-id')!,\n type: element.getAttribute('data-port-type')! as WorkflowPortType,\n location: element.getAttribute('data-port-location')! as LinePointLocation,\n targetElement: element,\n }))\n );\n }\n this.updatePorts(staticPorts.concat(dynamicPorts));\n }\n\n /**\n * 根据 key 获取 port 实体\n */\n public getPortEntityByKey(\n portType: WorkflowPortType,\n portKey?: string | number\n ): WorkflowPortEntity {\n const entity = this.getOrCreatePortEntity({\n type: portType,\n portID: portKey,\n });\n return entity;\n }\n\n /**\n * 更新 ports 数据\n */\n protected updatePorts(ports: WorkflowPorts): void {\n if (!isEqual(this._prePorts, ports)) {\n const portKeys = ports.map((port) => this.getPortId(port.type, port.portID));\n this._portIDSet.forEach((portId) => {\n if (!portKeys.includes(portId)) {\n this.getPortEntity(portId)?.dispose();\n }\n });\n ports.forEach((port) => this.updatePortEntity(port));\n this._prePorts = ports;\n this.fireChange();\n }\n\n // Note: 为什么调用 port.validate 不够,需要调用 line.validate\n // 原因:假设有这样的连线:dynamic port → end 节点。\n // line.validate 时,line.fromPort 可能为 undefined(未创建实体),导致 end 节点上的 port 未正确校验\n // 所以需要在所有 port entities 准备完成后,通过再次调用 line.validate 来触发连线另一端的 port 更新\n this.allPorts.forEach((port) => {\n port.allLines.forEach((line) => {\n line.validate();\n });\n });\n }\n\n /**\n * 获取所有 port entities\n */\n public get allPorts(): WorkflowPortEntity[] {\n return Array.from(this._portIDSet)\n .map((portId) => this.getPortEntity(portId)!)\n .filter(Boolean); // dispose 时,会获取不到 port\n }\n\n /**\n * 获取输入点位\n */\n public get inputPorts(): WorkflowPortEntity[] {\n return this.allPorts.filter((port) => port.portType === 'input');\n }\n\n /**\n * 获取输出点位\n */\n public get outputPorts(): WorkflowPortEntity[] {\n return this.allPorts.filter((port) => port.portType === 'output');\n }\n\n /**\n * 获取输入点位置\n */\n public get inputPoints(): LinePoint[] {\n return this.inputPorts.map((port) => port.point);\n }\n\n /**\n * 获取输出点位置\n */\n public get outputPoints(): LinePoint[] {\n return this.inputPorts.map((port) => port.point);\n }\n\n /**\n * 根据 key 获取 输入点位置\n */\n public getInputPoint(key?: string | number): LinePoint {\n return this.getPortEntityByKey('input', key).point;\n }\n\n /**\n * 根据 key 获取输出点位置\n */\n public getOutputPoint(key?: string | number): LinePoint {\n return this.getPortEntityByKey('output', key).point;\n }\n\n /**\n * 获取 port 实体\n */\n protected getPortEntity(portId: string): WorkflowPortEntity | undefined {\n if (!this._portIDSet.has(portId)) {\n // 如果不是自身创建的 port,则返回 undefined\n return undefined;\n }\n return this.entity.entityManager.getEntityById<WorkflowPortEntity>(portId)!;\n }\n\n /**\n * 拼接 port 实体的 id\n */\n protected getPortId(portType: WorkflowPortType, portKey: string | number = ''): string {\n return getPortEntityId(this.entity, portType, portKey);\n }\n\n /**\n * 创建 port 实体\n */\n protected createPortEntity(portInfo: WorkflowPort): WorkflowPortEntity {\n const id = this.getPortId(portInfo.type, portInfo.portID);\n let portEntity = this.entity.entityManager.getEntityById<WorkflowPortEntity>(id);\n if (!portEntity) {\n portEntity = this.entity.entityManager.createEntity<WorkflowPortEntity>(WorkflowPortEntity, {\n id,\n node: this.entity,\n ...portInfo,\n });\n }\n portEntity.onDispose(() => {\n this._portIDSet.delete(id);\n });\n this._portIDSet.add(id);\n return portEntity;\n }\n\n /**\n * 获取或创建 port 实体\n */\n protected getOrCreatePortEntity(portInfo: WorkflowPort): WorkflowPortEntity {\n const id = this.getPortId(portInfo.type, portInfo.portID);\n return this.getPortEntity(id) ?? this.createPortEntity(portInfo);\n }\n\n /**\n * 更新 port 实体\n */\n protected updatePortEntity(portInfo: WorkflowPort): WorkflowPortEntity {\n const portEntity = this.getOrCreatePortEntity(portInfo);\n portEntity.update(portInfo);\n return portEntity;\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { type IPoint, Rectangle, Emitter, Compare } from '@flowgram.ai/utils';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport {\n Entity,\n type EntityOpts,\n PlaygroundConfigEntity,\n TransformData,\n type EntityRegistry,\n} from '@flowgram.ai/core';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport {\n type WorkflowPortType,\n getPortEntityId,\n WORKFLOW_LINE_ENTITY,\n domReactToBounds,\n} from '../utils/statics';\nimport { type WorkflowNodeMeta, LinePointLocation, LinePoint } from '../typings';\nimport { type WorkflowNodeEntity } from './workflow-node-entity';\nimport { type WorkflowLineEntity } from './workflow-line-entity';\n\n// port 的宽度\nexport const PORT_SIZE = 24;\n\nexport interface WorkflowPort {\n /**\n * 没有代表 默认连接点,默认 input 类型 为最左边中心,output 类型为最右边中心\n */\n portID?: string | number;\n /**\n * 输入或者输出点\n */\n type: WorkflowPortType;\n /**\n * 端口位置\n */\n location?: LinePointLocation;\n /**\n * 端口热区大小\n */\n size?: { width: number; height: number };\n /**\n * 相对于 position 的偏移\n */\n offset?: IPoint;\n /**\n * 禁用端口\n */\n disabled?: boolean;\n /**\n * 将点位渲染到该父节点上\n */\n targetElement?: HTMLElement;\n}\n\nexport type WorkflowPorts = WorkflowPort[];\n\nexport interface WorkflowPortEntityOpts extends EntityOpts, WorkflowPort {\n /**\n * port 属于哪个节点\n */\n node: WorkflowNodeEntity;\n}\n\n/**\n * Port 抽象的 Entity\n */\nexport class WorkflowPortEntity extends Entity<WorkflowPortEntityOpts> {\n static type = 'WorkflowPortEntity';\n\n readonly node: WorkflowNodeEntity;\n\n readonly portID: string | number = '';\n\n readonly portType: WorkflowPortType;\n\n private _disabled?: boolean;\n\n private _hasError = false;\n\n private _location?: LinePointLocation;\n\n private _size?: { width: number; height: number };\n\n private _offset?: IPoint;\n\n protected readonly _onErrorChangedEmitter = new Emitter<void>();\n\n onErrorChanged = this._onErrorChangedEmitter.event;\n\n targetElement?: HTMLElement;\n\n static getPortEntityId(\n node: WorkflowNodeEntity,\n portType: WorkflowPortType,\n portID: string | number = ''\n ): string {\n return getPortEntityId(node, portType, portID);\n }\n\n get position(): LinePointLocation | undefined {\n return this._location;\n }\n\n constructor(opts: WorkflowPortEntityOpts) {\n super(opts);\n this.portID = opts.portID || '';\n this.portType = opts.type;\n this._disabled = opts.disabled;\n this._offset = opts.offset;\n this._location = opts.location;\n this._size = opts.size;\n this.node = opts.node;\n this.updateTargetElement(opts.targetElement);\n this.toDispose.push(this.node.getData(TransformData)!.onDataChange(() => this.fireChange()));\n this.toDispose.push(this.node.onDispose(this.dispose.bind(this)));\n }\n\n // 获取连线是否为错误态\n get hasError() {\n return this._hasError;\n }\n\n // 设置连线的错误态,外部应使用 validate 进行更新\n set hasError(hasError: boolean) {\n if (hasError !== this._hasError) {\n this._hasError = hasError;\n this._onErrorChangedEmitter.fire();\n }\n }\n\n validate() {\n // 一个端口可能连接很多线,需要保证所有的连线都不包含错误\n const anyLineHasError = this.allLines.some((line) => {\n // 忽略已销毁和被隐藏的线\n if (line.disposed || line.isHidden) {\n return false;\n }\n\n return line.hasError;\n });\n // 如果没有连线错误,需校验端口自身错误\n const isPortHasError = (this.node.document as WorkflowDocument).isErrorPort(this);\n this.hasError = anyLineHasError || isPortHasError;\n }\n\n isErrorPort() {\n return (this.node.document as WorkflowDocument).isErrorPort(this, this.hasError);\n }\n\n get location(): LinePointLocation {\n if (this._location) {\n return this._location;\n }\n if (this.portType === 'input') {\n return 'left';\n }\n return 'right';\n }\n\n get point(): LinePoint {\n const { targetElement } = this;\n const { bounds } = this.node.getData(FlowNodeTransformData)!;\n const location = this.location;\n if (targetElement) {\n const pos = domReactToBounds(targetElement.getBoundingClientRect()).center;\n const point = this.entityManager\n .getEntity<PlaygroundConfigEntity>(PlaygroundConfigEntity)!\n .getPosFromMouseEvent({\n clientX: pos.x,\n clientY: pos.y,\n });\n return {\n x: point.x,\n y: point.y,\n location,\n };\n }\n let point = { x: 0, y: 0 };\n const offset = this._offset || { x: 0, y: 0 };\n switch (location) {\n case 'left':\n point = bounds.leftCenter;\n break;\n case 'top':\n point = bounds.topCenter;\n break;\n case 'right':\n point = bounds.rightCenter;\n break;\n case 'bottom':\n point = bounds.bottomCenter;\n break;\n }\n return {\n x: point.x + offset.x,\n y: point.y + offset.y,\n location,\n };\n }\n\n /**\n * 端口热区\n */\n get bounds(): Rectangle {\n const { point } = this;\n const size = this._size || { width: PORT_SIZE, height: PORT_SIZE };\n return new Rectangle(\n point.x - size.width / 2,\n point.y - size.height / 2,\n size.width,\n size.height\n );\n }\n\n isHovered(x: number, y: number): boolean {\n return this.bounds.contains(x, y);\n }\n\n /**\n * 相对节点左上角的位置\n */\n get relativePosition(): IPoint {\n const { point } = this;\n const { bounds } = this.node.getData(FlowNodeTransformData)!;\n return {\n x: point.x - bounds.x,\n y: point.y - bounds.y,\n };\n }\n\n updateTargetElement(el?: HTMLElement): void {\n if (el !== this.targetElement) {\n this.targetElement = el;\n this.fireChange();\n }\n }\n\n /**\n * 是否被禁用\n */\n get disabled(): boolean {\n const document = this.node.document as WorkflowDocument;\n if (typeof document.options.isDisabledPort === 'function') {\n return document.options.isDisabledPort(this);\n }\n if (this._disabled) {\n return true;\n }\n const meta = this.node.getNodeMeta<WorkflowNodeMeta>();\n if (this.portType === 'input') {\n return !!meta.inputDisable;\n }\n return !!meta.outputDisable;\n }\n\n /**\n * 当前点位上连接的线条\n * @deprecated use `availableLines` instead\n */\n get lines(): WorkflowLineEntity[] {\n return this.allLines.filter((line) => !line.isDrawing);\n }\n\n /**\n * 当前有效的线条,不包含正在画的线条和隐藏的线条(这个出现在线条重连会先把原来的线条隐藏)\n */\n get availableLines(): WorkflowLineEntity[] {\n return this.allLines.filter((line) => !line.isDrawing && !line.isHidden);\n }\n\n /**\n * 当前点位上连接的线条(包含 isDrawing === true 的线条)\n */\n get allLines() {\n const lines: WorkflowLineEntity[] = [];\n // TODO: 后续 sdk 支持 getEntitiesByType 单独根据 type 获取功能后修改\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const allLines = this.entityManager.getEntities<WorkflowLineEntity>({\n type: WORKFLOW_LINE_ENTITY,\n } as EntityRegistry);\n allLines.forEach((line) => {\n // 不包含 drawing 的线条\n if (line.toPort === this || line.fromPort === this) {\n lines.push(line);\n }\n });\n return lines;\n }\n\n update(data: Exclude<WorkflowPort, 'portID' | 'type'>) {\n let changed = false;\n if (data.targetElement !== this.targetElement) {\n this.targetElement = data.targetElement;\n changed = true;\n }\n if (data.location !== this._location) {\n this._location = data.location;\n changed = true;\n }\n if (Compare.isChanged(data.offset, this._offset)) {\n this._offset = data.offset;\n changed = true;\n }\n if (Compare.isChanged(data.size, this._size)) {\n this._size = data.size;\n changed = true;\n }\n if (data.disabled !== this._disabled) {\n this._disabled = data.disabled;\n changed = true;\n }\n if (changed) {\n this.fireChange();\n }\n }\n\n dispose(): void {\n // 点位被删除,对应的线条也要删除\n this.lines.forEach((l) => l.dispose());\n super.dispose();\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Disposable } from '@flowgram.ai/utils';\nimport { EntityData } from '@flowgram.ai/core';\n\nimport { type WorkflowLineEntity, type WorkflowNodeEntity } from '../entities';\n\nexport interface WorkflowNodeLines {\n inputLines: WorkflowLineEntity[];\n outputLines: WorkflowLineEntity[];\n}\n\n/**\n * 节点的关联的线条\n */\nexport class WorkflowNodeLinesData extends EntityData<WorkflowNodeLines> {\n static type = 'WorkflowNodeLinesData';\n\n entity: WorkflowNodeEntity;\n\n getDefaultData(): WorkflowNodeLines {\n return {\n inputLines: [],\n outputLines: [],\n };\n }\n\n constructor(entity: WorkflowNodeEntity) {\n super(entity);\n this.entity = entity;\n this.entity.preDispose.push(\n Disposable.create(() => {\n this.inputLines.slice().forEach((line) => line.dispose());\n this.outputLines.slice().forEach((line) => line.dispose());\n })\n );\n }\n\n /**\n * 输入线条\n */\n get inputLines(): WorkflowLineEntity[] {\n return this.data.inputLines;\n }\n\n /**\n * 输出线条\n */\n get outputLines(): WorkflowLineEntity[] {\n return this.data.outputLines;\n }\n\n get allLines(): WorkflowLineEntity[] {\n return this.data.inputLines.concat(this.data.outputLines);\n }\n\n get availableLines(): WorkflowLineEntity[] {\n return this.allLines.filter((line) => !line.isDrawing && !line.isHidden);\n }\n\n /**\n * 输入节点\n */\n get inputNodes(): WorkflowNodeEntity[] {\n return this.inputLines.map((l) => l.from!).filter(Boolean);\n }\n\n /**\n * 所有输入节点\n */\n get allInputNodes(): WorkflowNodeEntity[] {\n const nodeSet: Set<WorkflowNodeEntity> = new Set();\n\n const handleNode = (node: WorkflowNodeEntity): void => {\n if (nodeSet.has(node)) {\n return;\n }\n\n nodeSet.add(node);\n\n const { inputNodes } = node.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData)!;\n if (!inputNodes || !inputNodes.length) {\n return;\n }\n\n inputNodes.forEach((inputNode: WorkflowNodeEntity) => {\n // 如果 outputNode 和当前 node 是父子节点,则不向下遍历\n if (inputNode?.parent === node || node?.parent === inputNode) {\n return;\n }\n handleNode(inputNode);\n });\n };\n\n handleNode(this.entity);\n nodeSet.delete(this.entity);\n\n return Array.from(nodeSet);\n }\n\n /**\n * 输出节点\n */\n get outputNodes(): WorkflowNodeEntity[] {\n return this.outputLines.map((l) => l.to!).filter(Boolean);\n }\n\n /**\n * 输入输出节点\n */\n get allOutputNodes(): WorkflowNodeEntity[] {\n const nodeSet: Set<WorkflowNodeEntity> = new Set();\n\n const handleNode = (node: WorkflowNodeEntity): void => {\n if (nodeSet.has(node)) {\n return;\n }\n\n nodeSet.add(node);\n\n const { outputNodes } = node.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData)!;\n if (!outputNodes || !outputNodes.length) {\n return;\n }\n\n outputNodes.forEach((outputNode: WorkflowNodeEntity) => {\n // 如果 outputNode 和当前 node 是父子节点,则不向下遍历\n if (outputNode?.parent === node || node?.parent === outputNode) {\n return;\n }\n handleNode(outputNode);\n });\n };\n\n handleNode(this.entity);\n nodeSet.delete(this.entity);\n\n return Array.from(nodeSet);\n }\n\n addLine(line: WorkflowLineEntity): void {\n if (line.from === this.entity) {\n this.outputLines.push(line);\n } else {\n this.inputLines.push(line);\n }\n this.fireChange();\n }\n\n removeLine(line: WorkflowLineEntity): void {\n const { inputLines, outputLines } = this;\n const inputIndex = inputLines.indexOf(line);\n const outputIndex = outputLines.indexOf(line);\n if (inputIndex !== -1) {\n inputLines.splice(inputIndex, 1);\n this.fireChange();\n }\n if (outputIndex !== -1) {\n outputLines.splice(outputIndex, 1);\n this.fireChange();\n }\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { IPoint, Rectangle } from '@flowgram.ai/utils';\nimport { EntityData } from '@flowgram.ai/core';\n\nimport {\n LineCenterPoint,\n LinePosition,\n LineRenderType,\n WorkflowLineRenderContribution,\n WorkflowLineRenderContributionFactory,\n} from '../typings';\nimport { WorkflowLineEntity } from '../entities';\nimport { WorkflowNodePortsData } from './workflow-node-ports-data';\n\nexport interface WorkflowLineRenderDataSchema {\n version: string;\n contributions: Map<LineRenderType, WorkflowLineRenderContribution>;\n position: LinePosition;\n}\n\nexport class WorkflowLineRenderData extends EntityData<WorkflowLineRenderDataSchema> {\n static type = 'WorkflowLineRenderData';\n\n declare entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n super(entity);\n this.syncContributions();\n }\n\n public getDefaultData(): WorkflowLineRenderDataSchema {\n return {\n version: '',\n contributions: new Map(),\n position: {\n from: { x: 0, y: 0, location: 'right' },\n to: { x: 0, y: 0, location: 'left' },\n },\n };\n }\n\n public get renderVersion(): string {\n return this.data.version;\n }\n\n public get position(): LinePosition {\n return this.data.position;\n }\n\n public get path(): string {\n return this.currentLine?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n return this.currentLine?.calcDistance(pos) ?? Number.MAX_SAFE_INTEGER;\n }\n\n public get bounds(): Rectangle {\n return this.currentLine?.bounds ?? new Rectangle();\n }\n\n /**\n * 更新数据\n * WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排\n */\n public update(): void {\n this.syncContributions();\n const oldVersion = this.data.version;\n this.updatePosition();\n const newVersion = this.data.version;\n if (oldVersion === newVersion) {\n return;\n }\n this.data.version = newVersion;\n this.currentLine?.update({\n fromPos: this.data.position.from,\n toPos: this.data.position.to,\n });\n }\n\n private get lineType(): LineRenderType {\n return this.entity.renderType ?? this.entity.linesManager.lineType;\n }\n\n /**\n * 获取 center 位置\n */\n get center(): LineCenterPoint {\n return this.currentLine?.center || { x: 0, y: 0, labelX: 0, labelY: 0 };\n }\n\n /**\n * 更新版本\n * WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排\n */\n private updatePosition(): void {\n this.data.position.from = this.entity.from\n .getData(WorkflowNodePortsData)!\n .getOutputPoint(this.entity.info.fromPort);\n\n if (this.entity.info.drawingTo) {\n this.data.position.to = this.entity.info.drawingTo;\n } else {\n this.data.position.to = this.entity.to\n ?.getData(WorkflowNodePortsData)\n ?.getInputPoint(this.entity.info.toPort) ?? {\n x: this.data.position.from.x,\n y: this.data.position.from.y,\n location: this.data.position.from.location === 'right' ? 'left' : 'top',\n };\n }\n\n this.data.version = [\n this.lineType,\n this.data.position.from.x,\n this.data.position.from.y,\n this.data.position.from.location,\n this.data.position.to.x,\n this.data.position.to.y,\n this.data.position.to.location,\n ].join('-');\n }\n\n private get currentLine(): WorkflowLineRenderContribution | undefined {\n return this.data.contributions.get(this.lineType);\n }\n\n private syncContributions(): void {\n if (this.entity.linesManager.contributionFactories.length === this.data.contributions.size) {\n return;\n }\n this.entity.linesManager.contributionFactories.forEach((factory) => {\n this.registerContribution(factory);\n });\n }\n\n private registerContribution(contributionFactory: WorkflowLineRenderContributionFactory): void {\n if (this.data.contributions.has(contributionFactory.type)) {\n return;\n }\n const contribution = new contributionFactory(this.entity);\n this.data.contributions.set(contributionFactory.type, contribution);\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { inject, injectable } from 'inversify';\nimport { Emitter, type PositionSchema } from '@flowgram.ai/utils';\nimport { EntityManager } from '@flowgram.ai/core';\n\nimport {\n type WorkflowLineEntity,\n type WorkflowNodeEntity,\n type WorkflowPortEntity,\n} from '../entities';\n\n/**\n * 可 Hover 的节点 类型\n */\nexport type WorkflowEntityHoverable = WorkflowNodeEntity | WorkflowLineEntity | WorkflowPortEntity;\n\nexport interface HoverPosition {\n position: PositionSchema;\n target?: HTMLElement;\n}\n\n/** @deprecated */\nexport type WorkfloEntityHoverable = WorkflowEntityHoverable;\n/**\n * hover 状态管理\n */\n@injectable()\nexport class WorkflowHoverService {\n @inject(EntityManager) protected entityManager: EntityManager;\n\n protected onHoveredChangeEmitter = new Emitter<string>();\n\n protected onUpdateHoverPositionEmitter = new Emitter<HoverPosition>();\n\n readonly onHoveredChange = this.onHoveredChangeEmitter.event;\n\n readonly onUpdateHoverPosition = this.onUpdateHoverPositionEmitter.event;\n\n // 当前鼠标 hover 位置\n hoveredPos: PositionSchema = { x: 0, y: 0 };\n\n /**\n * 当前 hovered 的 节点或者线条或者点\n * 1: nodeId / lineId (节点 / 线条)\n * 2: nodeId:portKey (节点连接点)\n */\n hoveredKey = '';\n\n /**\n * 更新 hover 的内容\n * @param hoveredKey hovered key\n */\n updateHoveredKey(hoveredKey: string): void {\n if (this.hoveredKey !== hoveredKey) {\n this.hoveredKey = hoveredKey;\n this.onHoveredChangeEmitter.fire(hoveredKey);\n }\n }\n\n updateHoverPosition(position: PositionSchema, target?: HTMLElement): void {\n this.hoveredPos = position;\n this.onUpdateHoverPositionEmitter.fire({\n position,\n target,\n });\n }\n\n /**\n * 清空 hover 内容\n */\n clearHovered(): void {\n this.updateHoveredKey('');\n }\n\n /**\n * 判断是否 hover\n * @param nodeId hoveredKey\n * @returns 是否 hover\n */\n isHovered(nodeId: string): boolean {\n return nodeId === this.hoveredKey;\n }\n\n isSomeHovered(): boolean {\n return !!this.hoveredKey;\n }\n\n /**\n * 获取被 hover 的节点或线条\n */\n get hoveredNode(): WorkfloEntityHoverable | undefined {\n return this.entityManager.getEntityById(this.hoveredKey);\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport type React from 'react';\n\nimport { nanoid } from 'nanoid';\nimport { inject, injectable, postConstruct } from 'inversify';\nimport {\n domUtils,\n type IPoint,\n PromiseDeferred,\n Emitter,\n type PositionSchema,\n DisposableCollection,\n Rectangle,\n delay,\n Disposable,\n} from '@flowgram.ai/utils';\nimport {\n FlowNodeTransformData,\n FlowNodeType,\n FlowOperationBaseService,\n type FlowNodeEntity,\n} from '@flowgram.ai/document';\nimport { FlowNodeBaseType } from '@flowgram.ai/document';\nimport {\n CommandService,\n MouseTouchEvent,\n PlaygroundConfigEntity,\n PlaygroundDrag,\n type PlaygroundDragEvent,\n TransformData,\n} from '@flowgram.ai/core';\n\nimport { WorkflowLinesManager } from '../workflow-lines-manager';\nimport { WorkflowDocumentOptions } from '../workflow-document-option';\nimport { WorkflowDocument } from '../workflow-document';\nimport { LineEventProps, NodesDragEvent, OnDragLineEnd } from '../typings/workflow-drag';\nimport { LinePointLocation, type WorkflowNodeJSON, type WorkflowNodeMeta } from '../typings';\nimport { WorkflowNodePortsData } from '../entity-datas';\nimport {\n type WorkflowLineEntity,\n type WorkflowLinePortInfo,\n type WorkflowNodeEntity,\n type WorkflowPortEntity,\n} from '../entities';\nimport { WorkflowSelectService } from './workflow-select-service';\nimport { WorkflowHoverService } from './workflow-hover-service';\n\nconst DRAG_TIMEOUT = 100;\nconst DRAG_MIN_DELTA = 5;\nfunction checkDragSuccess(\n time: number,\n e: PlaygroundDragEvent,\n originLine?: WorkflowLineEntity\n): boolean {\n if (\n !originLine ||\n time > DRAG_TIMEOUT ||\n Math.abs(e.endPos.x - e.startPos.x) >= DRAG_MIN_DELTA ||\n Math.abs(e.endPos.y - e.startPos.y) >= DRAG_MIN_DELTA\n ) {\n return true;\n }\n return false;\n}\n\nfunction reverseLocation(sourceLocation: LinePointLocation): LinePointLocation {\n switch (sourceLocation) {\n case 'bottom':\n return 'top';\n case 'left':\n return 'right';\n case 'top':\n return 'bottom';\n case 'right':\n return 'left';\n }\n}\n\n@injectable()\nexport class WorkflowDragService {\n @inject(PlaygroundConfigEntity)\n protected playgroundConfig: PlaygroundConfigEntity;\n\n @inject(WorkflowHoverService) protected hoverService: WorkflowHoverService;\n\n @inject(WorkflowDocument) protected document: WorkflowDocument;\n\n @inject(WorkflowLinesManager) protected linesManager: WorkflowLinesManager;\n\n @inject(CommandService) protected commandService: CommandService;\n\n @inject(WorkflowSelectService) protected selectService: WorkflowSelectService;\n\n @inject(FlowOperationBaseService)\n protected operationService: FlowOperationBaseService;\n\n @inject(WorkflowDocumentOptions)\n readonly options: WorkflowDocumentOptions;\n\n private _onDragLineEventEmitter = new Emitter<LineEventProps>();\n\n readonly onDragLineEventChange = this._onDragLineEventEmitter.event;\n\n isDragging = false;\n\n private _nodesDragEmitter = new Emitter<NodesDragEvent>();\n\n readonly onNodesDrag = this._nodesDragEmitter.event;\n\n protected _toDispose = new DisposableCollection();\n\n private _droppableTransforms: FlowNodeTransformData[] = [];\n\n private _dropNode?: FlowNodeEntity;\n\n private posAdjusters: Set<\n (params: { selectedNodes: WorkflowNodeEntity[]; position: IPoint }) => IPoint\n > = new Set();\n\n private _onDragLineEndCallbacks: Map<string, OnDragLineEnd> = new Map();\n\n @postConstruct()\n init() {\n this._toDispose.pushAll([this._onDragLineEventEmitter, this._nodesDragEmitter]);\n if (this.options.onDragLineEnd) {\n this._toDispose.push(this.onDragLineEnd(this.options.onDragLineEnd));\n }\n }\n\n dispose() {\n this._toDispose.dispose();\n }\n\n /**\n * 拖拽选中节点\n * @param triggerEvent\n */\n async startDragSelectedNodes(triggerEvent: MouseEvent | React.MouseEvent): Promise<boolean> {\n let { selectedNodes } = this.selectService;\n if (\n selectedNodes.length === 0 ||\n this.playgroundConfig.readonly ||\n this.playgroundConfig.disabled ||\n this.isDragging\n ) {\n return Promise.resolve(false);\n }\n this.isDragging = true;\n const sameParent = this.childrenOfContainer(selectedNodes);\n if (sameParent && sameParent.flowNodeType !== FlowNodeBaseType.ROOT) {\n selectedNodes = [sameParent];\n }\n // 节点整体开始位置\n let startPosition = this.getNodesPosition(selectedNodes);\n // 单个节点开始位置\n let startPositions = selectedNodes.map((node) => {\n const transform = node.getData(TransformData);\n return { x: transform.position.x, y: transform.position.y };\n });\n let dragSuccess = false;\n const startTime = Date.now();\n const dragger = new PlaygroundDrag({\n onDragStart: (dragEvent) => {\n this._nodesDragEmitter.fire({\n type: 'onDragStart',\n nodes: selectedNodes,\n startPositions,\n dragEvent,\n triggerEvent,\n dragger,\n });\n },\n onDrag: (dragEvent) => {\n if (!dragSuccess && checkDragSuccess(Date.now() - startTime, dragEvent)) {\n dragSuccess = true;\n }\n\n // 计算拖拽偏移量\n const offset: IPoint = this.getDragPosOffset({\n event: dragEvent,\n selectedNodes,\n startPosition,\n });\n\n const positions: PositionSchema[] = [];\n\n selectedNodes.forEach((node, index) => {\n const transform = node.getData(TransformData);\n const nodeStartPosition = startPositions[index];\n const newPosition = {\n x: nodeStartPosition.x + offset.x,\n y: nodeStartPosition.y + offset.y,\n };\n transform.update({\n position: newPosition,\n });\n this.document.layout.updateAffectedTransform(node);\n positions.push(newPosition);\n });\n\n this._nodesDragEmitter.fire({\n type: 'onDragging',\n nodes: selectedNodes,\n startPositions,\n positions,\n dragEvent,\n triggerEvent,\n dragger,\n });\n },\n onDragEnd: (dragEvent) => {\n this.isDragging = false;\n this._nodesDragEmitter.fire({\n type: 'onDragEnd',\n nodes: selectedNodes,\n startPositions,\n dragEvent,\n triggerEvent,\n dragger,\n });\n },\n });\n const { clientX, clientY } = MouseTouchEvent.getEventCoord(triggerEvent);\n return dragger.start(clientX, clientY, this.playgroundConfig)?.then(() => dragSuccess);\n }\n\n /**\n * 通过拖入卡片添加\n * @param type\n * @param event\n * @param data 节点数据\n */\n async dropCard(\n type: string,\n event: { clientX: number; clientY: number },\n data?: Partial<WorkflowNodeJSON>,\n parent?: WorkflowNodeEntity\n ): Promise<WorkflowNodeEntity | undefined> {\n const mousePos = this.playgroundConfig.getPosFromMouseEvent(event);\n if (!this.playgroundConfig.getViewport().contains(mousePos.x, mousePos.y)) {\n // 鼠标范围不在画布之内\n return;\n }\n const position = this.adjustSubNodePosition(type, parent, mousePos);\n\n const node: WorkflowNodeEntity = await this.document.createWorkflowNodeByType(\n type,\n position,\n data,\n parent?.id\n );\n return node;\n }\n\n /**\n * 拖拽卡片到画布\n * 返回创建结果\n * @param type\n * @param event\n */\n async startDragCard(\n type: string,\n event: React.MouseEvent,\n data: Partial<WorkflowNodeJSON>,\n cloneNode?: (e: PlaygroundDragEvent) => HTMLDivElement // 创建拖拽的dom\n ): Promise<WorkflowNodeEntity | undefined> {\n let domNode: HTMLDivElement;\n let startPos: IPoint = { x: 0, y: 0 };\n const deferred = new PromiseDeferred<WorkflowNodeEntity | undefined>();\n const dragger = new PlaygroundDrag({\n onDragStart: (e) => {\n const targetNode = event.currentTarget as HTMLDivElement;\n domNode = cloneNode ? cloneNode(e) : (targetNode.cloneNode(true) as HTMLDivElement);\n const bounds = targetNode.getBoundingClientRect();\n startPos = { x: bounds.left, y: bounds.top };\n domUtils.setStyle(domNode, {\n zIndex: 1000,\n position: 'absolute',\n left: startPos.x,\n top: startPos.y,\n boxShadow: '0 6px 8px 0 rgba(28, 31, 35, .2)',\n });\n document.body.appendChild(domNode);\n this.updateDroppableTransforms();\n },\n onDrag: (e) => {\n const deltaX = e.endPos.x - e.startPos.x;\n const deltaY = e.endPos.y - e.startPos.y;\n const left = startPos.x + deltaX;\n const right = startPos.y + deltaY;\n domNode.style.left = `${left}px`;\n domNode.style.top = `${right}px`;\n // 节点类型拖拽碰撞检测\n const { x, y } = this.playgroundConfig.getPosFromMouseEvent(e);\n const draggingRect = new Rectangle(x, y, 170, 90);\n const collisionTransform = this._droppableTransforms.find((transform) => {\n const { bounds, entity } = transform;\n const padding = this.document.layout.getPadding(entity);\n const transformRect = new Rectangle(\n bounds.x + padding.left + padding.right,\n bounds.y,\n bounds.width,\n bounds.height\n );\n // 检测两个正方形是否相互碰撞\n return Rectangle.intersects(draggingRect, transformRect);\n });\n this.updateDropNode(collisionTransform?.entity);\n },\n onDragEnd: async (e) => {\n const dropNode = this._dropNode;\n const { allowDrop } = this.canDropToNode({\n dragNodeType: type,\n dropNodeType: dropNode?.flowNodeType,\n dropNode,\n });\n const dragNode = allowDrop ? await this.dropCard(type, e, data, dropNode) : undefined;\n this.clearDrop();\n if (dragNode) {\n domNode.remove();\n deferred.resolve(dragNode);\n } else {\n domNode.style.transition = 'all ease .2s';\n domNode.style.left = `${startPos.x}px`;\n domNode.style.top = `${startPos.y}px`;\n const TIMEOUT = 200;\n await delay(TIMEOUT);\n domNode.remove();\n deferred.resolve();\n }\n },\n });\n await dragger.start(event.clientX, event.clientY);\n return deferred.promise;\n }\n\n /**\n * 如果存在容器节点,且传入鼠标坐标,需要用容器的坐标减去传入的鼠标坐标\n */\n public adjustSubNodePosition(\n subNodeType?: string,\n containerNode?: WorkflowNodeEntity,\n mousePos?: IPoint\n ): IPoint {\n if (!mousePos) {\n return { x: 0, y: 0 };\n }\n if (!subNodeType || !containerNode || containerNode.flowNodeType === FlowNodeBaseType.ROOT) {\n return mousePos;\n }\n const isParentEmpty = !containerNode.children || containerNode.children.length === 0;\n const parentPadding = this.document.layout.getPadding(containerNode);\n const containerWorldTransform = containerNode.transform.transform.worldTransform;\n if (isParentEmpty) {\n // 确保空容器节点不偏移\n return {\n x: 0,\n y: parentPadding.top,\n };\n } else {\n return {\n x: mousePos.x - containerWorldTransform.tx,\n y: mousePos.y - containerWorldTransform.ty,\n };\n }\n }\n\n /**\n * 注册位置调整\n */\n public registerPosAdjuster(\n adjuster: (params: { selectedNodes: WorkflowNodeEntity[]; position: IPoint }) => IPoint\n ) {\n this.posAdjusters.add(adjuster);\n return {\n dispose: () => this.posAdjusters.delete(adjuster),\n };\n }\n\n /**\n * 判断是否可以放置节点\n */\n\n public canDropToNode(params: {\n dragNodeType?: FlowNodeType;\n dragNode?: WorkflowNodeEntity;\n dropNode?: WorkflowNodeEntity;\n dropNodeType?: FlowNodeType;\n }): {\n allowDrop: boolean;\n message?: string;\n dropNode?: WorkflowNodeEntity;\n } {\n const { canDropToNode } = this.document.options;\n const { dragNodeType, dropNode } = params;\n if (canDropToNode) {\n const result = canDropToNode(params);\n if (result) {\n return {\n allowDrop: true,\n dropNode,\n };\n }\n return {\n allowDrop: false,\n };\n }\n if (!dragNodeType) {\n return {\n allowDrop: false,\n message: 'Please select a node to drop',\n };\n }\n return {\n allowDrop: true,\n dropNode,\n };\n }\n\n /**\n * 获取拖拽偏移\n */\n private getDragPosOffset(params: {\n event: PlaygroundDragEvent;\n selectedNodes: WorkflowNodeEntity[];\n startPosition: IPoint;\n }) {\n const { event, selectedNodes, startPosition } = params;\n const { finalScale } = this.playgroundConfig;\n const mouseOffset: IPoint = {\n x: (event.endPos.x - event.startPos.x) / finalScale,\n y: (event.endPos.y - event.startPos.y) / finalScale,\n };\n const wholePosition: IPoint = {\n x: startPosition.x + mouseOffset.x,\n y: startPosition.y + mouseOffset.y,\n };\n const adjustedOffsets: IPoint[] = Array.from(this.posAdjusters.values()).map((adjuster) =>\n adjuster({\n selectedNodes,\n position: wholePosition,\n })\n );\n const offset: IPoint = adjustedOffsets.reduce(\n (offset, adjustOffset) => ({\n x: offset.x + adjustOffset.x,\n y: offset.y + adjustOffset.y,\n }),\n mouseOffset\n );\n return offset;\n }\n\n private updateDroppableTransforms() {\n this._droppableTransforms = this.document\n .getRenderDatas(FlowNodeTransformData, false)\n .filter((transform) => {\n const { entity } = transform;\n if (entity.originParent) {\n return this.nodeSelectable(entity) && this.nodeSelectable(entity.originParent);\n }\n return this.nodeSelectable(entity);\n })\n .filter((transform) => this.isContainer(transform.entity));\n }\n\n /** 是否容器节点 */\n private isContainer(node?: WorkflowNodeEntity): boolean {\n return node?.getNodeMeta<WorkflowNodeMeta>().isContainer ?? false;\n }\n\n /**\n * 获取节点整体位置\n */\n private getNodesPosition(nodes: WorkflowNodeEntity[]): IPoint {\n const selectedBounds = Rectangle.enlarge(\n nodes.map((n) => n.getData(FlowNodeTransformData)!.bounds)\n );\n const position: IPoint = {\n x: selectedBounds.x,\n y: selectedBounds.y,\n };\n return position;\n }\n\n private nodeSelectable(node: FlowNodeEntity) {\n const selectable = node.getNodeMeta().selectable;\n if (typeof selectable === 'function') {\n return selectable(node);\n } else {\n return selectable;\n }\n }\n\n private updateDropNode(node?: FlowNodeEntity) {\n if (this._dropNode) {\n if (this._dropNode.id === node?.id) {\n return;\n }\n this.selectService.clear();\n }\n if (node) {\n this.selectService.selectNode(node);\n }\n this._dropNode = node;\n }\n\n private clearDrop() {\n if (this._dropNode) {\n this.selectService.clear();\n }\n this._dropNode = undefined;\n this._droppableTransforms = [];\n }\n\n private setLineColor(line: WorkflowLineEntity, color: string) {\n line.highlightColor = color;\n this.hoverService.clearHovered();\n }\n\n private handleDragOnNode(\n toNode: WorkflowNodeEntity,\n fromPort: WorkflowPortEntity,\n line: WorkflowLineEntity,\n toPort?: WorkflowPortEntity,\n originLine?: WorkflowLineEntity\n ): {\n hasError: boolean;\n } {\n if (\n toPort &&\n (originLine?.toPort === toPort ||\n (toPort.portType === 'input' && this.linesManager.canAddLine(fromPort, toPort, true)))\n ) {\n // 同一条线条则不用在判断 canAddLine\n this.hoverService.updateHoveredKey(toPort.id);\n line.setToPort(toPort);\n this._onDragLineEventEmitter.fire({\n type: 'onDrag',\n onDragNodeId: toNode.id,\n });\n return {\n hasError: false,\n };\n } else if (this.isContainer(toNode)) {\n // 在容器内进行连线的情况,需忽略\n return {\n hasError: false,\n };\n } else {\n this.setLineColor(line, this.linesManager.lineColor.error);\n return {\n hasError: true,\n };\n }\n }\n\n private childrenOfContainer(nodes: WorkflowNodeEntity[]): WorkflowNodeEntity | undefined {\n if (nodes.length === 0) {\n return;\n }\n const sourceContainer = nodes[0]?.parent;\n if (!sourceContainer || sourceContainer.collapsedChildren.length !== nodes.length) {\n return;\n }\n const valid = nodes.every((node) => node?.parent === sourceContainer);\n if (!valid) {\n return;\n }\n return sourceContainer;\n }\n\n /**\n * 绘制线条\n * @param opts\n * @param event\n */\n async startDrawingLine(\n fromPort: WorkflowPortEntity,\n event: { clientX: number; clientY: number },\n originLine?: WorkflowLineEntity\n ): Promise<{\n dragSuccess?: boolean; // 是否拖拽成功,不成功则为选择节点\n newLine?: WorkflowLineEntity; // 新的线条\n }> {\n const isFromInActivePort = !originLine && fromPort.isErrorPort() && fromPort.disabled;\n if (\n originLine?.disabled ||\n isFromInActivePort ||\n this.playgroundConfig.readonly ||\n this.playgroundConfig.disabled\n ) {\n return { dragSuccess: false, newLine: undefined };\n }\n\n this.selectService.clear();\n const config = this.playgroundConfig;\n const deferred = new PromiseDeferred<{\n dragSuccess?: boolean;\n newLine?: WorkflowLineEntity; // 新的线条\n }>();\n const preCursor = config.cursor;\n let line: WorkflowLineEntity | undefined,\n toPort: WorkflowPortEntity | undefined,\n toNode: WorkflowNodeEntity | undefined,\n lineErrorReset = false;\n const startTime = Date.now();\n let dragSuccess = false;\n const dragger = new PlaygroundDrag({\n onDrag: (e) => {\n if (!line && checkDragSuccess(Date.now() - startTime, e, originLine)) {\n // 隐藏原来的线条\n if (originLine) {\n originLine.highlightColor = this.linesManager.lineColor.hidden;\n }\n dragSuccess = true;\n const pos = config.getPosFromMouseEvent(event);\n // 创建临时的线条\n line = this.linesManager.createLine({\n from: fromPort.node.id,\n fromPort: fromPort.portID,\n data: originLine?.lineData,\n drawingTo: {\n x: pos.x,\n y: pos.y,\n location: fromPort.location === 'right' ? 'left' : 'top',\n },\n });\n if (!line) {\n return;\n }\n config.updateCursor('grab');\n line.highlightColor = originLine?.lockedColor || this.linesManager.lineColor.drawing;\n this.hoverService.updateHoveredKey('');\n }\n if (!line) {\n return;\n }\n\n lineErrorReset = false;\n\n const dragPos = config.getPosFromMouseEvent(e);\n\n // 默认 toNode 获取\n toNode = this.linesManager.getNodeFromMousePos(dragPos);\n // 默认 toPort 获取\n toPort = this.linesManager.getPortFromMousePos(dragPos);\n\n if (!toPort) {\n line.setToPort(undefined);\n } else if (!this.linesManager.canAddLine(fromPort, toPort, true)) {\n line.highlightColor = this.linesManager.lineColor.error;\n lineErrorReset = true;\n line.setToPort(undefined);\n } else {\n line.setToPort(toPort);\n }\n\n this._onDragLineEventEmitter.fire({\n type: 'onDrag',\n });\n\n this.setLineColor(line, originLine?.lockedColor || this.linesManager.lineColor.drawing);\n if (toNode && this.canBuildContainerLine(toNode, dragPos)) {\n // 如果鼠标 hover 在 node 中的时候,默认连线到这个 node 的初始位置\n toPort = this.getNearestPort(toNode, dragPos);\n const { hasError } = this.handleDragOnNode(toNode, fromPort, line, toPort, originLine);\n lineErrorReset = hasError;\n }\n\n if (line.toPort) {\n line.drawingTo = {\n x: line.toPort.point.x,\n y: line.toPort.point.y,\n location: line.toPort.location,\n };\n } else {\n line.drawingTo = {\n x: dragPos.x,\n y: dragPos.y,\n location: reverseLocation(line.fromPort.location),\n };\n }\n\n // 触发原 toPort 的校验\n originLine?.validate();\n line.validate();\n },\n // eslint-disable-next-line complexity\n onDragEnd: async (e) => {\n const dragPos = config.getPosFromMouseEvent(e);\n const onDragLineEndCallbacks = Array.from(this._onDragLineEndCallbacks.values());\n config.updateCursor(preCursor);\n await Promise.all(\n onDragLineEndCallbacks.map((callback) =>\n callback({\n fromPort,\n toPort,\n mousePos: dragPos,\n line,\n originLine,\n event: e,\n })\n )\n );\n line?.dispose();\n this._onDragLineEventEmitter.fire({\n type: 'onDragEnd',\n });\n // 清除选中状态\n if (originLine) {\n originLine.highlightColor = '';\n }\n const end = () => {\n originLine?.validate();\n deferred.resolve({ dragSuccess });\n };\n if (dragSuccess) {\n // Step 1: check same line\n if (originLine && originLine.toPort === toPort) {\n // 线条没变化则直接返回,不做处理\n return end();\n }\n // 非 input 节点不能连接\n if (toPort && toPort.portType !== 'input') {\n return end();\n }\n const newLineInfo: Required<WorkflowLinePortInfo> | undefined = toPort\n ? {\n from: fromPort.node.id,\n fromPort: fromPort.portID,\n to: toPort.node.id,\n toPort: toPort.portID,\n data: originLine?.lineData,\n }\n : undefined;\n // Step2: 检测 reset\n const isReset = originLine && toPort;\n if (\n isReset &&\n !this.linesManager.canReset(\n originLine.fromPort,\n originLine.toPort as WorkflowPortEntity,\n toPort as WorkflowPortEntity\n )\n ) {\n return end();\n }\n // Step 3: delete line\n if (\n originLine &&\n (!this.linesManager.canRemove(originLine, newLineInfo, false) || lineErrorReset)\n ) {\n // 线条无法删除则返回,不再触发 canAddLine\n return end();\n } else {\n originLine?.dispose();\n }\n // Step 4: add line\n if (!toPort || !this.linesManager.canAddLine(fromPort, toPort, false)) {\n // 无法添加成功\n return end();\n }\n const newLine = this.linesManager.createLine(newLineInfo as WorkflowLinePortInfo);\n if (!newLine) {\n end();\n }\n deferred.resolve({\n dragSuccess,\n newLine,\n });\n } else {\n end();\n }\n },\n });\n const { clientX, clientY } = MouseTouchEvent.getEventCoord(event);\n await dragger.start(clientX, clientY, config);\n return deferred.promise;\n }\n\n /**\n * 重新连接线条\n * @param line\n * @param e\n */\n async resetLine(line: WorkflowLineEntity, e: MouseEvent): Promise<void> {\n const { fromPort } = line;\n const { dragSuccess } = await this.startDrawingLine(fromPort, e, line);\n if (!dragSuccess) {\n // 没有拖拽成功则表示为选中节点\n this.selectService.select(line);\n }\n }\n\n /** 线条拖拽结束 */\n public onDragLineEnd(callback: OnDragLineEnd): Disposable {\n const id = nanoid();\n this._onDragLineEndCallbacks.set(id, callback);\n return {\n dispose: () => {\n this._onDragLineEndCallbacks.delete(id);\n },\n };\n }\n\n /** 能否建立容器连线 */\n private canBuildContainerLine(node: WorkflowNodeEntity, mousePos: IPoint): boolean {\n const isContainer = this.isContainer(node);\n if (!isContainer) {\n return true;\n }\n const { padding, bounds } = node.transform;\n const contentRect = new Rectangle(bounds.x, bounds.y, (padding.left * 2) / 3, bounds.height);\n return contentRect.contains(mousePos.x, mousePos.y);\n }\n\n /** 获取最近的 port */\n private getNearestPort(node: WorkflowNodeEntity, mousePos: IPoint): WorkflowPortEntity {\n const portsData = node.getData(WorkflowNodePortsData)!;\n const distanceSortedPorts = portsData.inputPorts.sort((a, b) => {\n const aDistance = Math.abs(mousePos.y - a.point.y);\n const bDistance = Math.abs(mousePos.y - b.point.y);\n return aDistance - bDistance;\n });\n return distanceSortedPorts[0];\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { last } from 'lodash-es';\nimport { inject, injectable } from 'inversify';\nimport { DisposableCollection, Emitter, type IPoint } from '@flowgram.ai/utils';\nimport { FlowNodeRenderData, FlowNodeTransformData } from '@flowgram.ai/document';\nimport { EntityManager, PlaygroundConfigEntity } from '@flowgram.ai/core';\n\nimport { WorkflowDocumentOptions } from './workflow-document-option';\nimport { type WorkflowDocument } from './workflow-document';\nimport {\n LineColor,\n LineColors,\n LinePoint,\n LineRenderType,\n LineType,\n type WorkflowLineRenderContributionFactory,\n} from './typings/workflow-line';\nimport {\n type WorkflowContentChangeEvent,\n WorkflowContentChangeType,\n type WorkflowEdgeJSON,\n WorkflowNodeRegistry,\n} from './typings';\nimport { WorkflowHoverService, WorkflowSelectService } from './service';\nimport { WorkflowNodeLinesData } from './entity-datas/workflow-node-lines-data';\nimport { WorkflowLineRenderData, WorkflowNodePortsData } from './entity-datas';\nimport {\n LINE_HOVER_DISTANCE,\n WorkflowLineEntity,\n type WorkflowLinePortInfo,\n type WorkflowNodeEntity,\n WorkflowPortEntity,\n} from './entities';\n\n/**\n * 线条管理\n */\n@injectable()\nexport class WorkflowLinesManager {\n protected document: WorkflowDocument;\n\n protected toDispose = new DisposableCollection();\n // 线条类型\n\n protected _lineType: LineRenderType = LineType.BEZIER;\n\n protected onAvailableLinesChangeEmitter = new Emitter<WorkflowContentChangeEvent>();\n\n protected onForceUpdateEmitter = new Emitter<void>();\n\n @inject(WorkflowHoverService) hoverService: WorkflowHoverService;\n\n @inject(WorkflowSelectService) selectService: WorkflowSelectService;\n\n @inject(EntityManager) protected readonly entityManager: EntityManager;\n\n @inject(WorkflowDocumentOptions)\n readonly options: WorkflowDocumentOptions;\n\n /**\n * 有效的线条被添加或者删除时候触发,未连上的线条不算\n */\n readonly onAvailableLinesChange = this.onAvailableLinesChangeEmitter.event;\n\n /**\n * 强制渲染 lines\n */\n readonly onForceUpdate = this.onForceUpdateEmitter.event;\n\n readonly contributionFactories: WorkflowLineRenderContributionFactory[] = [];\n\n init(doc: WorkflowDocument): void {\n this.document = doc;\n }\n\n forceUpdate() {\n this.onForceUpdateEmitter.fire();\n }\n\n get lineType() {\n return this._lineType;\n }\n\n get lineColor(): LineColor {\n const color: LineColor = {\n default: LineColors.DEFUALT,\n error: LineColors.ERROR,\n hidden: LineColors.HIDDEN,\n drawing: LineColors.DRAWING,\n hovered: LineColors.HOVER,\n selected: LineColors.SELECTED,\n flowing: LineColors.FLOWING,\n };\n if (this.options.lineColor) {\n Object.assign(color, this.options.lineColor);\n }\n return color;\n }\n\n switchLineType(newType?: LineRenderType): LineRenderType {\n if (newType === undefined) {\n if (this._lineType === LineType.BEZIER) {\n newType = LineType.LINE_CHART;\n } else {\n newType = LineType.BEZIER;\n }\n }\n if (newType !== this._lineType) {\n this._lineType = newType;\n // 更新线条数据\n this.getAllLines().forEach((line) => {\n line.getData(WorkflowLineRenderData).update();\n });\n window.requestAnimationFrame(() => {\n // 触发线条重渲染\n this.entityManager.fireEntityChanged(WorkflowLineEntity.type);\n });\n }\n return this._lineType;\n }\n\n getAllLines(): WorkflowLineEntity[] {\n return this.entityManager.getEntities(WorkflowLineEntity);\n }\n\n hasLine(portInfo: Omit<WorkflowLinePortInfo, 'data'>): boolean {\n return !!this.entityManager.getEntityById<WorkflowLineEntity>(\n WorkflowLineEntity.portInfoToLineId(portInfo)\n );\n }\n\n getLine(portInfo: Omit<WorkflowLinePortInfo, 'data'>): WorkflowLineEntity | undefined {\n return this.entityManager.getEntityById<WorkflowLineEntity>(\n WorkflowLineEntity.portInfoToLineId(portInfo)\n );\n }\n\n getLineById(id: string): WorkflowLineEntity | undefined {\n return this.entityManager.getEntityById<WorkflowLineEntity>(id);\n }\n\n replaceLine(\n oldPortInfo: Omit<WorkflowLinePortInfo, 'data'>,\n newPortInfo: Omit<WorkflowLinePortInfo, 'data'>\n ): WorkflowLineEntity {\n const oldLine = this.getLine(oldPortInfo);\n if (oldLine) {\n oldLine.dispose();\n }\n return this.createLine(newPortInfo)!;\n }\n\n createLine(\n options: {\n drawingTo?: LinePoint; // 无连接的线条\n key?: string; // 自定义 key\n } & WorkflowLinePortInfo\n ): WorkflowLineEntity | undefined {\n const { from, to, drawingTo, fromPort, toPort, data } = options;\n const available = Boolean(from && to);\n const key = options.key || WorkflowLineEntity.portInfoToLineId(options);\n let line = this.entityManager.getEntityById<WorkflowLineEntity>(key)!;\n if (line) {\n // 如果之前有线条,则先把颜色去掉\n line.highlightColor = '';\n line.validate();\n return line;\n }\n\n const fromNode = this.entityManager\n .getEntityById<WorkflowNodeEntity>(from)\n ?.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData);\n const toNode = to\n ? this.entityManager\n .getEntityById<WorkflowNodeEntity>(to)!\n .getData<WorkflowNodeLinesData>(WorkflowNodeLinesData)!\n : undefined;\n\n if (!fromNode) {\n // 非法情况\n return;\n }\n\n this.isDrawing = Boolean(drawingTo);\n line = this.entityManager.createEntity<WorkflowLineEntity>(WorkflowLineEntity, {\n id: key,\n document: this.document,\n linesManager: this,\n from,\n fromPort,\n toPort,\n to,\n drawingTo,\n data,\n });\n\n this.registerData(line);\n\n fromNode.addLine(line);\n toNode?.addLine(line);\n line.onDispose(() => {\n if (drawingTo) {\n this.isDrawing = false;\n }\n fromNode.removeLine(line);\n toNode?.removeLine(line);\n });\n line.onDispose(() => {\n if (available) {\n this.onAvailableLinesChangeEmitter.fire({\n type: WorkflowContentChangeType.DELETE_LINE,\n toJSON: () => line.toJSON(),\n entity: line,\n });\n }\n });\n line.onLineDataChange(({ oldValue }) => {\n this.onAvailableLinesChangeEmitter.fire({\n type: WorkflowContentChangeType.LINE_DATA_CHANGE,\n toJSON: () => line.toJSON(),\n oldValue,\n entity: line,\n });\n });\n // 是否为有效的线条\n if (available) {\n this.onAvailableLinesChangeEmitter.fire({\n type: WorkflowContentChangeType.ADD_LINE,\n toJSON: () => line.toJSON(),\n entity: line,\n });\n }\n // 创建时检验 连线错误态 & 端口错误态\n line.validate();\n return line;\n }\n\n /**\n * 获取线条中距离鼠标位置最近的线条和距离\n * @param mousePos 鼠标位置\n * @param minDistance 最小检测距离\n * @returns 距离鼠标位置最近的线条 以及距离\n */\n getCloseInLineFromMousePos(\n mousePos: IPoint,\n minDistance: number = LINE_HOVER_DISTANCE\n ): WorkflowLineEntity | undefined {\n let targetLine: WorkflowLineEntity | undefined, targetLineDist: number | undefined;\n this.getAllLines().forEach((line) => {\n const dist = line.getHoverDist(mousePos);\n\n if (dist <= minDistance && (!targetLineDist || targetLineDist >= dist)) {\n targetLineDist = dist;\n targetLine = line;\n }\n });\n return targetLine;\n }\n\n /**\n * 是否在调整线条\n */\n isDrawing = false;\n\n dispose(): void {\n this.toDispose.dispose();\n }\n\n get disposed(): boolean {\n return this.toDispose.disposed;\n }\n\n isErrorLine(fromPort: WorkflowPortEntity, toPort?: WorkflowPortEntity, defaultValue?: boolean) {\n if (this.options.isErrorLine) {\n return this.options.isErrorLine(fromPort, toPort, this);\n }\n\n return !!defaultValue;\n }\n\n isReverseLine(line: WorkflowLineEntity, defaultValue = false): boolean {\n if (this.options.isReverseLine) {\n return this.options.isReverseLine(line);\n }\n\n return defaultValue;\n }\n\n isHideArrowLine(line: WorkflowLineEntity, defaultValue = false): boolean {\n if (this.options.isHideArrowLine) {\n return this.options.isHideArrowLine(line);\n }\n\n return defaultValue;\n }\n\n isFlowingLine(line: WorkflowLineEntity, defaultValue = false): boolean {\n if (this.options.isFlowingLine) {\n return this.options.isFlowingLine(line);\n }\n\n return defaultValue;\n }\n\n isDisabledLine(line: WorkflowLineEntity, defaultValue = false): boolean {\n if (this.options.isDisabledLine) {\n return this.options.isDisabledLine(line);\n }\n return defaultValue;\n }\n\n setLineRenderType(line: WorkflowLineEntity): LineRenderType | undefined {\n if (this.options.setLineRenderType) {\n return this.options.setLineRenderType(line);\n }\n return undefined;\n }\n\n setLineClassName(line: WorkflowLineEntity): string | undefined {\n if (this.options.setLineClassName) {\n return this.options.setLineClassName(line);\n }\n return undefined;\n }\n\n getLineColor(line: WorkflowLineEntity): string | undefined {\n // 隐藏的优先级比 hasError 高\n if (line.isHidden) {\n return this.lineColor.hidden;\n }\n // 颜色锁定\n if (line.lockedColor) {\n return line.lockedColor;\n }\n if (line.hasError) {\n return this.lineColor.error;\n }\n if (line.highlightColor) {\n return line.highlightColor;\n }\n if (line.drawingTo) {\n return this.lineColor.drawing;\n }\n if (this.hoverService.isHovered(line.id)) {\n return this.lineColor.hovered;\n }\n if (this.selectService.isSelected(line.id)) {\n return this.lineColor.selected;\n }\n // 检查是否为流动线条\n if (this.isFlowingLine(line)) {\n return this.lineColor.flowing;\n }\n return this.lineColor.default;\n }\n\n canAddLine(fromPort: WorkflowPortEntity, toPort: WorkflowPortEntity, silent?: boolean): boolean {\n if (\n fromPort === toPort ||\n fromPort.node === toPort.node ||\n fromPort.portType !== 'output' ||\n toPort.portType !== 'input' ||\n toPort.disabled\n ) {\n return false;\n }\n const fromCanAdd = fromPort.node.getNodeRegistry<WorkflowNodeRegistry>().canAddLine;\n const toCanAdd = toPort.node.getNodeRegistry<WorkflowNodeRegistry>().canAddLine;\n if (fromCanAdd && !fromCanAdd(fromPort, toPort, this, silent)) {\n return false;\n }\n if (toCanAdd && !toCanAdd(fromPort, toPort, this, silent)) {\n return false;\n }\n if (this.options.canAddLine) {\n return this.options.canAddLine(fromPort, toPort, this, silent);\n }\n // 默认不能连接自己\n return fromPort.node !== toPort.node;\n }\n\n toJSON(): WorkflowEdgeJSON[] {\n return this.getAllLines()\n .filter((l) => !l.isDrawing)\n .map((l) => l.toJSON());\n }\n\n getPortById(portId: string): WorkflowPortEntity | undefined {\n return this.entityManager.getEntityById<WorkflowPortEntity>(portId);\n }\n\n canRemove(\n line: WorkflowLineEntity,\n newLineInfo?: Required<Omit<WorkflowLinePortInfo, 'data'>>,\n silent?: boolean\n ): boolean {\n if (\n this.options &&\n this.options.canDeleteLine &&\n !this.options.canDeleteLine(line, newLineInfo, silent)\n ) {\n return false;\n }\n return true;\n }\n\n canReset(\n fromPort: WorkflowPortEntity,\n oldToPort: WorkflowPortEntity,\n newToPort: WorkflowPortEntity\n ): boolean {\n if (\n this.options &&\n this.options.canResetLine &&\n !this.options.canResetLine(fromPort, oldToPort, newToPort, this)\n ) {\n return false;\n }\n return true;\n }\n\n /**\n * 根据鼠标位置找到 port\n * @param pos\n */\n getPortFromMousePos(pos: IPoint): WorkflowPortEntity | undefined {\n const allNodes = this.getSortedNodes().reverse();\n const allPorts = allNodes.map((node) => node.getData(WorkflowNodePortsData).allPorts).flat();\n const targetPort = allPorts.find((port) => port.isHovered(pos.x, pos.y));\n if (targetPort) {\n const containNodes = this.getContainNodesFromMousePos(pos);\n const targetNode = last(containNodes);\n // 点位可能会被节点覆盖\n if (targetNode && targetNode !== targetPort.node) {\n return;\n }\n }\n return targetPort;\n }\n\n /**\n * 根据鼠标位置找到 node\n * @param pos - 鼠标位置\n */\n getNodeFromMousePos(pos: IPoint): WorkflowNodeEntity | undefined {\n // 先挑选出 bounds 区域符合的 node\n const { selection } = this.selectService;\n const containNodes = this.getContainNodesFromMousePos(pos);\n // 当有元素被选中的时候选中元素在顶层\n if (selection?.length) {\n const filteredNodes = containNodes.filter((node) =>\n selection.some((_node) => node.id === _node.id)\n );\n if (filteredNodes?.length) {\n return last(filteredNodes);\n }\n }\n // 默认取最顶层的\n return last(containNodes);\n }\n\n registerContribution(factory: WorkflowLineRenderContributionFactory): this {\n this.contributionFactories.push(factory);\n return this;\n }\n\n private registerData(line: WorkflowLineEntity) {\n line.addData(WorkflowLineRenderData);\n }\n\n private getSortedNodes() {\n return this.document.getAllNodes().sort((a, b) => this.getNodeIndex(a) - this.getNodeIndex(b));\n }\n\n /** 获取鼠标坐标位置的所有节点(stackIndex 从小到大排序) */\n private getContainNodesFromMousePos(pos: IPoint): WorkflowNodeEntity[] {\n const allNodes = this.getSortedNodes();\n const zoom =\n this.entityManager.getEntity<PlaygroundConfigEntity>(PlaygroundConfigEntity)?.config?.zoom ||\n 1;\n const containNodes = allNodes\n .map((node) => {\n const { bounds } = node.getData<FlowNodeTransformData>(FlowNodeTransformData);\n // 交互要求,节点边缘 4px 的时候就认为选中节点\n if (\n bounds\n .clone()\n .pad(4 / zoom)\n .contains(pos.x, pos.y)\n ) {\n return node;\n }\n })\n .filter(Boolean) as WorkflowNodeEntity[];\n return containNodes;\n }\n\n private getNodeIndex(node: WorkflowNodeEntity): number {\n const nodeRenderData = node.getData(FlowNodeRenderData);\n return nodeRenderData.stackIndex;\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { FlowNodeErrorData } from '@flowgram.ai/form-core';\nimport { FlowDocumentOptions, FlowNodeTransformData, FlowNodeType } from '@flowgram.ai/document';\nimport { TransformData } from '@flowgram.ai/core';\n\nimport { type WorkflowLinesManager } from './workflow-lines-manager';\nimport { initFormDataFromJSON, toFormJSON } from './utils/flow-node-form-data';\nimport {\n LineColor,\n LineRenderType,\n onDragLineEndParams,\n WorkflowNodeJSON,\n WorkflowNodeMeta,\n} from './typings';\nimport {\n type WorkflowLineEntity,\n type WorkflowLinePortInfo,\n type WorkflowNodeEntity,\n type WorkflowPortEntity,\n} from './entities';\n\nexport const WorkflowDocumentOptions = Symbol('WorkflowDocumentOptions');\n\n/**\n * 线条配置\n */\nexport interface WorkflowDocumentOptions extends FlowDocumentOptions {\n cursors?: {\n grab?: string;\n grabbing?: string;\n };\n /** 线条颜色 */\n lineColor?: Partial<LineColor>;\n /** 是否显示错误线条 */\n isErrorLine?: (\n fromPort: WorkflowPortEntity,\n toPort: WorkflowPortEntity | undefined,\n lines: WorkflowLinesManager\n ) => boolean;\n /** 是否错误端口 */\n isErrorPort?: (port: WorkflowPortEntity) => boolean;\n /** 是否禁用端口 */\n isDisabledPort?: (port: WorkflowPortEntity) => boolean;\n /** 是否反转线条箭头 */\n isReverseLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否隐藏线条箭头 */\n isHideArrowLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否流动线条 */\n isFlowingLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否禁用线条 */\n isDisabledLine?: (line: WorkflowLineEntity) => boolean;\n /** 拖拽线条结束 */\n onDragLineEnd?: (params: onDragLineEndParams) => Promise<void>;\n /** 获取线条渲染器 */\n setLineRenderType?: (line: WorkflowLineEntity) => LineRenderType | undefined;\n /** 设置线条样式 */\n setLineClassName?: (line: WorkflowLineEntity) => string | undefined;\n /** 能否添加线条 */\n canAddLine?: (\n fromPort: WorkflowPortEntity,\n toPort: WorkflowPortEntity,\n lines: WorkflowLinesManager,\n silent?: boolean\n ) => boolean;\n /** 能否删除节点 */\n canDeleteNode?: (node: WorkflowNodeEntity, silent?: boolean) => boolean;\n /** 能否删除线条 */\n canDeleteLine?: (\n line: WorkflowLineEntity,\n newLineInfo?: Required<Omit<WorkflowLinePortInfo, 'data'>>,\n silent?: boolean\n ) => boolean;\n /**\n * @param fromPort - 开始点\n * @param oldToPort - 旧的连接点\n * @param newToPort - 新的连接点\n * @param lines - 线条管理器\n */\n canResetLine?: (\n fromPort: WorkflowPortEntity,\n oldToPort: WorkflowPortEntity,\n newToPort: WorkflowPortEntity,\n lines: WorkflowLinesManager\n ) => boolean;\n /**\n * 是否允许拖入子画布 (loop or group)\n * Whether to allow dragging into the sub-canvas (loop or group)\n * @param params\n */\n canDropToNode?: (params: {\n dragNodeType?: FlowNodeType;\n dragNode?: WorkflowNodeEntity;\n dropNode?: WorkflowNodeEntity;\n dropNodeType?: FlowNodeType;\n }) => boolean;\n}\n\nexport const WorkflowDocumentOptionsDefault: WorkflowDocumentOptions = {\n cursors: {\n grab: 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMCAyMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC40ODczIDIuNjIzNzhDOS45MDczMSAyLjYyMzc4IDkuNDM3MTMgMy4wOTM5NiA5LjQzNzEzIDMuNjczOTZWNS4xNDM3NkM5LjM5NDI4IDQuNDAyNzQgOC43Nzk3OCAzLjgxNTA0IDguMDI4MDIgMy44MTUwNEM3LjI0ODQ4IDMuODE1MDQgNi42MTY1MyA0LjQ0Njk5IDYuNjE2NTMgNS4yMjY1M1YxMS44Mjg5TDUuNjc0MTggMTEuMDA0OUM1LjE1NDg3IDEwLjU1MDkgNC40MDk1IDEwLjQ2MzYgMy43OTkzOCAxMC43ODU1TDMuNjk2OTQgMTAuODM5NkMzLjA2MjE3IDExLjE3NDUgMi45MjI2IDEyLjAyMjggMy40MTY2MiAxMi41NDM0TDcuMzM5NTkgMTYuNjc3NVYxNy4zMjU5QzcuMzM5NTkgMTcuNzg2MiA3LjcxMjY5IDE4LjE1OTMgOC4xNzI5MiAxOC4xNTkzSDEzLjgwODRDMTQuMjY4NyAxOC4xNTkzIDE0LjY0MTcgMTcuNzg2MiAxNC42NDE3IDE3LjMyNTlWMTYuNzkzNUMxNS44MDk0IDE1LjY0ODUgMTYuNDY3MyAxNC4wODE5IDE2LjQ2NzMgMTIuNDQ2NVYxMS40OTY3TDE2LjQ2NzEgNi42MzY4NUMxNi40NjcxIDUuOTU2MyAxNS45MTU0IDUuNDA0NjEgMTUuMjM0OCA1LjQwNDYxQzE0LjU1NDMgNS40MDQ2MSAxNC4wMDI2IDUuOTU2MyAxNC4wMDI2IDYuNjM2ODVMMTQuMDAyMSA1LjA0NzI4QzE0LjAwMjEgNC4zNjY3MyAxMy40NTA0IDMuODE1MDQgMTIuNzY5OCAzLjgxNTA0QzEyLjA4OTMgMy44MTUwNCAxMS41Mzc2IDQuMzY2NzMgMTEuNTM3NiA1LjA0NzI4TDExLjUzNzUgMy42NzM5NUMxMS41Mzc1IDMuMDkzOTYgMTEuMDY3MyAyLjYyMzc4IDEwLjQ4NzMgMi42MjM3OFoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAuNDg3NCAxLjM3NDAyQzExLjM2MTIgMS4zNzQwMiAxMi4xMjExIDEuODYxMTggMTIuNTEwNSAyLjU3ODY4QzEyLjU5NTggMi41Njk4MyAxMi42ODIzIDIuNTY1MjggMTIuNzcgMi41NjUyOEMxMy44Mjc4IDIuNTY1MjggMTQuNzMxMSAzLjIyNzAxIDE1LjA4ODUgNC4xNTkxMUMxNS4xMzcgNC4xNTYyOSAxNS4xODU4IDQuMTU0ODYgMTUuMjM1IDQuMTU0ODZDMTYuNjA1OSA0LjE1NDg2IDE3LjcxNzIgNS4yNjYxOSAxNy43MTcyIDYuNjM3MDlMMTcuNzE3NCAxMi40NDY3QzE3LjcxNzQgMTQuMjM1NSAxNy4wNjQ0IDE1Ljk1NTkgMTUuODkxOSAxNy4yOTA0VjE3LjMyNjJDMTUuODkxOSAxOC40NzY4IDE0Ljk1OTEgMTkuNDA5NSAxMy44MDg1IDE5LjQwOTVIOC4xNzMwNkM3LjAyMjQ3IDE5LjQwOTUgNi4wODk3MyAxOC40NzY4IDYuMDg5NzMgMTcuMzI2MlYxNy4xNzY0TDIuNTEwMDMgMTMuNDA0MUMxLjQ0NTk5IDEyLjI4MjggMS43NDY2IDEwLjQ1NTUgMy4xMTM3OSA5LjczNDI0TDMuMjE2MjQgOS42ODAxOUMzLjg5MTY4IDkuMzIzODMgNC42NjE4NSA5LjI1NDAxIDUuMzY2NjYgOS40NTE5OFY1LjIyNjc4QzUuMzY2NjYgMy43NTY4NyA2LjU1ODI2IDIuNTY1MjggOC4wMjgxNiAyLjU2NTI4QzguMTcyOTMgMi41NjUyOCA4LjMxNDk5IDIuNTc2ODQgOC40NTM0NyAyLjU5OTA3QzguODM5NDMgMS44NzA0MiA5LjYwNTQ2IDEuMzc0MDIgMTAuNDg3NCAxLjM3NDAyWk0xMi40NDc2IDMuODU3ODdWOS40NzY0NkMxMi40NDc2IDkuNzI4NTIgMTIuMjQzMyA5LjkzMjg1IDExLjk5MTMgOS45MzI4NUMxMS43MzkyIDkuOTMyODUgMTEuNTM0OSA5LjcyODUyIDExLjUzNDkgOS40NzY0NlYzLjc5NjU1QzExLjUzNDkgMy43Nzk1NiAxMS41MzU4IDMuNzYyNzcgMTEuNTM3NiAzLjc0NjI2VjMuNjc0MkMxMS41Mzc2IDMuNDMyODIgMTEuNDU2MiAzLjIxMDQ2IDExLjMxOTMgMy4wMzMwOUMxMS4xMjcyIDIuNzg0MjggMTAuODI2MSAyLjYyNDAyIDEwLjQ4NzQgMi42MjQwMkMxMC4xMjM4IDIuNjI0MDIgOS44MDMzMiAyLjgwODg2IDkuNjE0ODMgMy4wODk3QzkuNTAyNjkgMy4yNTY3OSA5LjQzNzI2IDMuNDU3ODUgOS40MzcyNiAzLjY3NDJWMy43ODU3M0M5LjQzNzM1IDMuNzg5MzMgOS40MzczOSAzLjc5Mjk0IDkuNDM3MzkgMy43OTY1NVY5LjkwMTdDOS40MzczOSAxMC4xNTM3IDkuMjMzMDYgMTAuMzU4MSA4Ljk4MTAxIDEwLjM1ODFDOC43Mjg5NSAxMC4zNTgxIDguNTI0NjIgMTAuMTUzNyA4LjUyNDYyIDkuOTAxN1YzLjkwNTA3QzguNDE3NzMgMy44NjQ5IDguMzA0NjggMy44MzczMiA4LjE4NzI2IDMuODI0MTVDOC4xMzUwNCAzLjgxODI5IDguMDgxOTUgMy44MTUyOCA4LjAyODE2IDMuODE1MjhDNy4yNDg2MSAzLjgxNTI4IDYuNjE2NjYgNC40NDcyMyA2LjYxNjY2IDUuMjI2NzhWMTEuODI5Mkw1LjY3NDMxIDExLjAwNTJDNS41Nzg2OCAxMC45MjE2IDUuNDc1MzcgMTAuODUwNCA1LjM2NjY2IDEwLjc5MTlDNC44ODUwNiAxMC41MzI5IDQuMjk3MjggMTAuNTIzMSAzLjc5OTUyIDEwLjc4NThMMy42OTcwNyAxMC44Mzk4QzMuMDYyMzEgMTEuMTc0NyAyLjkyMjczIDEyLjAyMzEgMy40MTY3NSAxMi41NDM3TDcuMzM5NzMgMTYuNjc3N1YxNy4zMjYyQzcuMzM5NzMgMTcuNzg2NCA3LjcxMjgyIDE4LjE1OTUgOC4xNzMwNiAxOC4xNTk1SDEzLjgwODVDMTQuMjY4OCAxOC4xNTk1IDE0LjY0MTkgMTcuNzg2NCAxNC42NDE5IDE3LjMyNjJWMTYuNzkzOEMxNS43Mzc5IDE1LjcxOSAxNi4zODQ3IDE0LjI3MjggMTYuNDYgMTIuNzQ3QzE2LjQ2NDEgMTIuNjY0MSAxNi40NjY1IDEyLjU4MDkgMTYuNDY3MiAxMi40OTc1TDE2LjQ2NzQgMTIuNDQ2N0wxNi40NjcyIDYuNjM3MDlDMTYuNDY3MiA1Ljk2MjMgMTUuOTI0OCA1LjQxNDE5IDE1LjI1MjIgNS40MDQ5N0wxNS4yMzUgNS40MDQ4NkMxNS4xMjQ2IDUuNDA0ODYgMTUuMDE3NyA1LjQxOTM2IDE0LjkxNTkgNS40NDY1NlY5LjYwMjI2QzE0LjkxNTkgOS44NTQzMSAxNC43MTE2IDEwLjA1ODYgMTQuNDU5NSAxMC4wNTg2QzE0LjIwNzUgMTAuMDU4NiAxNC4wMDMxIDkuODU0MzEgMTQuMDAzMSA5LjYwMjI2VjYuNjA1MTRDMTQuMDAyOSA2LjYxNTc2IDE0LjAwMjcgNi42MjY0MSAxNC4wMDI3IDYuNjM3MDlWOS4yNzcwNUwxNC4wMDIyIDUuMDQ3NTJDMTQuMDAyMiA0Ljg2OTEzIDEzLjk2NDMgNC42OTk2IDEzLjg5NjEgNC41NDY1M0MxMy43MDY0IDQuMTIwNzIgMTMuMjgyMiAzLjgyMjM1IDEyLjc4NzYgMy44MTU0MUwxMi43NyAzLjgxNTI4QzEyLjY1ODQgMy44MTUyOCAxMi41NTA0IDMuODMwMSAxMi40NDc2IDMuODU3ODdaIiBmaWxsPSIjMUQxQzIzIi8+Cjwvc3ZnPg==\"), auto',\n grabbing:\n 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMCAyMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02LjYxODE3IDUuNTk4NzVDNi42MTgxNyA0LjgxOTIgNy4yNTAxMiA0LjE4NzI2IDguMDI5NjcgNC4xODcyNkM4Ljc3ODczIDQuMTg3MjYgOS4zOTE1MiA0Ljc3MDc1IDkuNDM4MjkgNS41MDgwMUM5LjQ1OTkyIDQuOTQ3MSA5LjkyMTQ3IDQuNDk5MDIgMTAuNDg3NyA0LjQ5OTAyQzExLjA2NzcgNC40OTkwMiAxMS41Mzc4IDQuOTY5MiAxMS41Mzc4IDUuNTQ5MTlWOC43NjI0NkwxMS41Mzc5IDYuNzExNUMxMS41Mzc5IDYuMDMwOTUgMTIuMDg5NiA1LjQ3OTI2IDEyLjc3MDIgNS40NzkyNkMxMy40NTA3IDUuNDc5MjYgMTQuMDAyNCA2LjAzMDk1IDE0LjAwMjQgNi43MTE1TDE0LjAwMjQgOC43NjI0NkwxNC4wMDI5IDguMDE5ODNDMTQuMDAyOSA3LjMzOTI5IDE0LjU1NDYgNi43ODc1OSAxNS4yMzUyIDYuNzg3NTlDMTUuOTE1NyA2Ljc4NzU5IDE2LjQ2NzQgNy4zMzkyOCAxNi40Njc0IDguMDE5ODNWMTEuNDk3TDE2LjQ2NzUgMTIuNDQ2N0MxNi40Njc1IDE0LjA4MjEgMTUuODA5NiAxNS42NDg3IDE0LjY0MiAxNi43OTM4VjE3LjMyNjJDMTQuNjQyIDE3Ljc4NjQgMTQuMjY4OSAxOC4xNTk1IDEzLjgwODcgMTguMTU5NUg4LjE3MzE3QzcuNzEyOTMgMTguMTU5NSA3LjMzOTg0IDE3Ljc4NjQgNy4zMzk4NCAxNy4zMjYyVjE1Ljk0MjRMNS4zNDU2MiAxNC43NTM0QzQuNTg5MjQgMTQuMzAyNCA0LjEyNTkxIDEzLjQ4NjcgNC4xMjU4OSAxMi42MDYxTDQuMTI1ODMgOS4yODM4M0M0LjEyNTgyIDguOTU0MjcgNC4zMjAwMyA4LjY1NTY2IDQuNjIxMjkgOC41MjIwNUw2LjYxODE3IDcuNjM2MzRWNS41OTg3NVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAuNDg3OCAzLjI0OTAyQzExLjI3OTYgMy4yNDkwMiAxMS45Nzc4IDMuNjQ5MDIgMTIuMzkxNyA0LjI1Nzk2QzEyLjUxNTEgNC4yMzkwNiAxMi42NDE2IDQuMjI5MjYgMTIuNzcwMyA0LjIyOTI2QzEzLjcyMjQgNC4yMjkyNiAxNC41NDkzIDQuNzY1MzEgMTQuOTY1NyA1LjU1MjA3QzE1LjA1NDMgNS41NDI1IDE1LjE0NDIgNS41Mzc1OSAxNS4yMzUzIDUuNTM3NTlDMTYuNjA2MiA1LjUzNzU5IDE3LjcxNzYgNi42NDg5MyAxNy43MTc2IDguMDE5ODNMMTcuNzE3NyAxMi40NDY3QzE3LjcxNzcgMTQuMjM1NSAxNy4wNjQ3IDE1Ljk1NTkgMTUuODkyMSAxNy4yOTA0VjE3LjMyNjJDMTUuODkyMSAxOC40NzY4IDE0Ljk1OTQgMTkuNDA5NSAxMy44MDg4IDE5LjQwOTVIOC4xNzMzMkM3LjAyMjczIDE5LjQwOTUgNi4wODk5OCAxOC40NzY4IDYuMDg5OTggMTcuMzI2MlYxNi42NTI0TDQuNzA1NjMgMTUuODI3QzMuNTcxMDYgMTUuMTUwNSAyLjg3NjA3IDEzLjkyNzEgMi44NzYwNCAxMi42MDYxTDIuODc1OTggOS4yODM4NUMyLjg3NTk2IDguNDU5OTYgMy4zNjE0OSA3LjcxMzQ1IDQuMTE0NjIgNy4zNzk0TDUuMzY4MzIgNi44MjMzM1Y1LjU5ODc1QzUuMzY4MzIgNC4xMjg4NSA2LjU1OTkxIDIuOTM3MjYgOC4wMjk4MiAyLjkzNzI2QzguNjA4MzEgMi45MzcyNiA5LjE0MzU1IDMuMTIxNyA5LjU4MDA1IDMuNDM1MDVDOS44NTg1MyAzLjMxNTMyIDEwLjE2NTQgMy4yNDkwMiAxMC40ODc4IDMuMjQ5MDJaTTEyLjQ0NzkgNS41MjE4NlY5LjQ3NTU3QzEyLjQ0NzkgOS43Mjc2MiAxMi4yNDM2IDkuOTMxOTUgMTEuOTkxNiA5LjkzMTk1QzExLjc1NjggOS45MzE5NSAxMS41NjM0IDkuNzU0NjUgMTEuNTM4IDkuNTI2NjNDMTEuNTM2MSA5LjUwOTg3IDExLjUzNTIgOS40OTI4MyAxMS41MzUyIDkuNDc1NTdWNS40NzE1OEMxMS41MTU0IDUuMjAwODMgMTEuMzkzIDQuOTU4NTggMTEuMjA2NiA0Ljc4MzU4QzExLjAxODggNC42MDcxMSAxMC43NjU5IDQuNDk5MDIgMTAuNDg3OCA0LjQ5OTAyQzEwLjQ3NjYgNC40OTkwMiAxMC40NjU0IDQuNDk5MTkgMTAuNDU0MiA0LjQ5OTU0QzkuOTAzNDcgNC41MTY4NCA5LjQ1OTY0IDQuOTU4MjQgOS40Mzg0NCA1LjUwODAxQzkuNDM4MiA1LjUwNDMgOS40Mzc5NSA1LjUwMDU4IDkuNDM3NjkgNS40OTY4OFY5LjkwMjQzQzkuNDM3NjkgMTAuMTU0NSA5LjIzMzM2IDEwLjM1ODggOC45ODEzMSAxMC4zNTg4QzguNzI5MjUgMTAuMzU4OCA4LjUyNDkyIDEwLjE1NDUgOC41MjQ5MiA5LjkwMjQzVjQuMjc2NTNDOC4zNzA4NiA0LjIxODgyIDguMjA0MDIgNC4xODcyNiA4LjAyOTgyIDQuMTg3MjZDNy4yNTAyNyA0LjE4NzI2IDYuNjE4MzIgNC44MTkyIDYuNjE4MzIgNS41OTg3NUw2LjYxODI3IDkuOTc1OTlDNi42MTgyNyAxMC4yMjggNi40MTM5NCAxMC40MzI0IDYuMTYxODkgMTAuNDMyNEM1LjkwOTgzIDEwLjQzMjQgNS43MDU1IDEwLjIyOCA1LjcwNTUgOS45NzU5OVY4LjA0MTIyTDQuNjIxNDQgOC41MjIwNUM0LjMyMDE4IDguNjU1NjYgNC4xMjU5NyA4Ljk1NDI3IDQuMTI1OTggOS4yODM4M0w0LjEyNjA0IDEyLjYwNjFDNC4xMjYwNiAxMy40ODY3IDQuNTg5MzkgMTQuMzAyNCA1LjM0NTc2IDE0Ljc1MzRMNy4zMzk5OCAxNS45NDI0VjE3LjMyNjJDNy4zMzk5OCAxNy43ODY0IDcuNzEzMDggMTguMTU5NSA4LjE3MzMyIDE4LjE1OTVIMTMuODA4OEMxNC4yNjkgMTguMTU5NSAxNC42NDIxIDE3Ljc4NjQgMTQuNjQyMSAxNy4zMjYyVjE2Ljc5MzhDMTUuNzM4MSAxNS43MTkgMTYuMzg1IDE0LjI3MjggMTYuNDYwMyAxMi43NDdDMTYuNDY0NiAxMi42NiAxNi40NjcgMTIuNTcyOCAxNi40Njc2IDEyLjQ4NTRMMTYuNDY3NyAxMi40NDY3TDE2LjQ2NzYgOC4wMTk4M0MxNi40Njc2IDcuMzQ1MDQgMTUuOTI1MiA2Ljc5NjkzIDE1LjI1MjUgNi43ODc3MUwxNS4yMzUzIDYuNzg3NTlDMTUuMTI1IDYuNzg3NTkgMTUuMDE4IDYuODAyMSAxNC45MTYyIDYuODI5MzFWOS42MDEzNkMxNC45MTYyIDkuODUzNDIgMTQuNzExOSAxMC4wNTc3IDE0LjQ1OTggMTAuMDU3N0MxNC4yMDc4IDEwLjA1NzcgMTQuMDAzNCA5Ljg1MzQxIDE0LjAwMzQgOS42MDEzNlY3Ljk4OTg1QzE0LjAwMzIgNy45OTk4MiAxNC4wMDMxIDguMDA5ODEgMTQuMDAzMSA4LjAxOTgzTDE0LjAwMzQgOS42MDEzNkwxNC4wMDI1IDYuNzExNUMxNC4wMDI1IDYuNDQ5NzQgMTMuOTIwOSA2LjIwNzA1IDEzLjc4MTggNi4wMDc0OEMxMy41NjIgNS42OTI0MiAxMy4xOTg5IDUuNDg0ODMgMTIuNzg3IDUuNDc5MzdMMTIuNzcwMyA1LjQ3OTI2QzEyLjY1ODggNS40NzkyNiAxMi41NTA3IDUuNDk0MDggMTIuNDQ3OSA1LjUyMTg2WiIgZmlsbD0iIzFEMUMyMyIvPgo8L3N2Zz4=\"), auto',\n },\n\n fromNodeJSON(node, json, isFirstCreate) {\n initFormDataFromJSON(node, json, isFirstCreate);\n return;\n },\n toNodeJSON(node: WorkflowNodeEntity): WorkflowNodeJSON {\n const nodeError = node.getData<FlowNodeErrorData>(FlowNodeErrorData)?.getError();\n // 如果节点有错误,这里抛出错误,避免后面的代码执行异常\n if (nodeError) {\n throw nodeError;\n }\n const transform = node.getData<TransformData>(TransformData)!;\n\n let formJSON = toFormJSON(node);\n const metaData: Record<string, unknown> = {};\n\n // 持久化子画布位置\n const nodeMeta = node.getNodeMeta<WorkflowNodeMeta>();\n const subCanvas = nodeMeta.subCanvas?.(node);\n if (subCanvas?.isCanvas === false) {\n const canvasNodeTransform =\n subCanvas.canvasNode.getData<FlowNodeTransformData>(FlowNodeTransformData);\n const { x, y } = canvasNodeTransform.transform.position;\n metaData.canvasPosition = { x, y };\n }\n\n const json: WorkflowNodeJSON = {\n id: node.id,\n type: node.flowNodeType,\n meta: {\n position: { x: transform.position.x, y: transform.position.y },\n ...metaData,\n },\n data: formJSON,\n };\n return json;\n },\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { FlowNodeFormData } from '@flowgram.ai/form-core';\nimport { FlowNodeEntity, FlowNodeJSON } from '@flowgram.ai/document';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport { WorkflowContentChangeType, type WorkflowNodeRegistry } from '../typings';\n\nexport function getFlowNodeFormData(node: FlowNodeEntity) {\n return node.getData(FlowNodeFormData) as FlowNodeFormData;\n}\n\nexport function toFormJSON(node: FlowNodeEntity) {\n const formData = node.getData(FlowNodeFormData) as FlowNodeFormData;\n if (!formData || !(node.getNodeRegistry() as WorkflowNodeRegistry).formMeta) return undefined;\n return formData.toJSON();\n}\n\nexport function initFormDataFromJSON(\n node: FlowNodeEntity,\n json: FlowNodeJSON,\n isFirstCreate: boolean\n) {\n const formData = node.getData(FlowNodeFormData)!;\n const registry = node.getNodeRegistry();\n const { formMeta } = registry;\n\n if (formData && formMeta) {\n if (isFirstCreate) {\n formData.createForm(formMeta, json.data);\n formData.onDataChange(() => {\n (node.document as WorkflowDocument).fireContentChange({\n type: WorkflowContentChangeType.NODE_DATA_CHANGE,\n toJSON: () => formData.toJSON(),\n entity: node,\n });\n });\n } else {\n formData.updateFormValues(json.data);\n }\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { type WorkflowLineEntity, type WorkflowNodeEntity } from '../entities';\nimport { type WorkflowNodeJSON } from './workflow-node';\nimport { type WorkflowEdgeJSON } from './workflow-edge';\n\nexport interface WorkflowJSON {\n nodes: WorkflowNodeJSON[];\n edges: WorkflowEdgeJSON[];\n}\n\nexport enum WorkflowContentChangeType {\n /**\n * 添加节点\n */\n ADD_NODE = 'ADD_NODE',\n /**\n * 删除节点\n */\n DELETE_NODE = 'DELETE_NODE',\n /**\n * 移动节点\n */\n MOVE_NODE = 'MOVE_NODE',\n /**\n * 节点数据更新 (表单引擎数据 或者 extInfo 数据)\n */\n NODE_DATA_CHANGE = 'NODE_DATA_CHANGE',\n /**\n * 添加线条\n */\n ADD_LINE = 'ADD_LINE',\n /**\n * 删除线条\n */\n DELETE_LINE = 'DELETE_LINE',\n /**\n * 线条数据修改\n */\n LINE_DATA_CHANGE = 'LINE_DATA_CHANGE',\n /**\n * 节点Meta信息变更\n */\n META_CHANGE = 'META_CHANGE',\n}\n\nexport interface WorkflowContentChangeEvent {\n type: WorkflowContentChangeType;\n /**\n * 当前触发的元素的json数据,toJSON 需要主动触发\n */\n toJSON: () => any;\n /**\n * oldValue\n */\n oldValue?: any;\n /*\n * 当前的事件的 entity\n */\n entity: WorkflowNodeEntity | WorkflowLineEntity;\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport type { Rectangle, IPoint } from '@flowgram.ai/utils';\n\nimport { type WorkflowLineEntity } from '../entities';\n\nexport enum LineType {\n BEZIER, // 贝塞尔曲线\n LINE_CHART, // 折叠线\n STRAIGHT, // 直线\n}\n\nexport type LineRenderType = LineType | string;\n\nexport type LinePointLocation = 'left' | 'top' | 'right' | 'bottom';\n\nexport interface LinePoint {\n x: number;\n y: number;\n location: LinePointLocation;\n}\n\nexport interface LinePosition {\n from: LinePoint;\n to: LinePoint;\n}\n\nexport interface LineColor {\n hidden: string;\n default: string;\n drawing: string;\n hovered: string;\n selected: string;\n error: string;\n flowing: string;\n}\n\nexport enum LineColors {\n HIDDEN = 'var(--g-workflow-line-color-hidden,transparent)', // 隐藏线条\n DEFUALT = 'var(--g-workflow-line-color-default,#4d53e8)',\n DRAWING = 'var(--g-workflow-line-color-drawing, #5DD6E3)', // '#b5bbf8', // '#9197F1',\n HOVER = 'var(--g-workflow-line-color-hover,#37d0ff)',\n SELECTED = 'var(--g-workflow-line-color-selected,#37d0ff)',\n ERROR = 'var(--g-workflow-line-color-error,red)',\n FLOWING = 'var(--g-workflow-line-color-flowing,#4d53e8)', // 流动线条,默认使用主题色\n}\n\nexport interface LineCenterPoint {\n x: number;\n y: number;\n labelX: number; // Relative to where the line begins\n labelY: number; // Relative to where the line begins\n}\n\nexport interface WorkflowLineRenderContribution {\n entity: WorkflowLineEntity;\n path: string;\n center?: LineCenterPoint;\n bounds: Rectangle;\n update: (params: { fromPos: LinePoint; toPos: LinePoint }) => void;\n calcDistance: (pos: IPoint) => number;\n}\n\nexport type WorkflowLineRenderContributionFactory = (new (\n entity: WorkflowLineEntity\n) => WorkflowLineRenderContribution) & {\n type: LineRenderType;\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { IPoint, Event } from '@flowgram.ai/utils';\nimport {\n FlowNodeEntity,\n FlowNodeEntityOrId,\n FlowOperationBaseService,\n} from '@flowgram.ai/document';\n\nexport interface NodePostionUpdateEvent {\n node: FlowNodeEntity;\n oldPosition: IPoint;\n newPosition: IPoint;\n}\n\nexport interface WorkflowOperationBaseService extends FlowOperationBaseService {\n /**\n * 节点位置更新事件\n */\n readonly onNodePostionUpdate: Event<NodePostionUpdateEvent>;\n /**\n * 更新节点位置\n * @param nodeOrId\n * @param position\n * @returns\n */\n updateNodePosition(nodeOrId: FlowNodeEntityOrId, position: IPoint): void;\n}\n\nexport const WorkflowOperationBaseService = Symbol('WorkflowOperationBaseService');\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport * from './workflow-json';\nexport * from './workflow-edge';\nexport * from './workflow-node';\nexport * from './workflow-registry';\nexport * from './workflow-line';\nexport * from './workflow-sub-canvas';\nexport * from './workflow-operation';\nexport * from './workflow-drag';\n\nexport const URLParams = Symbol('');\n\nexport interface URLParams {\n [key: string]: string;\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { customAlphabet } from 'nanoid';\nimport { inject, injectable, optional, postConstruct } from 'inversify';\nimport { Emitter, type IPoint } from '@flowgram.ai/utils';\nimport { NodeEngineContext } from '@flowgram.ai/form-core';\nimport {\n AddNodeData,\n FlowDocument,\n FlowNodeBaseType,\n FlowNodeTransformData,\n} from '@flowgram.ai/document';\nimport {\n injectPlaygroundContext,\n PlaygroundConfigEntity,\n PlaygroundContext,\n PositionData,\n TransformData,\n} from '@flowgram.ai/core';\n\nimport { WorkflowLinesManager } from './workflow-lines-manager';\nimport {\n WorkflowDocumentOptions,\n WorkflowDocumentOptionsDefault,\n} from './workflow-document-option';\nimport { getFlowNodeFormData } from './utils/flow-node-form-data';\nimport { buildGroupJSON, delay, fitView, getAntiOverlapPosition } from './utils';\nimport {\n type WorkflowContentChangeEvent,\n WorkflowContentChangeType,\n WorkflowEdgeJSON,\n type WorkflowJSON,\n type WorkflowNodeJSON,\n type WorkflowNodeMeta,\n type WorkflowNodeRegistry,\n WorkflowSubCanvas,\n} from './typings';\nimport { WorkflowSelectService } from './service/workflow-select-service';\nimport { FREE_LAYOUT_KEY, type FreeLayout } from './layout';\nimport { WorkflowNodeLinesData } from './entity-datas';\nimport {\n WorkflowLineEntity,\n WorkflowLinePortInfo,\n WorkflowNodeEntity,\n WorkflowPortEntity,\n} from './entities';\n\nconst nanoid = customAlphabet('1234567890', 5);\n\nexport const WorkflowDocumentProvider = Symbol('WorkflowDocumentProvider');\nexport type WorkflowDocumentProvider = () => WorkflowDocument;\n\n@injectable()\nexport class WorkflowDocument extends FlowDocument {\n private _onContentChangeEmitter = new Emitter<WorkflowContentChangeEvent>();\n\n protected readonly onLoadedEmitter = new Emitter<void>();\n\n readonly onContentChange = this._onContentChangeEmitter.event;\n\n private _onReloadEmitter = new Emitter<WorkflowDocument>();\n\n readonly onReload = this._onReloadEmitter.event;\n\n /**\n * 数据加载完成\n */\n readonly onLoaded = this.onLoadedEmitter.event;\n\n protected _loading = false;\n\n @inject(WorkflowLinesManager) linesManager: WorkflowLinesManager;\n\n @inject(PlaygroundConfigEntity) playgroundConfig: PlaygroundConfigEntity;\n\n @injectPlaygroundContext() playgroundContext: PlaygroundContext;\n\n @inject(WorkflowDocumentOptions)\n options: WorkflowDocumentOptions = {};\n\n @inject(NodeEngineContext) @optional() nodeEngineContext: NodeEngineContext;\n\n @inject(WorkflowSelectService) selectServices: WorkflowSelectService;\n\n get loading(): boolean {\n return this._loading;\n }\n\n /**\n * use `ctx.tools.fitView()` instead\n * @deprecated\n * @param easing\n */\n async fitView(easing?: boolean): Promise<void> {\n return fitView(this, this.playgroundConfig, easing).then(() => {\n this.linesManager.forceUpdate();\n });\n }\n\n @postConstruct()\n init(): void {\n super.init();\n this.currentLayoutKey = this.options.defaultLayout || FREE_LAYOUT_KEY;\n this.linesManager.init(this);\n this.playgroundConfig.getCursors = () => this.options.cursors;\n this.linesManager.onAvailableLinesChange((e) => this.fireContentChange(e));\n this.playgroundConfig.onReadonlyOrDisabledChange(({ readonly }) => {\n if (this.nodeEngineContext) {\n this.nodeEngineContext.readonly = readonly;\n }\n });\n }\n\n async load(): Promise<void> {\n if (this.disposed) return;\n this._loading = true;\n await super.load();\n this._loading = false;\n this.onLoadedEmitter.fire();\n }\n\n async reload(json: WorkflowJSON, delayTime = 0): Promise<void> {\n if (this.disposed) return;\n this._loading = true;\n this.clear();\n this.fromJSON(json);\n // loading添加delay,避免reload时触发fireContentChange的副作用\n await delay(delayTime);\n this._loading = false;\n this._onReloadEmitter.fire(this);\n }\n\n /**\n * 从数据加载\n * @param json\n */\n fromJSON(json: Partial<WorkflowJSON>, fireRender = true): void {\n if (this.disposed) return;\n const workflowJSON: WorkflowJSON = {\n nodes: json.nodes ?? [],\n edges: json.edges ?? [],\n };\n // 触发画布更新\n this.entityManager.changeEntityLocked = true;\n\n // 逐层渲染\n this.renderJSON(workflowJSON);\n\n this.entityManager.changeEntityLocked = false;\n this.transformer.loading = false;\n // 批量触发画布更新\n if (fireRender) {\n this.fireRender();\n }\n }\n\n /**\n * 清空画布\n */\n clear(): void {\n this.getAllNodes().map((node) => node.dispose()); // 清空节点\n this.linesManager.getAllLines().map((line) => line.dispose()); // 清空线条\n this.getAllPorts().map((port) => port.dispose()); // 清空端口\n this.selectServices.clear(); // 清空选择\n }\n\n /**\n * 创建流程节点\n * @param json\n */\n createWorkflowNode(\n json: WorkflowNodeJSON,\n isClone: boolean = false,\n parentId?: string\n ): WorkflowNodeEntity {\n // 是否是一个已经存在的节点\n const isExistedNode = this.getNode(json.id);\n const parent = this.getNode(parentId ?? this.root.id) ?? this.root;\n const node = this.addNode(\n {\n ...json,\n parent,\n },\n undefined,\n true\n ) as WorkflowNodeEntity;\n\n const registry = node.getNodeRegistry() as WorkflowNodeRegistry;\n const { formMeta } = registry;\n const meta = node.getNodeMeta<WorkflowNodeMeta>();\n const formData = getFlowNodeFormData(node);\n\n const transform = node.getData<FlowNodeTransformData>(FlowNodeTransformData)!;\n const freeLayout = this.layout as FreeLayout;\n if (!isExistedNode) {\n transform.onDataChange(() => {\n // TODO 这个有点难以理解,其实是为了同步size 数据\n freeLayout.syncTransform(node);\n });\n }\n let { position } = meta;\n if (!position) {\n // 获取默认的位置\n position = this.getNodeDefaultPosition(json.type);\n }\n\n // 更新节点位置信息\n node.getData(TransformData)!.update({\n position,\n });\n\n // 初始化表单数据\n if (formMeta && formData && !formData.formModel.initialized) {\n // 如果表单数据在前置步骤(fromJSON)内已定义,则跳过表单初始化逻辑\n formData.createForm(formMeta, json.data);\n\n formData.onDataChange(() => {\n this.fireContentChange({\n type: WorkflowContentChangeType.NODE_DATA_CHANGE,\n toJSON: () => formData.toJSON(),\n entity: node,\n });\n });\n }\n // 位置变更\n const positionData = node.getData<PositionData>(PositionData)!;\n if (!isExistedNode) {\n positionData.onDataChange(() => {\n this.fireContentChange({\n type: WorkflowContentChangeType.MOVE_NODE,\n toJSON: () => positionData.toJSON(),\n entity: node,\n });\n });\n }\n\n const subCanvas = this.getNodeSubCanvas(node);\n\n if (!isExistedNode && !subCanvas?.isCanvas) {\n this.fireContentChange({\n type: WorkflowContentChangeType.ADD_NODE,\n entity: node,\n toJSON: () => this.toNodeJSON(node),\n });\n node.onDispose(() => {\n if (!node.parent || node.parent.flowNodeType === FlowNodeBaseType.ROOT) {\n return;\n }\n const parentTransform = node.parent.getData(FlowNodeTransformData);\n parentTransform.fireChange();\n });\n let lastDeleteNodeData: WorkflowNodeJSON | undefined;\n node.preDispose.onDispose(() => {\n lastDeleteNodeData = this.toNodeJSON(node);\n });\n node.onDispose(() => {\n this.fireContentChange({\n type: WorkflowContentChangeType.DELETE_NODE,\n entity: node,\n toJSON: () => lastDeleteNodeData,\n });\n });\n }\n\n // 若存在子节点,则创建子节点\n if (json.blocks) {\n this.renderJSON(\n { nodes: json.blocks, edges: json.edges ?? [] },\n {\n parent: node,\n isClone,\n }\n );\n }\n // 子画布联动\n if (subCanvas) {\n const canvasTransform = subCanvas.canvasNode.getData<TransformData>(TransformData);\n canvasTransform.update({\n position: subCanvas.parentNode.getNodeMeta()?.canvasPosition,\n });\n if (!isExistedNode) {\n subCanvas.parentNode.onDispose(() => {\n subCanvas.canvasNode.dispose();\n });\n subCanvas.canvasNode.onDispose(() => {\n subCanvas.parentNode.dispose();\n });\n }\n }\n if (!isExistedNode) {\n this.onNodeCreateEmitter.fire({\n node,\n data: json,\n json,\n });\n } else {\n this.onNodeUpdateEmitter.fire({\n node,\n data: json,\n json,\n });\n }\n\n return node;\n }\n\n /**\n * 添加节点,如果节点已经存在则不会重复创建\n * @param data\n * @param addedNodes\n */\n addNode(\n data: AddNodeData,\n addedNodes?: WorkflowNodeEntity[],\n ignoreCreateAndUpdateEvent?: boolean\n ): WorkflowNodeEntity {\n const { id, type = 'block', originParent, parent, meta, hidden, index } = data;\n let node = this.getNode(id);\n let isNew = false;\n const register = this.getNodeRegistry(type, data.originParent);\n // node 类型变化则全部删除重新来\n if (node && node.flowNodeType !== data.type) {\n node.dispose();\n node = undefined;\n }\n if (!node) {\n const { dataRegistries } = register;\n node = this.entityManager.createEntity<WorkflowNodeEntity>(WorkflowNodeEntity, {\n id,\n document: this,\n flowNodeType: type,\n originParent,\n meta,\n });\n const datas = dataRegistries\n ? this.nodeDataRegistries.concat(...dataRegistries)\n : this.nodeDataRegistries;\n node.addInitializeData(datas);\n node.onDispose(() => this.onNodeDisposeEmitter.fire({ node: node! }));\n this.options.fromNodeJSON?.(node, data, true);\n isNew = true;\n } else {\n this.options.fromNodeJSON?.(node, data, false);\n }\n // 初始化数据重制\n node.initData({\n originParent,\n parent,\n meta,\n hidden,\n index,\n });\n addedNodes?.push(node);\n // 自定义创建逻辑\n if (register.onCreate) {\n const extendNodes = register.onCreate(node, data);\n if (extendNodes && addedNodes) {\n addedNodes.push(...extendNodes);\n }\n }\n\n if (!ignoreCreateAndUpdateEvent) {\n if (isNew) {\n this.onNodeCreateEmitter.fire({\n node,\n data,\n json: data,\n });\n } else {\n this.onNodeUpdateEmitter.fire({ node, data, json: data });\n }\n }\n\n return node;\n }\n\n get layout(): FreeLayout {\n const layout = this.layouts.find((layout) => layout.name == this.currentLayoutKey);\n if (!layout) {\n throw new Error(`Unknown flow layout: ${this.currentLayoutKey}`);\n }\n return layout as FreeLayout;\n }\n\n /**\n * 获取默认的 x y 坐标, 默认为当前画布可视区域中心\n * @param type\n * @protected\n */\n getNodeDefaultPosition(type: string | number): IPoint {\n const { size } = this.getNodeRegistry(type).meta || {};\n // 当前可视区域的中心位置\n let position = this.playgroundConfig.getViewport(true).center;\n if (size) {\n position = {\n x: position.x,\n y: position.y - size.height / 2,\n };\n }\n // 去掉叠加的\n return getAntiOverlapPosition(this, position);\n }\n\n /**\n * 通过类型创建节点, 如果没有提供position 则直接放在画布中间\n * @param type\n */\n createWorkflowNodeByType(\n type: string | number,\n position?: IPoint,\n json: Partial<WorkflowNodeJSON> = {},\n parentID?: string\n ): WorkflowNodeEntity {\n let id: string = json.id as string;\n if (id === undefined) {\n // 保证 id 不要重复\n do {\n id = `1${nanoid()}`;\n } while (this.entityManager.getEntityById(id));\n } else {\n if (this.entityManager.getEntityById(id)) {\n throw new Error(`[WorkflowDocument.createWorkflowNodeByType] Node Id \"${id}\" duplicated.`);\n }\n }\n return this.createWorkflowNode(\n {\n ...json,\n id,\n type,\n meta: { position, ...json?.meta }, // TODO title 和 meta 要从注册数据去拿\n data: json?.data,\n blocks: json?.blocks,\n edges: json?.edges,\n },\n false,\n parentID\n );\n }\n\n getAllNodes(): WorkflowNodeEntity[] {\n return this.entityManager\n .getEntities<WorkflowNodeEntity>(WorkflowNodeEntity)\n .filter((n) => n.id !== FlowNodeBaseType.ROOT);\n }\n\n getAllPorts(): WorkflowPortEntity[] {\n return this.entityManager\n .getEntities<WorkflowPortEntity>(WorkflowPortEntity)\n .filter((p) => p.node.id !== FlowNodeBaseType.ROOT);\n }\n\n /**\n * 获取画布中的非游离节点\n * 1. 开始节点\n * 2. 从开始节点出发能走到的节点\n * 3. 结束节点\n * 4. 默认所有子画布内节点为游离节点\n */\n getAssociatedNodes(): WorkflowNodeEntity[] {\n const allNode = this.getAllNodes();\n\n const allLines = this.linesManager\n .getAllLines()\n .filter((line) => line.from && line.to)\n .map((line) => ({\n from: line.from.id,\n to: line.to!.id,\n }));\n\n const startNodeId = allNode.find((node) => node.isStart)?.id;\n const endNodeId = allNode.find((node) => node.isNodeEnd)?.id;\n\n // 子画布内节点无需开始/结束\n const nodeInContainer = allNode\n .filter((node) => node.parent?.getNodeMeta<WorkflowNodeMeta>().isContainer)\n .map((node) => node.id);\n\n const associatedCache = new Set(nodeInContainer);\n if (endNodeId) {\n associatedCache.add(endNodeId);\n }\n const bfs = (nodeId: string) => {\n if (associatedCache.has(nodeId)) {\n return;\n }\n associatedCache.add(nodeId);\n const nextNodes = allLines.reduce((ids, { from, to }) => {\n if (from === nodeId && !associatedCache.has(to)) {\n ids.push(to);\n }\n return ids;\n }, [] as string[]);\n\n nextNodes.forEach(bfs);\n };\n\n if (startNodeId) {\n bfs(startNodeId);\n }\n\n const associatedNodes = allNode.filter((node) => associatedCache.has(node.id));\n\n return associatedNodes;\n }\n\n /**\n * 触发渲染\n */\n fireRender() {\n this.entityManager.fireEntityChanged(WorkflowNodeEntity.type);\n this.entityManager.fireEntityChanged(WorkflowLineEntity.type);\n this.entityManager.fireEntityChanged(WorkflowPortEntity.type);\n }\n\n fireContentChange(event: WorkflowContentChangeEvent): void {\n if (this._loading || this.disposed || this.entityManager.changeEntityLocked) {\n return;\n }\n this._onContentChangeEmitter.fire(event);\n }\n\n toNodeJSON(node: WorkflowNodeEntity): WorkflowNodeJSON {\n // 如果是子画布,返回其父节点的JSON\n const subCanvas = this.getNodeSubCanvas(node);\n if (subCanvas?.isCanvas === true) {\n return this.toNodeJSON(subCanvas.parentNode);\n }\n\n const json = this.toNodeJSONFromOptions(node);\n const children = this.getNodeChildren(node);\n\n // 计算子节点 JSON\n const blocks = children.map((child) => this.toNodeJSON(child));\n\n // 计算子线条 JSON\n const linesMap = new Map<string, WorkflowEdgeJSON>();\n children.forEach((child) => {\n const childLinesData = child.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData);\n [...childLinesData.inputLines, ...childLinesData.outputLines]\n .filter(Boolean)\n .forEach((line) => {\n const lineJSON = this.toLineJSON(line);\n if (!lineJSON || linesMap.has(line.id)) {\n return;\n }\n linesMap.set(line.id, lineJSON);\n });\n });\n const edges = Array.from(linesMap.values()); // 使用 Map 防止线条重复\n\n // 拼接 JSON\n if (blocks.length > 0) json.blocks = blocks;\n if (edges.length > 0) json.edges = edges;\n\n return json;\n }\n\n /**\n * 节点转换为JSON, 没有format的过程\n * @param node\n * @returns\n */\n private toNodeJSONFromOptions(node: WorkflowNodeEntity): WorkflowNodeJSON {\n if (this.options.toNodeJSON) {\n return this.options.toNodeJSON(node) as WorkflowNodeJSON;\n }\n return WorkflowDocumentOptionsDefault.toNodeJSON!(node) as WorkflowNodeJSON;\n }\n\n copyNode(\n node: WorkflowNodeEntity,\n newNodeId?: string | undefined,\n format?: (json: WorkflowNodeJSON) => WorkflowNodeJSON,\n position?: IPoint\n ): WorkflowNodeEntity {\n let json = this.toNodeJSON(node);\n if (format) {\n json = format(json);\n }\n position = position || {\n x: json.meta!.position!.x + 30,\n y: json.meta!.position!.y + 30,\n };\n return this.createWorkflowNode(\n {\n id: newNodeId || `1${nanoid()}`,\n type: node.flowNodeType,\n meta: {\n ...json.meta,\n position,\n },\n data: json.data,\n blocks: json.blocks,\n edges: json.edges,\n },\n true,\n node.parent?.id\n );\n }\n\n copyNodeFromJSON(\n flowNodeType: string,\n nodeJSON: WorkflowNodeJSON,\n newNodeId?: string | undefined,\n position?: IPoint,\n parentId?: string\n ): WorkflowNodeEntity {\n position = position || {\n x: nodeJSON.meta!.position!.x + 30,\n y: nodeJSON.meta!.position!.y + 30,\n };\n return this.createWorkflowNode(\n {\n id: newNodeId || `1${nanoid()}`,\n type: flowNodeType,\n meta: {\n ...nodeJSON.meta,\n position,\n },\n data: nodeJSON.data,\n blocks: nodeJSON.blocks,\n edges: nodeJSON.edges,\n },\n true,\n parentId\n );\n }\n\n canRemove(node: WorkflowNodeEntity, silent?: boolean): boolean {\n const meta = node.getNodeMeta<WorkflowNodeMeta>();\n if (meta.deleteDisable) {\n return false;\n }\n if (this.options.canDeleteNode && !this.options.canDeleteNode(node, silent)) {\n return false;\n }\n return true;\n }\n\n /**\n * 判断端口是否为错误态\n */\n isErrorPort(port: WorkflowPortEntity, defaultValue = false) {\n if (typeof this.options.isErrorPort === 'function') {\n return this.options.isErrorPort(port);\n }\n\n return defaultValue;\n }\n\n /**\n * 导出数据\n */\n toJSON(): WorkflowJSON {\n if (this.disposed) {\n throw new Error(\n 'The WorkflowDocument has been disposed and it is no longer possible to call toJSON.'\n );\n }\n const rootJSON = this.toNodeJSON(this.root);\n const json = {\n nodes: rootJSON.blocks ?? [],\n edges: rootJSON.edges ?? [],\n };\n return json;\n }\n\n dispose() {\n super.dispose();\n this._onReloadEmitter.dispose();\n }\n\n /**\n * 批量添加节点\n * @deprecated use 'batchAddFromJSON' instead\n * @param json\n * @param options\n */\n public renderJSON(\n json: WorkflowJSON,\n options?: {\n parent?: WorkflowNodeEntity;\n isClone?: boolean;\n }\n ): {\n nodes: WorkflowNodeEntity[];\n edges: WorkflowLineEntity[];\n } {\n return this.batchAddFromJSON(json, options);\n }\n\n /**\n * 批量添加节点\n */\n public batchAddFromJSON(\n json: WorkflowJSON,\n options?: {\n parent?: WorkflowNodeEntity;\n isClone?: boolean;\n }\n ): {\n nodes: WorkflowNodeEntity[];\n edges: WorkflowLineEntity[];\n } {\n const { parent = this.root, isClone = false } = options ?? {};\n // 创建节点\n const containerID = this.getNodeSubCanvas(parent)?.canvasNode.id ?? parent.id;\n const processedJSON = buildGroupJSON(json);\n const nodes = processedJSON.nodes.map((nodeJSON: WorkflowNodeJSON) =>\n this.createWorkflowNode(nodeJSON, isClone, containerID)\n );\n // 创建线条\n const edges = processedJSON.edges\n .map((edge) => this.createWorkflowLine(edge, containerID))\n .filter(Boolean) as WorkflowLineEntity[];\n return { nodes, edges };\n }\n\n private getNodeSubCanvas(node: WorkflowNodeEntity): WorkflowSubCanvas | undefined {\n if (!node) return;\n const nodeMeta = node.getNodeMeta<WorkflowNodeMeta>();\n const subCanvas = nodeMeta.subCanvas?.(node);\n return subCanvas;\n }\n\n private getNodeChildren(node: WorkflowNodeEntity): WorkflowNodeEntity[] {\n if (!node || node.flowNodeType === FlowNodeBaseType.GROUP) return [];\n const subCanvas = this.getNodeSubCanvas(node);\n // get real children\n const realChildren = subCanvas ? subCanvas.canvasNode.blocks : node.blocks;\n // filter sub canvas node\n const childrenWithoutSubCanvas = realChildren\n .filter((child) => {\n const childMeta = child.getNodeMeta<WorkflowNodeMeta>();\n return !childMeta.subCanvas?.(node)?.isCanvas;\n })\n .filter(Boolean);\n // flat group nodes\n const children = childrenWithoutSubCanvas\n .map((child) => {\n if (child.flowNodeType === FlowNodeBaseType.GROUP) {\n return [child, ...child.blocks];\n }\n return child;\n })\n .flat();\n return children;\n }\n\n private toLineJSON(line: WorkflowLineEntity): WorkflowEdgeJSON | undefined {\n const lineJSON = line.toJSON();\n if (\n !line.from ||\n !line.info.from ||\n !line.fromPort ||\n !line.to ||\n !line.info.to ||\n !line.toPort\n ) {\n return;\n }\n // 父子节点之间连线,需替换子画布为父节点\n const fromSubCanvas = this.getNodeSubCanvas(line.from);\n const toSubCanvas = this.getNodeSubCanvas(line.to);\n if (fromSubCanvas && !fromSubCanvas.isCanvas && toSubCanvas && toSubCanvas.isCanvas) {\n // 忽略子画布与父节点的连线\n return;\n }\n if (line.from === line.to.parent && fromSubCanvas) {\n return {\n ...lineJSON,\n sourceNodeID: fromSubCanvas.parentNode.id,\n };\n }\n if (line.to === line.from.parent && toSubCanvas) {\n return {\n ...lineJSON,\n targetNodeID: toSubCanvas.parentNode.id,\n };\n }\n return lineJSON;\n }\n\n private createWorkflowLine(\n json: WorkflowEdgeJSON,\n parentId?: string\n ): WorkflowLineEntity | undefined {\n const fromNode = this.getNode(json.sourceNodeID);\n const toNode = this.getNode(json.targetNodeID);\n // 脏数据清除\n if (!fromNode || !toNode) {\n return;\n }\n const lineInfo: WorkflowLinePortInfo = {\n from: json.sourceNodeID,\n fromPort: json.sourcePortID,\n to: json.targetNodeID,\n toPort: json.targetPortID,\n data: json.data,\n };\n if (!parentId) {\n return this.linesManager.createLine(lineInfo);\n }\n // 父子节点之间连线,需替换父节点为子画布\n const canvasNode = this.getNode(parentId);\n if (!canvasNode) {\n return this.linesManager.createLine(lineInfo);\n }\n const parentSubCanvas = this.getNodeSubCanvas(canvasNode);\n if (!parentSubCanvas) {\n return this.linesManager.createLine(lineInfo);\n }\n if (lineInfo.from === parentSubCanvas.parentNode.id) {\n return this.linesManager.createLine({\n ...lineInfo,\n from: parentSubCanvas.canvasNode.id,\n });\n }\n if (lineInfo.to === parentSubCanvas.parentNode.id) {\n return this.linesManager.createLine({\n ...lineInfo,\n to: parentSubCanvas.canvasNode.id,\n });\n }\n return this.linesManager.createLine(lineInfo);\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { inject, injectable } from 'inversify';\nimport {\n type IPoint,\n PaddingSchema,\n Rectangle,\n type ScrollSchema,\n SizeSchema,\n} from '@flowgram.ai/utils';\nimport {\n type FlowDocument,\n type FlowLayout,\n type FlowNodeEntity,\n FlowDocumentProvider,\n FlowNodeTransformData,\n} from '@flowgram.ai/document';\nimport { PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\n\nexport const FREE_LAYOUT_KEY = 'free-layout';\n/**\n * 自由画布布局\n */\n@injectable()\nexport class FreeLayout implements FlowLayout {\n name = FREE_LAYOUT_KEY;\n\n @inject(PlaygroundConfigEntity) playgroundConfig: PlaygroundConfigEntity;\n\n @inject(FlowDocumentProvider)\n protected documentProvider: FlowDocumentProvider;\n\n get document(): FlowDocument {\n return this.documentProvider();\n }\n\n /**\n * 更新布局\n */\n update(): void {\n if (this.document.root.getData(FlowNodeTransformData)?.localDirty) {\n this.document.root.clearMemoGlobal();\n // this.document.root.getData(FlowNodeTransformData)!.localDirty = false\n }\n // 自由画布同步同步大小, TODO 这个移动到 createWorkflowNode\n // this.document.root.allChildren.forEach(this.syncTransform.bind(this))\n }\n\n syncTransform(node: FlowNodeEntity): void {\n const transform = node.getData<FlowNodeTransformData>(FlowNodeTransformData)!;\n if (!transform.localDirty) {\n return;\n }\n node.clearMemoGlobal();\n node.clearMemoLocal();\n // 同步 size 给原始的 transform\n transform.transform.update({\n size: transform.data.size,\n });\n if (!node.parent) {\n return;\n }\n node.parent.clearMemoGlobal();\n node.parent.clearMemoLocal();\n const parentTransform = node.parent.getData<FlowNodeTransformData>(FlowNodeTransformData);\n parentTransform.transform.fireChange();\n }\n\n /**\n * 更新所有受影响的上下游节点\n */\n updateAffectedTransform(node: FlowNodeEntity): void {\n const transformData = node.transform;\n if (!transformData.localDirty) {\n return;\n }\n const allParents = this.getAllParents(node);\n const allBlocks = this.getAllBlocks(node).reverse();\n const affectedNodes = [...allBlocks, ...allParents];\n affectedNodes.forEach((node) => {\n this.fireChange(node);\n });\n }\n\n /**\n * 获取节点的 padding 数据\n * @param node\n */\n getPadding(node: FlowNodeEntity): PaddingSchema {\n const { padding } = node.getNodeMeta();\n const transform = node.getData<FlowNodeTransformData>(FlowNodeTransformData);\n if (padding) {\n return typeof padding === 'function' ? padding(transform) : padding;\n }\n return PaddingSchema.empty();\n }\n\n /**\n * 默认滚动到 fitview 区域\n * @param contentSize\n */\n getInitScroll(contentSize: SizeSchema): ScrollSchema {\n const bounds = Rectangle.enlarge(\n this.document.getAllNodes().map((node) => node.getData<TransformData>(TransformData).bounds)\n ).pad(30, 30); // 留出 30 像素的边界\n const viewport = this.playgroundConfig.getViewport(false);\n const zoom = SizeSchema.fixSize(bounds, viewport);\n return {\n scrollX: (bounds.x + bounds.width / 2) * zoom - this.playgroundConfig.config.width / 2,\n scrollY: (bounds.y + bounds.height / 2) * zoom - this.playgroundConfig.config.height / 2,\n };\n }\n\n /**\n * 获取默认输入点\n */\n getDefaultInputPoint(node: FlowNodeEntity): IPoint {\n return node.getData<TransformData>(TransformData)!.bounds.leftCenter;\n }\n\n /**\n * 获取默认输出点\n */\n getDefaultOutputPoint(node: FlowNodeEntity): IPoint {\n return node.getData<TransformData>(TransformData)!.bounds.rightCenter;\n }\n\n /**\n * 水平中心点\n */\n getDefaultNodeOrigin(): IPoint {\n return { x: 0.5, y: 0 };\n }\n\n private getAllParents(node: FlowNodeEntity): FlowNodeEntity[] {\n const parents: FlowNodeEntity[] = [];\n let current = node.parent;\n\n while (current) {\n parents.push(current);\n current = current.parent;\n }\n\n return parents;\n }\n\n private getAllBlocks(node: FlowNodeEntity): FlowNodeEntity[] {\n return node.blocks.reduce<FlowNodeEntity[]>(\n (acc, child) => [...acc, ...this.getAllBlocks(child)],\n [node]\n );\n }\n\n private fireChange(node?: FlowNodeEntity): void {\n const transformData = node?.transform;\n if (!node || !transformData?.localDirty) {\n return;\n }\n node.clearMemoGlobal();\n node.clearMemoLocal();\n transformData.transform.fireChange();\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { inject, injectable, postConstruct } from 'inversify';\nimport { PlaygroundConfigEntity } from '@flowgram.ai/core';\nimport { EntityManager } from '@flowgram.ai/core';\nimport { DisposableCollection, Emitter, type IPoint } from '@flowgram.ai/utils';\n\nimport { WorkflowDocument } from '../workflow-document';\nimport { layoutToPositions } from '../utils/layout-to-positions';\nimport { fitView } from '../utils';\nimport { WorkflowNodeEntity } from '../entities';\n\nexport type PositionMap = Record<string, IPoint>;\n\n/**\n * 重置布局服务\n */\n@injectable()\nexport class WorkflowResetLayoutService {\n @inject(PlaygroundConfigEntity)\n private _config: PlaygroundConfigEntity;\n\n @inject(WorkflowDocument)\n private _document: WorkflowDocument;\n\n @inject(EntityManager)\n private _entityManager: EntityManager;\n\n private _resetLayoutEmitter = new Emitter<{\n nodeIds: string[];\n positionMap: PositionMap;\n oldPositionMap: PositionMap;\n }>();\n\n /**\n * reset layout事件\n */\n readonly onResetLayout = this._resetLayoutEmitter.event;\n\n private _toDispose = new DisposableCollection();\n\n /**\n * 初始化\n */\n @postConstruct()\n init() {\n this._toDispose.push(this._resetLayoutEmitter);\n }\n\n /**\n * 触发重置布局\n * @param nodeIds 节点id\n * @param positionMap 新布局数据\n * @param oldPositionMap 老布局数据\n */\n fireResetLayout(nodeIds: string[], positionMap: PositionMap, oldPositionMap: PositionMap) {\n this._resetLayoutEmitter.fire({\n nodeIds,\n positionMap,\n oldPositionMap,\n });\n }\n\n /**\n * 根据数据重新布局\n * @param positionMap\n * @returns\n */\n async layoutToPositions(nodeIds: string[], positionMap: PositionMap) {\n const nodes = nodeIds\n .map(id => this._entityManager.getEntityById(id))\n .filter(Boolean) as WorkflowNodeEntity[];\n const positions = await layoutToPositions(nodes, positionMap);\n fitView(this._document, this._config, true);\n return positions;\n }\n\n /**\n * 销毁\n */\n dispose() {\n this._toDispose.dispose();\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { type IPoint } from '@flowgram.ai/utils';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { TransformData, startTween } from '@flowgram.ai/core';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport { type WorkflowNodeEntity } from '../entities';\n\n/**\n * Coze 中节点坐标,以卡片顶部中间为原点。\n * autoLayout 计算出来的对齐的坐标以节点正中为原点,需要上移当前节点一般高度。\n * 即: newPosition.y - transform.bounds.height / 2\n * bounds 的原点坐标为左上角。\n */\nexport const layoutToPositions = async (\n nodes: WorkflowNodeEntity[],\n nodePositionMap: Record<string, IPoint>\n): Promise<Record<string, IPoint>> => {\n // 缓存上次位置,用来还原位置\n const newNodePositionMap: Record<string, IPoint> = {};\n nodes.forEach((node) => {\n const transform = node.getData(TransformData);\n const nodeTransform = node.getData(FlowNodeTransformData);\n\n newNodePositionMap[node.id] = {\n x: transform.position.x,\n y: transform.position.y + nodeTransform.bounds.height / 2,\n };\n });\n\n return new Promise((resolve) => {\n startTween({\n from: { d: 0 },\n to: { d: 100 },\n duration: 300,\n onUpdate: (v) => {\n nodes.forEach((node) => {\n const transform = node.getData(TransformData);\n const deltaX = ((nodePositionMap[node.id].x - transform.position.x) * v.d) / 100;\n const deltaY =\n ((nodePositionMap[node.id].y - transform.bounds.height / 2 - transform.position.y) *\n v.d) /\n 100;\n\n transform.update({\n position: {\n x: transform.position.x + deltaX,\n y: transform.position.y + deltaY,\n },\n });\n\n const document = node.document as WorkflowDocument;\n document.layout.updateAffectedTransform(node);\n });\n },\n onComplete: () => {\n resolve(newNodePositionMap);\n },\n });\n });\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { inject } from 'inversify';\nimport { IPoint, Emitter } from '@flowgram.ai/utils';\nimport { FlowNodeEntityOrId, FlowOperationBaseServiceImpl } from '@flowgram.ai/document';\nimport { TransformData } from '@flowgram.ai/core';\n\nimport { WorkflowDocument } from '../workflow-document';\nimport {\n NodePostionUpdateEvent,\n WorkflowOperationBaseService,\n} from '../typings/workflow-operation';\n\nexport class WorkflowOperationBaseServiceImpl\n extends FlowOperationBaseServiceImpl\n implements WorkflowOperationBaseService\n{\n @inject(WorkflowDocument)\n protected declare document: WorkflowDocument;\n\n private onNodePostionUpdateEmitter = new Emitter<NodePostionUpdateEvent>();\n\n public readonly onNodePostionUpdate = this.onNodePostionUpdateEmitter.event;\n\n updateNodePosition(nodeOrId: FlowNodeEntityOrId, position: IPoint): void {\n const node = this.toNodeEntity(nodeOrId);\n\n if (!node) {\n return;\n }\n\n const transformData = node.getData(TransformData);\n const oldPosition = {\n x: transformData.position.x,\n y: transformData.position.y,\n };\n transformData.update({\n position,\n });\n\n this.onNodePostionUpdateEmitter.fire({\n node,\n oldPosition,\n newPosition: position,\n });\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { useEffect } from 'react';\n\nimport { usePlayground, useRefresh } from '@flowgram.ai/core';\nimport { type Disposable } from '@flowgram.ai/utils';\n\n/**\n * 获取 readonly 状态\n */\nexport function usePlaygroundReadonlyState(listenChange?: boolean): boolean {\n const playground = usePlayground();\n const refresh = useRefresh();\n useEffect(() => {\n let dispose: Disposable | undefined = undefined;\n if (listenChange) {\n dispose = playground.config.onReadonlyOrDisabledChange(() => refresh());\n }\n return () => dispose?.dispose();\n }, [listenChange]);\n return playground.config.readonly;\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { FlowNodeRenderData } from '@flowgram.ai/document';\nimport { useEntityFromContext } from '@flowgram.ai/core';\n\nimport { type WorkflowNodeEntity } from '../entities';\n\n/**\n * 获取当前渲染的 dom 节点\n */\nexport function useCurrentDomNode(): HTMLDivElement {\n const entity = useEntityFromContext<WorkflowNodeEntity>();\n const renderData = entity.getData(FlowNodeRenderData)!;\n return renderData.node;\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { useEntityFromContext } from '@flowgram.ai/core';\n\nimport { type WorkflowNodeEntity } from '../entities';\n\n/**\n * 获取当前节点\n */\nexport function useCurrentEntity(): WorkflowNodeEntity {\n return useEntityFromContext<WorkflowNodeEntity>();\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { useService } from '@flowgram.ai/core';\n\nimport { WorkflowDocument } from '../workflow-document';\n\nexport function useWorkflowDocument(): WorkflowDocument {\n return useService<WorkflowDocument>(WorkflowDocument);\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport enum EditorCursorState {\n GRAB = 'GRAB',\n SELECT = 'SELECT',\n}\n\nexport enum InteractiveType {\n /** 鼠标优先交互模式 */\n MOUSE = 'MOUSE',\n\n /** 触控板优先交互模式 */\n PAD = 'PAD',\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { ContainerModule } from 'inversify';\nimport { bindContributions } from '@flowgram.ai/utils';\nimport { FlowDocument, FlowDocumentContribution } from '@flowgram.ai/document';\n\nimport { WorkflowLinesManager } from './workflow-lines-manager';\nimport {\n WorkflowDocumentOptions,\n WorkflowDocumentOptionsDefault,\n} from './workflow-document-option';\nimport { WorkflowDocumentContribution } from './workflow-document-contribution';\nimport { WorkflowDocument, WorkflowDocumentProvider } from './workflow-document';\nimport { getUrlParams } from './utils/get-url-params';\nimport { URLParams, WorkflowOperationBaseService } from './typings';\nimport {\n WorkflowDragService,\n WorkflowHoverService,\n WorkflowSelectService,\n WorkflowResetLayoutService,\n WorkflowOperationBaseServiceImpl,\n} from './service';\nimport { FreeLayout } from './layout';\n\nexport const WorkflowDocumentContainerModule = new ContainerModule(\n (bind, unbind, isBound, rebind) => {\n bind(WorkflowDocument).toSelf().inSingletonScope();\n bind(WorkflowLinesManager).toSelf().inSingletonScope();\n bind(FreeLayout).toSelf().inSingletonScope();\n bind(WorkflowDragService).toSelf().inSingletonScope();\n bind(WorkflowSelectService).toSelf().inSingletonScope();\n bind(WorkflowHoverService).toSelf().inSingletonScope();\n bind(WorkflowResetLayoutService).toSelf().inSingletonScope();\n bind(WorkflowOperationBaseService).to(WorkflowOperationBaseServiceImpl).inSingletonScope();\n bind(URLParams)\n .toDynamicValue(() => getUrlParams())\n .inSingletonScope();\n bindContributions(bind, WorkflowDocumentContribution, [FlowDocumentContribution]);\n bind(WorkflowDocumentOptions).toConstantValue({\n ...WorkflowDocumentOptionsDefault,\n });\n rebind(FlowDocument).toService(WorkflowDocument);\n bind(WorkflowDocumentProvider)\n .toDynamicValue((ctx) => () => ctx.container.get(WorkflowDocument))\n .inSingletonScope();\n }\n);\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { injectable, inject } from 'inversify';\nimport {\n type FlowDocumentContribution,\n FlowNodeRenderData,\n FlowNodeTransformData,\n} from '@flowgram.ai/document';\n\nimport { WorkflowDocument } from './workflow-document';\nimport { FreeLayout } from './layout';\nimport { WorkflowNodeLinesData, WorkflowNodePortsData } from './entity-datas';\n\n@injectable()\nexport class WorkflowDocumentContribution implements FlowDocumentContribution<WorkflowDocument> {\n @inject(FreeLayout) freeLayout: FreeLayout;\n\n registerDocument(document: WorkflowDocument): void {\n // 注册节点数据\n document.registerNodeDatas(\n FlowNodeTransformData,\n FlowNodeRenderData,\n WorkflowNodePortsData,\n WorkflowNodeLinesData,\n );\n document.registerLayout(this.freeLayout);\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport function getUrlParams(): Record<string, string> {\n return location.search\n .replace(/^\\?/, '')\n .split('&')\n .reduce((res: Record<string, string>, key) => {\n const [k, v] = key.split('=');\n res[k] = v;\n return res;\n }, {} satisfies Record<string, string>);\n}\n"],"mappings":"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","names":["WorkflowCommands","import_core","import_react","import_document","import_core","import_core","import_utils","import_core","import_utils","nanoidOrigin","import_utils","import_core","import_utils","import_document","import_lodash_es","import_utils","import_core","import_document","import_core","import_utils","import_document","import_core","location","point","document","import_utils","import_core","import_utils","import_core","fitView","import_inversify","import_utils","import_core","import_nanoid","import_inversify","import_utils","import_document","import_core","import_lodash_es","import_inversify","import_utils","import_document","import_core","import_form_core","import_document","import_core","WorkflowContentChangeType","LineType","LineColors","import_nanoid","import_inversify","import_utils","import_form_core","import_document","import_core","import_inversify","import_utils","import_document","import_core","node","nanoid","layout","offset","import_inversify","import_core","import_utils","import_document","import_core","document","import_inversify","import_utils","import_document","import_core","import_core","import_document","import_core","import_core","import_core","EditorCursorState","InteractiveType","import_inversify","import_utils","import_document","import_inversify","import_document","document"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/workflow-commands.ts","../src/hooks/index.ts","../src/hooks/use-node-render.tsx","../src/service/workflow-select-service.ts","../src/utils/index.ts","../src/utils/build-group-json.ts","../src/utils/get-line-center.ts","../src/utils/nanoid.ts","../src/utils/compose.ts","../src/utils/fit-view.ts","../src/utils/get-anti-overlap-position.ts","../src/utils/statics.ts","../src/entities/workflow-node-entity.ts","../src/entities/workflow-line-entity.ts","../src/entity-datas/workflow-node-ports-data.ts","../src/entities/workflow-port-entity.ts","../src/entity-datas/workflow-node-lines-data.ts","../src/entity-datas/workflow-line-render-data.ts","../src/service/workflow-hover-service.ts","../src/service/workflow-drag-service.ts","../src/workflow-lines-manager.ts","../src/workflow-document-option.ts","../src/utils/flow-node-form-data.ts","../src/typings/workflow-json.ts","../src/typings/workflow-line.ts","../src/typings/workflow-operation.ts","../src/typings/index.ts","../src/workflow-document.ts","../src/layout/free-layout.ts","../src/service/workflow-reset-layout-service.ts","../src/utils/layout-to-positions.ts","../src/service/workflow-operation-base-service.ts","../src/hooks/use-playground-readonly-state.ts","../src/hooks/use-current-dom-node.ts","../src/hooks/use-current-entity.ts","../src/hooks/use-workflow-document.ts","../src/constants.ts","../src/workflow-document-container-module.ts","../src/workflow-document-contribution.ts","../src/utils/get-url-params.ts"],"sourcesContent":["/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport * from './workflow-commands';\nexport * from './hooks';\nexport * from './utils';\nexport * from './typings';\nexport * from './entities';\nexport * from './constants';\nexport * from './entity-datas';\nexport * from './service';\nexport * from './workflow-document';\nexport * from './workflow-document-container-module';\nexport * from './workflow-lines-manager';\nexport * from './workflow-document-option';\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport enum WorkflowCommands {\n DELETE_NODES = 'DELETE_NODES',\n COPY_NODES = 'COPY_NODES',\n PASTE_NODES = 'PASTE_NODES',\n ZOOM_IN = 'ZOOM_IN',\n ZOOM_OUT = 'ZOOM_OUT',\n UNDO = 'UNDO',\n REDO = 'REDO',\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport {\n useConfigEntity,\n useService,\n usePlayground,\n useListenEvents,\n usePlaygroundContainer,\n usePlaygroundContext,\n useEntities,\n useEntityFromContext,\n useEntityDataFromContext,\n useRefresh,\n} from '@flowgram.ai/core';\nexport * from './typings';\nexport * from './use-node-render';\nexport * from './use-current-dom-node';\nexport * from './use-current-entity';\nexport * from './use-workflow-document';\nexport * from './use-playground-readonly-state';\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport type React from 'react';\nimport { useCallback, useEffect, useRef, useState, useContext, useMemo } from 'react';\n\nimport { useObserve } from '@flowgram.ai/reactive';\nimport { getNodeForm } from '@flowgram.ai/node';\nimport { FlowNodeRenderData } from '@flowgram.ai/document';\nimport {\n MouseTouchEvent,\n PlaygroundEntityContext,\n useListenEvents,\n useService,\n} from '@flowgram.ai/core';\n\nimport { WorkflowDragService, WorkflowSelectService } from '../service';\nimport { WorkflowNodePortsData } from '../entity-datas';\nimport { type WorkflowNodeEntity } from '../entities';\nimport { usePlaygroundReadonlyState } from './use-playground-readonly-state';\nimport { type NodeRenderReturnType } from './typings';\n\nfunction checkTargetDraggable(el: any): boolean {\n return (\n el &&\n el.tagName !== 'INPUT' &&\n el.tagName !== 'TEXTAREA' &&\n !el.closest('.flow-canvas-not-draggable')\n );\n}\n/**\n * - 下面的 firefox 为了修复一个 bug\n * - firefox 下 draggable 属性会影响节点 input 内容 focus:https://jsfiddle.net/Aydar/ztsvbyep/3/\n * - 该 bug 在 firefox 浏览器上存在了很久,需要作兼容:https://bugzilla.mozilla.org/show_bug.cgi?id=739071\n */\nconst isFirefox = navigator?.userAgent?.includes?.('Firefox');\n\nexport function useNodeRender(nodeFromProps?: WorkflowNodeEntity): NodeRenderReturnType {\n const node = nodeFromProps || useContext<WorkflowNodeEntity>(PlaygroundEntityContext);\n const renderData = node.getData(FlowNodeRenderData)!;\n const portsData = node.getData(WorkflowNodePortsData)!;\n const readonly = usePlaygroundReadonlyState();\n const dragService = useService<WorkflowDragService>(WorkflowDragService);\n const selectionService = useService<WorkflowSelectService>(WorkflowSelectService);\n const isDragging = useRef(false);\n const [formValueVersion, updateFormValueVersion] = useState<number>(0);\n const formValueDependRef = useRef(false);\n formValueDependRef.current = false;\n const nodeRef = useRef<HTMLDivElement | null>(null);\n const [linkingNodeId, setLinkingNodeId] = useState('');\n\n useEffect(() => {\n const disposable = dragService.onDragLineEventChange(({ type, onDragNodeId }) => {\n if (type === 'onDrag') {\n setLinkingNodeId(onDragNodeId || '');\n } else {\n setLinkingNodeId('');\n }\n });\n\n return () => {\n disposable.dispose();\n };\n }, []);\n\n const startDrag = useCallback(\n (e: React.MouseEvent) => {\n MouseTouchEvent.preventDefault(e);\n if (!selectionService.isSelected(node.id)) {\n selectNode(e);\n }\n if (!MouseTouchEvent.isTouchEvent(e as unknown as React.TouchEvent)) {\n // 输入框不能拖拽\n if (!checkTargetDraggable(e.target) || !checkTargetDraggable(document.activeElement)) {\n return;\n }\n }\n isDragging.current = true;\n // 拖拽选中的节点\n dragService.startDragSelectedNodes(e)?.finally(() =>\n setTimeout(() => {\n isDragging.current = false;\n })\n );\n },\n [dragService, node]\n );\n /**\n * 单选节点\n */\n const selectNode = useCallback(\n (e: React.MouseEvent) => {\n // 触发了拖拽就不要再触发单选\n if (isDragging.current) {\n return;\n }\n // 追加选择\n if (e.shiftKey) {\n selectionService.toggleSelect(node);\n } else {\n selectionService.selectNode(node);\n }\n if (e.target) {\n (e.target as HTMLDivElement).focus();\n }\n },\n [node]\n );\n const deleteNode = useCallback(() => node.dispose(), [node]);\n // 监听端口变化\n useListenEvents(portsData.onDataChange);\n\n const onFocus = useCallback(() => {\n if (isFirefox) {\n nodeRef.current?.setAttribute('draggable', 'false');\n }\n }, []);\n const onBlur = useCallback(() => {\n if (isFirefox) {\n nodeRef.current?.setAttribute('draggable', 'true');\n }\n }, []);\n const getExtInfo = useCallback(() => node.getExtInfo() as any, [node]);\n const updateExtInfo = useCallback(\n (data: any) => {\n node.updateExtInfo(data);\n },\n [node]\n );\n const form = useMemo(() => getNodeForm(node), [node]);\n // Listen FormState change\n const formState = useObserve<any>(form?.state);\n const toggleExpand = useCallback(() => {\n renderData.toggleExpand();\n }, [renderData]);\n const selected = selectionService.isSelected(node.id);\n const activated = selectionService.isActivated(node.id);\n const expanded = renderData.expanded;\n useEffect(() => {\n const toDispose = form?.onFormValuesChange(() => {\n if (formValueDependRef.current) {\n updateFormValueVersion((v) => v + 1);\n }\n });\n return () => toDispose?.dispose();\n }, [form]);\n\n return useMemo(\n () => ({\n id: node.id,\n type: node.flowNodeType,\n get data() {\n if (form) {\n formValueDependRef.current = true;\n return form.values;\n }\n return getExtInfo();\n },\n updateData(values: any) {\n if (form) {\n form.updateFormValues(values);\n } else {\n updateExtInfo(values);\n }\n },\n node,\n selected,\n activated,\n expanded,\n startDrag,\n get ports() {\n return portsData.allPorts;\n },\n deleteNode,\n selectNode,\n readonly,\n linkingNodeId,\n nodeRef,\n onFocus,\n onBlur,\n getExtInfo,\n updateExtInfo,\n toggleExpand,\n get form() {\n if (!form) return undefined;\n return {\n ...form,\n get values() {\n formValueDependRef.current = true;\n return form.values!;\n },\n get state() {\n return formState;\n },\n };\n },\n }),\n [\n node,\n selected,\n activated,\n expanded,\n startDrag,\n deleteNode,\n selectNode,\n readonly,\n linkingNodeId,\n nodeRef,\n onFocus,\n onBlur,\n getExtInfo,\n updateExtInfo,\n toggleExpand,\n formValueVersion,\n ]\n );\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { inject, injectable } from 'inversify';\nimport {\n type Entity,\n Playground,\n SelectionService,\n TransformData,\n type PlaygroundConfigRevealOpts,\n} from '@flowgram.ai/core';\nimport { type Event, Rectangle, SizeSchema } from '@flowgram.ai/utils';\n\nimport { delay } from '../utils';\nimport { WorkflowNodeEntity } from '../entities';\nimport { type WorkfloEntityHoverable } from './workflow-hover-service';\n\n@injectable()\nexport class WorkflowSelectService {\n @inject(SelectionService) protected selectionService: SelectionService;\n\n @inject(Playground) protected playground: Playground;\n\n get onSelectionChanged(): Event<void> {\n return this.selectionService.onSelectionChanged;\n }\n\n get selection(): Entity[] {\n return this.selectionService.selection;\n }\n\n set selection(entities: Entity[]) {\n this.selectionService.selection = entities;\n }\n\n /**\n * 当前激活的节点只能有一个\n */\n get activatedNode(): WorkflowNodeEntity | undefined {\n const { selectedNodes } = this;\n if (selectedNodes.length !== 1) {\n return undefined;\n }\n return selectedNodes[0];\n }\n\n isSelected(id: string): boolean {\n return this.selectionService.selection.some(s => s.id === id);\n }\n\n isActivated(id: string): boolean {\n return this.activatedNode?.id === id;\n }\n\n /**\n * 选中的节点\n */\n get selectedNodes(): WorkflowNodeEntity[] {\n return this.selectionService.selection.filter(\n n => n instanceof WorkflowNodeEntity,\n ) as WorkflowNodeEntity[];\n }\n\n /**\n * 选中\n * @param node\n */\n selectNode(node: WorkflowNodeEntity): void {\n this.selectionService.selection = [node];\n }\n\n toggleSelect(node: WorkflowNodeEntity): void {\n if (this.selectionService.selection.includes(node)) {\n this.selectionService.selection = this.selectionService.selection.filter(n => n !== node);\n } else {\n this.selectionService.selection = this.selectionService.selection.concat(node);\n }\n }\n\n select(node: WorkfloEntityHoverable): void {\n this.selectionService.selection = [node];\n }\n\n clear(): void {\n this.selectionService.selection = [];\n }\n\n /**\n * 选中并滚动到节点\n * @param node\n */\n async selectNodeAndScrollToView(node: WorkflowNodeEntity, fitView?: boolean): Promise<void> {\n this.selectNodeAndFocus(node);\n const DELAY_TIME = 30;\n // 等待节点渲染完成(一般用于刚添加的节点)\n await delay(DELAY_TIME);\n\n const scrollConfig: PlaygroundConfigRevealOpts = {\n entities: [node],\n };\n\n if (fitView) {\n const bounds = Rectangle.enlarge([node.getData<TransformData>(TransformData).bounds]).pad(\n 30,\n 30,\n ); // 留出 30 像素的边界\n\n const viewport = this.playground.config.getViewport(false);\n\n const zoom = SizeSchema.fixSize(bounds, viewport);\n\n scrollConfig.zoom = zoom;\n scrollConfig.scrollToCenter = true;\n scrollConfig.easing = true;\n }\n\n return this.playground.config.scrollToView(scrollConfig);\n }\n\n selectNodeAndFocus(node: WorkflowNodeEntity): void {\n // 新添加的节点需要被选中\n this.select(node);\n // 拖进来需要让画布聚焦, 才能使用快捷键删除\n this.playground.node.focus();\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { bindConfigEntity } from '@flowgram.ai/core';\nexport { delay } from '@flowgram.ai/utils';\n\n/**\n * 让 entity 可以注入到类中\n *\n * @example\n * ```\n * class SomeClass {\n * @inject(PlaygroundConfigEntity) playgroundConfig: PlaygroundConfigEntity\n * }\n * ```\n * @param bind\n * @param entityRegistry\n */\nexport { bindConfigEntity };\n\nexport { buildGroupJSON } from './build-group-json';\nexport { getLineCenter } from './get-line-center';\nexport * from './nanoid';\nexport * from './compose';\nexport * from './fit-view';\nexport * from './get-anti-overlap-position';\nexport * from './statics';\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { FlowNodeBaseType } from '@flowgram.ai/document';\n\nimport { WorkflowJSON, WorkflowNodeJSON } from '../typings';\n\ninterface WorkflowGroupJSON extends WorkflowNodeJSON {\n data: {\n parentID?: string;\n blockIDs?: string[];\n };\n}\n\nexport const buildGroupJSON = (json: WorkflowJSON): WorkflowJSON => {\n const { nodes, edges } = json;\n const groupJSONs = nodes.filter(\n (nodeJSON) => nodeJSON.type === FlowNodeBaseType.GROUP\n ) as WorkflowGroupJSON[];\n\n const nodeJSONMap = new Map<string, WorkflowNodeJSON>(nodes.map((n) => [n.id, n]));\n const groupNodeJSONs = groupJSONs.map((groupJSON): WorkflowNodeJSON => {\n const groupBlocks = (groupJSON.data.blockIDs ?? [])\n .map((blockID) => nodeJSONMap.get(blockID))\n .filter(Boolean) as WorkflowNodeJSON[];\n const groupEdges = edges?.filter((edge) =>\n groupBlocks.some((block) => block.id === edge.sourceNodeID || block.id === edge.targetNodeID)\n );\n const groupNodeJSON: WorkflowNodeJSON = {\n ...groupJSON,\n blocks: groupBlocks,\n edges: groupEdges,\n };\n return groupNodeJSON;\n });\n\n const groupBlockSet = new Set(groupJSONs.map((groupJSON) => groupJSON.data.blockIDs).flat());\n const processedNodes = nodes\n .filter((nodeJSON) => !groupBlockSet.has(nodeJSON.id))\n .concat(groupNodeJSONs);\n return {\n nodes: processedNodes,\n edges,\n };\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { IPoint, Rectangle } from '@flowgram.ai/utils';\n\nimport { LineCenterPoint } from '../typings';\n\nexport function getLineCenter(\n from: IPoint,\n to: IPoint,\n bbox: Rectangle,\n linePadding: number\n): LineCenterPoint {\n return {\n x: bbox.center.x,\n y: bbox.center.y,\n labelX: bbox.center.x - bbox.x + linePadding,\n labelY: bbox.center.y - bbox.y + linePadding,\n };\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { nanoid as nanoidOrigin } from 'nanoid';\n\nexport function nanoid(n?: number): string {\n return nanoidOrigin(n);\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport { compose, composeAsync } from '@flowgram.ai/utils';\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Rectangle } from '@flowgram.ai/utils';\nimport { type PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\n\nimport { type WorkflowDocument } from '../workflow-document';\n\nexport const fitView = (\n doc: WorkflowDocument,\n playgroundConfig: PlaygroundConfigEntity,\n easing = true\n) => {\n const bounds = Rectangle.enlarge(\n doc.getAllNodes().map((node) => node.getData<TransformData>(TransformData).bounds)\n );\n // 留出 30 像素的边界\n return playgroundConfig.fitView(bounds, easing, 30);\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { TransformData } from '@flowgram.ai/core';\nimport { type IPoint } from '@flowgram.ai/utils';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport { WorkflowNodeEntity } from '../entities';\n\n/**\n * 获取没有碰撞的位置\n * 距离很小时,xy 各偏移 30\n * @param position\n */\nexport function getAntiOverlapPosition(\n doc: WorkflowDocument,\n position: IPoint,\n containerNode?: WorkflowNodeEntity,\n): IPoint {\n let { x, y } = position;\n const nodes = containerNode ? containerNode.collapsedChildren : doc.getAllNodes();\n const positions = nodes\n .map(n => {\n const transform = n.getData<TransformData>(TransformData)!;\n return { x: transform.position.x, y: transform.position.y };\n })\n .sort((a, b) => a.y - b.y);\n const minDistance = 3;\n for (const pos of positions) {\n const { x: posX, y: posY } = pos;\n if (y - posY < -minDistance) {\n break;\n }\n const deltaX = Math.abs(x - posX);\n const deltaY = Math.abs(y - posY);\n if (deltaX <= minDistance && deltaY <= minDistance) {\n x += 30;\n y += 30;\n }\n }\n return { x, y };\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Rectangle } from '@flowgram.ai/utils';\n\nimport { type WorkflowNodeEntity } from '../entities/workflow-node-entity';\nexport type WorkflowPortType = 'input' | 'output';\n\nexport const getPortEntityId = (\n node: WorkflowNodeEntity,\n portType: WorkflowPortType,\n portID: string | number = '',\n): string => `port_${portType}_${node.id}_${portID}`;\n\nexport const WORKFLOW_LINE_ENTITY = 'WorkflowLineEntity';\n\nexport function domReactToBounds(react: DOMRect): Rectangle {\n return new Rectangle(react.x, react.y, react.width, react.height);\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { FlowNodeEntity } from '@flowgram.ai/document';\n\nexport type WorkflowNodeEntity = FlowNodeEntity;\nexport const WorkflowNodeEntity = FlowNodeEntity;\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { isEqual } from 'lodash-es';\nimport { domUtils, type IPoint, Rectangle, Emitter } from '@flowgram.ai/utils';\nimport { Entity, type EntityOpts } from '@flowgram.ai/core';\n\nimport { type WorkflowLinesManager } from '../workflow-lines-manager';\nimport { type WorkflowDocument } from '../workflow-document';\nimport { WORKFLOW_LINE_ENTITY } from '../utils/statics';\nimport {\n LineRenderType,\n type LinePosition,\n LinePoint,\n LineCenterPoint,\n} from '../typings/workflow-line';\nimport { type WorkflowEdgeJSON } from '../typings';\nimport { WorkflowNodePortsData } from '../entity-datas/workflow-node-ports-data';\nimport { WorkflowLineRenderData } from '../entity-datas';\nimport { type WorkflowPortEntity } from './workflow-port-entity';\nimport { type WorkflowNodeEntity } from './workflow-node-entity';\n\nexport const LINE_HOVER_DISTANCE = 8; // 线条 hover 的最小检测距离\nexport const POINT_RADIUS = 10;\n\nexport interface WorkflowLinePortInfo {\n from: string; // 前置节点 id\n to?: string; // 后置节点 id\n fromPort?: string | number; // 连线的 port 位置\n toPort?: string | number; // 连线的 port 位置\n data?: any;\n}\n\nexport interface WorkflowLineEntityOpts extends EntityOpts, WorkflowLinePortInfo {\n document: WorkflowDocument;\n linesManager: WorkflowLinesManager;\n drawingTo?: LinePoint;\n}\n\nexport interface WorkflowLineInfo extends WorkflowLinePortInfo {\n drawingTo?: LinePoint; // 正在画中的元素\n}\n\nexport interface WorkflowLineUIState {\n /**\n * 是否出错\n */\n hasError: boolean;\n /**\n * 流动\n */\n flowing: boolean;\n /**\n * 禁用\n */\n disabled: boolean;\n /**\n * 箭头反转\n */\n reverse: boolean;\n /**\n * 隐藏箭头\n */\n hideArrow: boolean;\n /**\n * 线条宽度\n * @default 2\n */\n strokeWidth?: number;\n /**\n * 选中后的线条宽度\n * @default 3\n */\n strokeWidthSelected?: number;\n /**\n * 收缩\n * @default 10\n */\n shrink: number;\n /**\n * @deprecated use `lockedColor` instead\n */\n highlightColor: string;\n /**\n * 曲率\n * only for Bezier,\n * @default 0.25\n */\n curvature: number;\n /**\n * Line locked color\n */\n lockedColor: string;\n /**\n * React className\n */\n className?: string;\n /**\n * React style\n */\n style?: React.CSSProperties;\n}\n\n/**\n * 线条\n */\nexport class WorkflowLineEntity extends Entity<WorkflowLineEntityOpts> {\n static type = WORKFLOW_LINE_ENTITY;\n\n /**\n * 转成线条 id\n * @param info\n */\n static portInfoToLineId(info: WorkflowLinePortInfo): string {\n const { from, to, fromPort, toPort } = info;\n return `${from}_${fromPort || ''}-${to || ''}_${toPort || ''}`;\n }\n\n private _onLineDataChangeEmitter = new Emitter<{ oldValue: any; newValue: any }>();\n\n readonly document: WorkflowDocument;\n\n readonly linesManager: WorkflowLinesManager;\n\n readonly onLineDataChange = this._onLineDataChangeEmitter.event;\n\n private _from: WorkflowNodeEntity;\n\n private _to?: WorkflowNodeEntity;\n\n private _lineData: any;\n\n private _uiState: WorkflowLineUIState = {\n hasError: false,\n flowing: false,\n disabled: false,\n hideArrow: false,\n reverse: false,\n shrink: 10,\n curvature: 0.25,\n highlightColor: '',\n lockedColor: '',\n };\n\n /**\n * 线条的 UI 状态\n */\n get uiState(): WorkflowLineUIState {\n return this._uiState;\n }\n\n /**\n * 更新线条的 ui 状态\n * @param newState\n */\n updateUIState(newState: Partial<WorkflowLineUIState>): void {\n let changed = false;\n Object.keys(newState).forEach((key: string) => {\n const value: any = newState[key as keyof WorkflowLineUIState] as any;\n if (this._uiState[key as keyof WorkflowLineUIState] !== value) {\n (this._uiState as any)[key as keyof WorkflowLineUIState] = value;\n changed = true;\n }\n });\n if (changed) {\n this.fireChange();\n }\n }\n\n /**\n * 线条的扩展数据\n */\n get lineData(): any {\n return this._lineData;\n }\n\n /**\n * 更新线条扩展数据\n * @param data\n */\n set lineData(newValue: any) {\n const oldValue = this._lineData;\n if (!isEqual(oldValue, newValue)) {\n this._lineData = newValue;\n this._onLineDataChangeEmitter.fire({ oldValue, newValue });\n this.fireChange();\n }\n }\n\n public stackIndex = 0;\n\n /**\n * 线条数据\n */\n info: WorkflowLineInfo = {\n from: '',\n };\n\n readonly isDrawing: boolean;\n\n /**\n * 线条 Portal 挂载的 div\n */\n private _node?: HTMLDivElement;\n\n constructor(opts: WorkflowLineEntityOpts) {\n super(opts);\n this.document = opts.document;\n this.linesManager = opts.linesManager;\n // 初始化\n this.initInfo({\n from: opts.from,\n to: opts.to,\n drawingTo: opts.drawingTo,\n fromPort: opts.fromPort,\n toPort: opts.toPort,\n data: opts.data,\n });\n if (opts.drawingTo) {\n this.isDrawing = true;\n }\n this.onEntityChange(() => {\n this.fromPort?.validate();\n this.toPort?.validate();\n });\n this.onDispose(() => {\n this.fromPort?.validate();\n this.toPort?.validate();\n });\n this.toDispose.push(this._onLineDataChangeEmitter);\n // this.onDispose(() => {\n // this._infoDispose.dispose();\n // });\n }\n\n /**\n * 获取线条的前置节点\n */\n get from(): WorkflowNodeEntity {\n return this._from;\n }\n\n /**\n * 获取线条的后置节点\n */\n get to(): WorkflowNodeEntity | undefined {\n return this._to;\n }\n\n get isHidden(): boolean {\n return this.highlightColor === this.linesManager.lineColor.hidden;\n }\n\n get inContainer(): boolean {\n const nodeInContainer = (node?: WorkflowNodeEntity) =>\n !!node?.parent && node.parent.flowNodeType !== 'root';\n return nodeInContainer(this.from) || nodeInContainer(this.to);\n }\n\n /**\n * 获取是否 testrun processing\n * @deprecated use `flowing` instead\n */\n get processing(): boolean {\n return this._uiState.flowing;\n }\n\n /**\n * 设置 testrun processing 状态\n * @deprecated use `flowing` instead\n */\n set processing(status: boolean) {\n this.flowing = status;\n }\n\n // 获取连线是否为错误态\n get hasError() {\n return this.uiState.hasError;\n }\n\n // 设置连线的错误态\n set hasError(hasError: boolean) {\n this.updateUIState({\n hasError,\n });\n if (this._node) {\n this._node.dataset.hasError = this.hasError ? 'true' : 'false';\n }\n }\n\n /**\n * 设置线条的后置节点\n */\n setToPort(toPort?: WorkflowPortEntity) {\n // 只有绘制中的线条才允许设置 port, 主要用于吸附到点\n if (!this.isDrawing) {\n throw new Error('[setToPort] only support drawing line.');\n }\n if (this.toPort === toPort) {\n return;\n }\n const prePort = this.toPort;\n if (\n toPort &&\n toPort.portType === 'input' &&\n this.linesManager.canAddLine(this.fromPort, toPort, true)\n ) {\n const { node, portID } = toPort;\n this._to = node;\n this.info.drawingTo = undefined;\n this.info.to = node.id;\n this.info.toPort = portID;\n } else {\n this._to = undefined;\n this.info.to = undefined;\n this.info.toPort = '';\n }\n /**\n * 移动到端口又快速移出,需要更新 prePort 的状态\n */\n if (prePort) {\n prePort.validate();\n }\n this.fireChange();\n }\n\n /**\n * 设置线条画线时的目标位置\n */\n set drawingTo(pos: LinePoint | undefined) {\n const oldDrawingTo = this.info.drawingTo;\n if (!pos) {\n this.info.drawingTo = undefined;\n this.fireChange();\n return;\n }\n if (!oldDrawingTo || pos.x !== oldDrawingTo.x || pos.y !== oldDrawingTo.y) {\n this.info.to = undefined;\n this.info.drawingTo = pos;\n this.fireChange();\n }\n }\n\n /**\n * 获取线条正在画线的位置\n */\n get drawingTo(): LinePoint | undefined {\n return this.info.drawingTo;\n }\n\n get highlightColor(): string {\n return this.uiState.highlightColor || '';\n }\n\n set highlightColor(highlightColor) {\n this.updateUIState({\n highlightColor,\n });\n }\n\n get lockedColor(): string {\n return this.uiState.lockedColor;\n }\n\n set lockedColor(lockedColor: string) {\n this.updateUIState({\n lockedColor,\n });\n }\n\n /**\n * 获取线条的边框位置大小\n */\n get bounds(): Rectangle {\n return this.getData(WorkflowLineRenderData).bounds;\n }\n\n get center(): LineCenterPoint {\n return this.getData(WorkflowLineRenderData).center;\n }\n\n /**\n * 获取点和线最接近的距离\n */\n getHoverDist(pos: IPoint): number {\n return this.getData(WorkflowLineRenderData).calcDistance(pos);\n }\n\n get fromPort(): WorkflowPortEntity {\n return this.from\n .getData(WorkflowNodePortsData)\n .getPortEntityByKey('output', this.info.fromPort);\n }\n\n get toPort(): WorkflowPortEntity | undefined {\n if (!this.to) {\n return undefined;\n }\n return this.to.getData(WorkflowNodePortsData).getPortEntityByKey('input', this.info.toPort);\n }\n\n /**\n * 获取线条真实的输入输出节点坐标\n */\n get position(): LinePosition {\n return this.getData(WorkflowLineRenderData).position;\n }\n\n /** 是否反转箭头 */\n get reverse(): boolean {\n return this.linesManager.isReverseLine(this, this.uiState.reverse);\n }\n\n /** 是否隐藏箭头 */\n get hideArrow(): boolean {\n return this.linesManager.isHideArrowLine(this, this.uiState.hideArrow);\n }\n\n /** 是否流动 */\n get flowing(): boolean {\n return this.linesManager.isFlowingLine(this, this.uiState.flowing);\n }\n\n set flowing(flowing: boolean) {\n if (this._uiState.flowing !== flowing) {\n this._uiState.flowing = flowing;\n this.fireChange();\n }\n }\n\n /** 是否禁用 */\n get disabled(): boolean {\n return this.linesManager.isDisabledLine(this, this.uiState.disabled);\n }\n\n /**\n * @deprecated\n */\n get vertical(): boolean {\n const fromLocation = this.fromPort.location;\n const toLocation = this.toPort?.location;\n if (toLocation) {\n return toLocation === 'top';\n } else {\n return fromLocation === 'bottom';\n }\n }\n\n /** 获取线条渲染器类型 */\n get renderType(): LineRenderType | undefined {\n return this.linesManager.setLineRenderType(this);\n }\n\n /** 获取线条样式 */\n get className(): string {\n return [this.linesManager.setLineClassName(this), this._uiState.className]\n .filter((s) => !!s)\n .join(' ');\n }\n\n get color(): string | undefined {\n return this.linesManager.getLineColor(this);\n }\n\n /**\n * 初始化线条\n * @param info 线条信息\n */\n protected initInfo(info: WorkflowLineInfo): void {\n if (!isEqual(info, this.info)) {\n this.info = info;\n this._from = this.document.getNode(info.from)!;\n this._to = info.to ? this.document.getNode(info.to) : undefined;\n this._lineData = info.data;\n this.fireChange();\n }\n }\n\n // 校验连线是否为错误态\n validate() {\n this.validateSelf();\n }\n\n /**\n * use `validate` instead\n * @deprecated\n */\n protected validateSelf() {\n const { fromPort, toPort } = this;\n\n if (fromPort) {\n this.hasError = this.linesManager.isErrorLine(fromPort, toPort, this.uiState.hasError);\n }\n }\n\n is(line: WorkflowLineEntity | WorkflowLinePortInfo): boolean {\n if (line instanceof WorkflowLineEntity) {\n return this === line;\n }\n return WorkflowLineEntity.portInfoToLineId(line as WorkflowLinePortInfo) === this.id;\n }\n\n canRemove(newLineInfo?: Required<WorkflowLinePortInfo>): boolean {\n return this.linesManager.canRemove(this, newLineInfo);\n }\n\n get node(): HTMLDivElement {\n if (this._node) return this._node;\n this._node = domUtils.createDivWithClass('gedit-flow-activity-line');\n this._node.dataset.testid = 'sdk.workflow.canvas.line';\n this._node.dataset.lineId = this.id;\n this._node.dataset.fromNodeId = this.from.id;\n this._node.dataset.fromPortId = this.fromPort?.id ?? '';\n this._node.dataset.toNodeId = this.to?.id ?? '';\n this._node.dataset.toPortId = this.toPort?.id ?? '';\n this._node.dataset.hasError = this.hasError ? 'true' : 'false';\n return this._node;\n }\n\n toJSON(): WorkflowEdgeJSON {\n const json: WorkflowEdgeJSON = {\n sourceNodeID: this.info.from,\n targetNodeID: this.info.to!,\n sourcePortID: this.info.fromPort,\n targetPortID: this.info.toPort,\n };\n if (this._lineData !== undefined) {\n json.data = this._lineData;\n }\n if (!json.sourcePortID) {\n delete json.sourcePortID;\n }\n if (!json.targetPortID) {\n delete json.targetPortID;\n }\n return json;\n }\n\n /** 触发线条渲染 */\n fireRender(): void {\n this.fireChange();\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { isEqual } from 'lodash-es';\nimport { FlowNodeRenderData } from '@flowgram.ai/document';\nimport { EntityData, SizeData } from '@flowgram.ai/core';\n\nimport { type WorkflowPortType, getPortEntityId } from '../utils/statics';\nimport { type LinePoint, LinePointLocation, type WorkflowNodeMeta } from '../typings';\nimport { WorkflowPortEntity } from '../entities/workflow-port-entity';\nimport { type WorkflowNodeEntity, type WorkflowPort, type WorkflowPorts } from '../entities';\n\n/**\n * 节点的点位信息\n * portsData 只监听点位的数目和类型,不监听点位的 position 变化\n */\nexport class WorkflowNodePortsData extends EntityData {\n public static readonly type = 'WorkflowNodePortsData';\n\n public readonly entity: WorkflowNodeEntity;\n\n /** 静态的 ports 数据 */\n protected _staticPorts: WorkflowPorts = [];\n\n /** 存储 port 实体的 id,用于判断 port 是否存在 */\n protected _portIDSet = new Set<string>();\n\n /** 上一次的 ports 数据,用于判断 ports 是否发生变化 */\n protected _prePorts: WorkflowPorts;\n\n constructor(entity: WorkflowNodeEntity) {\n super(entity);\n this.entity = entity;\n const meta = entity.getNodeMeta<WorkflowNodeMeta>();\n // 动态模式默认为空, 非动态模式默认左右两个点位\n const defaultPorts: WorkflowPorts = meta.useDynamicPort\n ? []\n : [{ type: 'input' }, { type: 'output' }];\n this._staticPorts = meta.defaultPorts?.slice() || defaultPorts;\n this.updatePorts(this._staticPorts);\n if (meta.useDynamicPort) {\n this.toDispose.push(\n // 只需要监听节点的大小,因为算的是相对位置\n entity.getData!(SizeData)!.onDataChange(() => {\n // 有可能节点被销毁了\n if (entity.getData!(SizeData).width && entity.getData!(SizeData).height) {\n this.updateDynamicPorts();\n }\n })\n );\n }\n this.onDispose(() => {\n this.allPorts.forEach((port) => port.dispose());\n });\n }\n\n public getDefaultData(): any {\n return {};\n }\n\n /**\n * Update all ports data, includes static ports and dynamic ports\n * @param ports\n */\n public updateAllPorts(ports?: WorkflowPorts) {\n const meta = this.entity.getNodeMeta<WorkflowNodeMeta>();\n if (ports) {\n this._staticPorts = ports;\n }\n if (meta.useDynamicPort) {\n this.updateDynamicPorts();\n } else {\n this.updatePorts(this._staticPorts);\n }\n }\n\n /**\n * @deprecated use `updateAllPorts` instead\n */\n public updateStaticPorts(ports: WorkflowPorts): void {\n this.updateAllPorts(ports);\n }\n\n /**\n * 动态计算点位,通过 dom 的 data-port-key\n */\n public updateDynamicPorts(): void {\n const domNode = this.entity.getData(FlowNodeRenderData)!.node;\n const elements = domNode.querySelectorAll<HTMLDivElement>('[data-port-id]');\n const staticPorts: WorkflowPorts = this._staticPorts;\n const dynamicPorts: WorkflowPorts = [];\n if (elements.length > 0) {\n dynamicPorts.push(\n ...Array.from(elements).map((element) => ({\n portID: element.getAttribute('data-port-id')!,\n type: element.getAttribute('data-port-type')! as WorkflowPortType,\n location: element.getAttribute('data-port-location')! as LinePointLocation,\n targetElement: element,\n }))\n );\n }\n this.updatePorts(staticPorts.concat(dynamicPorts));\n }\n\n /**\n * 根据 key 获取 port 实体\n */\n public getPortEntityByKey(\n portType: WorkflowPortType,\n portKey?: string | number\n ): WorkflowPortEntity {\n const entity = this.getOrCreatePortEntity({\n type: portType,\n portID: portKey,\n });\n return entity;\n }\n\n /**\n * 更新 ports 数据\n */\n protected updatePorts(ports: WorkflowPorts): void {\n if (!isEqual(this._prePorts, ports)) {\n const portKeys = ports.map((port) => this.getPortId(port.type, port.portID));\n this._portIDSet.forEach((portId) => {\n if (!portKeys.includes(portId)) {\n this.getPortEntity(portId)?.dispose();\n }\n });\n ports.forEach((port) => this.updatePortEntity(port));\n this._prePorts = ports;\n this.fireChange();\n }\n\n // Note: 为什么调用 port.validate 不够,需要调用 line.validate\n // 原因:假设有这样的连线:dynamic port → end 节点。\n // line.validate 时,line.fromPort 可能为 undefined(未创建实体),导致 end 节点上的 port 未正确校验\n // 所以需要在所有 port entities 准备完成后,通过再次调用 line.validate 来触发连线另一端的 port 更新\n this.allPorts.forEach((port) => {\n port.allLines.forEach((line) => {\n line.validate();\n });\n });\n }\n\n /**\n * 获取所有 port entities\n */\n public get allPorts(): WorkflowPortEntity[] {\n return Array.from(this._portIDSet)\n .map((portId) => this.getPortEntity(portId)!)\n .filter(Boolean); // dispose 时,会获取不到 port\n }\n\n /**\n * 获取输入点位\n */\n public get inputPorts(): WorkflowPortEntity[] {\n return this.allPorts.filter((port) => port.portType === 'input');\n }\n\n /**\n * 获取输出点位\n */\n public get outputPorts(): WorkflowPortEntity[] {\n return this.allPorts.filter((port) => port.portType === 'output');\n }\n\n /**\n * 获取输入点位置\n */\n public get inputPoints(): LinePoint[] {\n return this.inputPorts.map((port) => port.point);\n }\n\n /**\n * 获取输出点位置\n */\n public get outputPoints(): LinePoint[] {\n return this.inputPorts.map((port) => port.point);\n }\n\n /**\n * 根据 key 获取 输入点位置\n */\n public getInputPoint(key?: string | number): LinePoint {\n return this.getPortEntityByKey('input', key).point;\n }\n\n /**\n * 根据 key 获取输出点位置\n */\n public getOutputPoint(key?: string | number): LinePoint {\n return this.getPortEntityByKey('output', key).point;\n }\n\n /**\n * 获取 port 实体\n */\n protected getPortEntity(portId: string): WorkflowPortEntity | undefined {\n if (!this._portIDSet.has(portId)) {\n // 如果不是自身创建的 port,则返回 undefined\n return undefined;\n }\n return this.entity.entityManager.getEntityById<WorkflowPortEntity>(portId)!;\n }\n\n /**\n * 拼接 port 实体的 id\n */\n protected getPortId(portType: WorkflowPortType, portKey: string | number = ''): string {\n return getPortEntityId(this.entity, portType, portKey);\n }\n\n /**\n * 创建 port 实体\n */\n protected createPortEntity(portInfo: WorkflowPort): WorkflowPortEntity {\n const id = this.getPortId(portInfo.type, portInfo.portID);\n let portEntity = this.entity.entityManager.getEntityById<WorkflowPortEntity>(id);\n if (!portEntity) {\n portEntity = this.entity.entityManager.createEntity<WorkflowPortEntity>(WorkflowPortEntity, {\n id,\n node: this.entity,\n ...portInfo,\n });\n }\n portEntity.onDispose(() => {\n this._portIDSet.delete(id);\n });\n this._portIDSet.add(id);\n return portEntity;\n }\n\n /**\n * 获取或创建 port 实体\n */\n protected getOrCreatePortEntity(portInfo: WorkflowPort): WorkflowPortEntity {\n const id = this.getPortId(portInfo.type, portInfo.portID);\n return this.getPortEntity(id) ?? this.createPortEntity(portInfo);\n }\n\n /**\n * 更新 port 实体\n */\n protected updatePortEntity(portInfo: WorkflowPort): WorkflowPortEntity {\n const portEntity = this.getOrCreatePortEntity(portInfo);\n portEntity.update(portInfo);\n return portEntity;\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { type IPoint, Rectangle, Emitter, Compare } from '@flowgram.ai/utils';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport {\n Entity,\n type EntityOpts,\n PlaygroundConfigEntity,\n TransformData,\n type EntityRegistry,\n} from '@flowgram.ai/core';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport {\n type WorkflowPortType,\n getPortEntityId,\n WORKFLOW_LINE_ENTITY,\n domReactToBounds,\n} from '../utils/statics';\nimport { type WorkflowNodeMeta, LinePointLocation, LinePoint } from '../typings';\nimport { type WorkflowNodeEntity } from './workflow-node-entity';\nimport { type WorkflowLineEntity } from './workflow-line-entity';\n\n// port 的宽度\nexport const PORT_SIZE = 24;\n\nexport interface WorkflowPort {\n /**\n * 没有代表 默认连接点,默认 input 类型 为最左边中心,output 类型为最右边中心\n */\n portID?: string | number;\n /**\n * 输入或者输出点\n */\n type: WorkflowPortType;\n /**\n * 端口位置\n */\n location?: LinePointLocation;\n /**\n * 端口热区大小\n */\n size?: { width: number; height: number };\n /**\n * 相对于 position 的偏移\n */\n offset?: IPoint;\n /**\n * 禁用端口\n */\n disabled?: boolean;\n /**\n * 将点位渲染到该父节点上\n */\n targetElement?: HTMLElement;\n}\n\nexport type WorkflowPorts = WorkflowPort[];\n\nexport interface WorkflowPortEntityOpts extends EntityOpts, WorkflowPort {\n /**\n * port 属于哪个节点\n */\n node: WorkflowNodeEntity;\n}\n\n/**\n * Port 抽象的 Entity\n */\nexport class WorkflowPortEntity extends Entity<WorkflowPortEntityOpts> {\n static type = 'WorkflowPortEntity';\n\n readonly node: WorkflowNodeEntity;\n\n readonly portID: string | number = '';\n\n readonly portType: WorkflowPortType;\n\n private _disabled?: boolean;\n\n private _hasError = false;\n\n private _location?: LinePointLocation;\n\n private _size?: { width: number; height: number };\n\n private _offset?: IPoint;\n\n protected readonly _onErrorChangedEmitter = new Emitter<void>();\n\n onErrorChanged = this._onErrorChangedEmitter.event;\n\n targetElement?: HTMLElement;\n\n static getPortEntityId(\n node: WorkflowNodeEntity,\n portType: WorkflowPortType,\n portID: string | number = ''\n ): string {\n return getPortEntityId(node, portType, portID);\n }\n\n get position(): LinePointLocation | undefined {\n return this._location;\n }\n\n constructor(opts: WorkflowPortEntityOpts) {\n super(opts);\n this.portID = opts.portID || '';\n this.portType = opts.type;\n this._disabled = opts.disabled;\n this._offset = opts.offset;\n this._location = opts.location;\n this._size = opts.size;\n this.node = opts.node;\n this.updateTargetElement(opts.targetElement);\n this.toDispose.push(this.node.getData(TransformData)!.onDataChange(() => this.fireChange()));\n this.toDispose.push(this.node.onDispose(this.dispose.bind(this)));\n }\n\n // 获取连线是否为错误态\n get hasError() {\n return this._hasError;\n }\n\n // 设置连线的错误态,外部应使用 validate 进行更新\n set hasError(hasError: boolean) {\n if (hasError !== this._hasError) {\n this._hasError = hasError;\n this._onErrorChangedEmitter.fire();\n }\n }\n\n validate() {\n // 一个端口可能连接很多线,需要保证所有的连线都不包含错误\n const anyLineHasError = this.allLines.some((line) => {\n // 忽略已销毁和被隐藏的线\n if (line.disposed || line.isHidden) {\n return false;\n }\n\n return line.hasError;\n });\n // 如果没有连线错误,需校验端口自身错误\n const isPortHasError = (this.node.document as WorkflowDocument).isErrorPort(this);\n this.hasError = anyLineHasError || isPortHasError;\n }\n\n isErrorPort() {\n return (this.node.document as WorkflowDocument).isErrorPort(this, this.hasError);\n }\n\n get location(): LinePointLocation {\n if (this._location) {\n return this._location;\n }\n if (this.portType === 'input') {\n return 'left';\n }\n return 'right';\n }\n\n get point(): LinePoint {\n const { targetElement } = this;\n const { bounds } = this.node.getData(FlowNodeTransformData)!;\n const location = this.location;\n if (targetElement) {\n const pos = domReactToBounds(targetElement.getBoundingClientRect()).center;\n const point = this.entityManager\n .getEntity<PlaygroundConfigEntity>(PlaygroundConfigEntity)!\n .getPosFromMouseEvent({\n clientX: pos.x,\n clientY: pos.y,\n });\n return {\n x: point.x,\n y: point.y,\n location,\n };\n }\n let point = { x: 0, y: 0 };\n const offset = this._offset || { x: 0, y: 0 };\n switch (location) {\n case 'left':\n point = bounds.leftCenter;\n break;\n case 'top':\n point = bounds.topCenter;\n break;\n case 'right':\n point = bounds.rightCenter;\n break;\n case 'bottom':\n point = bounds.bottomCenter;\n break;\n }\n return {\n x: point.x + offset.x,\n y: point.y + offset.y,\n location,\n };\n }\n\n /**\n * 端口热区\n */\n get bounds(): Rectangle {\n const { point } = this;\n const size = this._size || { width: PORT_SIZE, height: PORT_SIZE };\n return new Rectangle(\n point.x - size.width / 2,\n point.y - size.height / 2,\n size.width,\n size.height\n );\n }\n\n isHovered(x: number, y: number): boolean {\n return this.bounds.contains(x, y);\n }\n\n /**\n * 相对节点左上角的位置\n */\n get relativePosition(): IPoint {\n const { point } = this;\n const { bounds } = this.node.getData(FlowNodeTransformData)!;\n return {\n x: point.x - bounds.x,\n y: point.y - bounds.y,\n };\n }\n\n updateTargetElement(el?: HTMLElement): void {\n if (el !== this.targetElement) {\n this.targetElement = el;\n this.fireChange();\n }\n }\n\n /**\n * 是否被禁用\n */\n get disabled(): boolean {\n const document = this.node.document as WorkflowDocument;\n if (typeof document.options.isDisabledPort === 'function') {\n return document.options.isDisabledPort(this);\n }\n if (this._disabled) {\n return true;\n }\n const meta = this.node.getNodeMeta<WorkflowNodeMeta>();\n if (this.portType === 'input') {\n return !!meta.inputDisable;\n }\n return !!meta.outputDisable;\n }\n\n /**\n * 当前点位上连接的线条\n * @deprecated use `availableLines` instead\n */\n get lines(): WorkflowLineEntity[] {\n return this.allLines.filter((line) => !line.isDrawing);\n }\n\n /**\n * 当前有效的线条,不包含正在画的线条和隐藏的线条(这个出现在线条重连会先把原来的线条隐藏)\n */\n get availableLines(): WorkflowLineEntity[] {\n return this.allLines.filter((line) => !line.isDrawing && !line.isHidden);\n }\n\n /**\n * 当前点位上连接的线条(包含 isDrawing === true 的线条)\n */\n get allLines() {\n const lines: WorkflowLineEntity[] = [];\n // TODO: 后续 sdk 支持 getEntitiesByType 单独根据 type 获取功能后修改\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const allLines = this.entityManager.getEntities<WorkflowLineEntity>({\n type: WORKFLOW_LINE_ENTITY,\n } as EntityRegistry);\n allLines.forEach((line) => {\n // 不包含 drawing 的线条\n if (line.toPort === this || line.fromPort === this) {\n lines.push(line);\n }\n });\n return lines;\n }\n\n update(data: Exclude<WorkflowPort, 'portID' | 'type'>) {\n let changed = false;\n if (data.targetElement !== this.targetElement) {\n this.targetElement = data.targetElement;\n changed = true;\n }\n if (data.location !== this._location) {\n this._location = data.location;\n changed = true;\n }\n if (Compare.isChanged(data.offset, this._offset)) {\n this._offset = data.offset;\n changed = true;\n }\n if (Compare.isChanged(data.size, this._size)) {\n this._size = data.size;\n changed = true;\n }\n if (data.disabled !== this._disabled) {\n this._disabled = data.disabled;\n changed = true;\n }\n if (changed) {\n this.fireChange();\n }\n }\n\n dispose(): void {\n // 点位被删除,对应的线条也要删除\n this.lines.forEach((l) => l.dispose());\n super.dispose();\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Disposable } from '@flowgram.ai/utils';\nimport { EntityData } from '@flowgram.ai/core';\n\nimport { type WorkflowLineEntity, type WorkflowNodeEntity } from '../entities';\n\nexport interface WorkflowNodeLines {\n inputLines: WorkflowLineEntity[];\n outputLines: WorkflowLineEntity[];\n}\n\n/**\n * 节点的关联的线条\n */\nexport class WorkflowNodeLinesData extends EntityData<WorkflowNodeLines> {\n static type = 'WorkflowNodeLinesData';\n\n entity: WorkflowNodeEntity;\n\n getDefaultData(): WorkflowNodeLines {\n return {\n inputLines: [],\n outputLines: [],\n };\n }\n\n constructor(entity: WorkflowNodeEntity) {\n super(entity);\n this.entity = entity;\n this.entity.preDispose.push(\n Disposable.create(() => {\n this.inputLines.slice().forEach((line) => line.dispose());\n this.outputLines.slice().forEach((line) => line.dispose());\n })\n );\n }\n\n /**\n * 输入线条\n */\n get inputLines(): WorkflowLineEntity[] {\n return this.data.inputLines;\n }\n\n /**\n * 输出线条\n */\n get outputLines(): WorkflowLineEntity[] {\n return this.data.outputLines;\n }\n\n get allLines(): WorkflowLineEntity[] {\n return this.data.inputLines.concat(this.data.outputLines);\n }\n\n get availableLines(): WorkflowLineEntity[] {\n return this.allLines.filter((line) => !line.isDrawing && !line.isHidden);\n }\n\n /**\n * 输入节点\n */\n get inputNodes(): WorkflowNodeEntity[] {\n return this.inputLines.map((l) => l.from!).filter(Boolean);\n }\n\n /**\n * 所有输入节点\n */\n get allInputNodes(): WorkflowNodeEntity[] {\n const nodeSet: Set<WorkflowNodeEntity> = new Set();\n\n const handleNode = (node: WorkflowNodeEntity): void => {\n if (nodeSet.has(node)) {\n return;\n }\n\n nodeSet.add(node);\n\n const { inputNodes } = node.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData)!;\n if (!inputNodes || !inputNodes.length) {\n return;\n }\n\n inputNodes.forEach((inputNode: WorkflowNodeEntity) => {\n // 如果 outputNode 和当前 node 是父子节点,则不向下遍历\n if (inputNode?.parent === node || node?.parent === inputNode) {\n return;\n }\n handleNode(inputNode);\n });\n };\n\n handleNode(this.entity);\n nodeSet.delete(this.entity);\n\n return Array.from(nodeSet);\n }\n\n /**\n * 输出节点\n */\n get outputNodes(): WorkflowNodeEntity[] {\n return this.outputLines.map((l) => l.to!).filter(Boolean);\n }\n\n /**\n * 输入输出节点\n */\n get allOutputNodes(): WorkflowNodeEntity[] {\n const nodeSet: Set<WorkflowNodeEntity> = new Set();\n\n const handleNode = (node: WorkflowNodeEntity): void => {\n if (nodeSet.has(node)) {\n return;\n }\n\n nodeSet.add(node);\n\n const { outputNodes } = node.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData)!;\n if (!outputNodes || !outputNodes.length) {\n return;\n }\n\n outputNodes.forEach((outputNode: WorkflowNodeEntity) => {\n // 如果 outputNode 和当前 node 是父子节点,则不向下遍历\n if (outputNode?.parent === node || node?.parent === outputNode) {\n return;\n }\n handleNode(outputNode);\n });\n };\n\n handleNode(this.entity);\n nodeSet.delete(this.entity);\n\n return Array.from(nodeSet);\n }\n\n addLine(line: WorkflowLineEntity): void {\n if (line.from === this.entity) {\n this.outputLines.push(line);\n } else {\n this.inputLines.push(line);\n }\n this.fireChange();\n }\n\n removeLine(line: WorkflowLineEntity): void {\n const { inputLines, outputLines } = this;\n const inputIndex = inputLines.indexOf(line);\n const outputIndex = outputLines.indexOf(line);\n if (inputIndex !== -1) {\n inputLines.splice(inputIndex, 1);\n this.fireChange();\n }\n if (outputIndex !== -1) {\n outputLines.splice(outputIndex, 1);\n this.fireChange();\n }\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { IPoint, Rectangle } from '@flowgram.ai/utils';\nimport { EntityData } from '@flowgram.ai/core';\n\nimport {\n LineCenterPoint,\n LinePosition,\n LineRenderType,\n WorkflowLineRenderContribution,\n WorkflowLineRenderContributionFactory,\n} from '../typings';\nimport { WorkflowLineEntity } from '../entities';\nimport { WorkflowNodePortsData } from './workflow-node-ports-data';\n\nexport interface WorkflowLineRenderDataSchema {\n version: string;\n contributions: Map<LineRenderType, WorkflowLineRenderContribution>;\n position: LinePosition;\n}\n\nexport class WorkflowLineRenderData extends EntityData<WorkflowLineRenderDataSchema> {\n static type = 'WorkflowLineRenderData';\n\n declare entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n super(entity);\n this.syncContributions();\n }\n\n public getDefaultData(): WorkflowLineRenderDataSchema {\n return {\n version: '',\n contributions: new Map(),\n position: {\n from: { x: 0, y: 0, location: 'right' },\n to: { x: 0, y: 0, location: 'left' },\n },\n };\n }\n\n public get renderVersion(): string {\n return this.data.version;\n }\n\n public get position(): LinePosition {\n return this.data.position;\n }\n\n public get path(): string {\n return this.currentLine?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n return this.currentLine?.calcDistance(pos) ?? Number.MAX_SAFE_INTEGER;\n }\n\n public get bounds(): Rectangle {\n return this.currentLine?.bounds ?? new Rectangle();\n }\n\n /**\n * 更新数据\n * WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排\n */\n public update(): void {\n this.syncContributions();\n const oldVersion = this.data.version;\n this.updatePosition();\n const newVersion = this.data.version;\n if (oldVersion === newVersion) {\n return;\n }\n this.data.version = newVersion;\n this.currentLine?.update({\n fromPos: this.data.position.from,\n toPos: this.data.position.to,\n });\n }\n\n private get lineType(): LineRenderType {\n return this.entity.renderType ?? this.entity.linesManager.lineType;\n }\n\n /**\n * 获取 center 位置\n */\n get center(): LineCenterPoint {\n return this.currentLine?.center || { x: 0, y: 0, labelX: 0, labelY: 0 };\n }\n\n /**\n * 更新版本\n * WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排\n */\n private updatePosition(): void {\n this.data.position.from = this.entity.from\n .getData(WorkflowNodePortsData)!\n .getOutputPoint(this.entity.info.fromPort);\n\n if (this.entity.info.drawingTo) {\n this.data.position.to = this.entity.info.drawingTo;\n } else {\n this.data.position.to = this.entity.to\n ?.getData(WorkflowNodePortsData)\n ?.getInputPoint(this.entity.info.toPort) ?? {\n x: this.data.position.from.x,\n y: this.data.position.from.y,\n location: this.data.position.from.location === 'right' ? 'left' : 'top',\n };\n }\n\n this.data.version = [\n this.lineType,\n this.data.position.from.x,\n this.data.position.from.y,\n this.data.position.from.location,\n this.data.position.to.x,\n this.data.position.to.y,\n this.data.position.to.location,\n ].join('-');\n }\n\n private get currentLine(): WorkflowLineRenderContribution | undefined {\n return this.data.contributions.get(this.lineType);\n }\n\n private syncContributions(): void {\n if (this.entity.linesManager.contributionFactories.length === this.data.contributions.size) {\n return;\n }\n this.entity.linesManager.contributionFactories.forEach((factory) => {\n this.registerContribution(factory);\n });\n }\n\n private registerContribution(contributionFactory: WorkflowLineRenderContributionFactory): void {\n if (this.data.contributions.has(contributionFactory.type)) {\n return;\n }\n const contribution = new contributionFactory(this.entity);\n this.data.contributions.set(contributionFactory.type, contribution);\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { inject, injectable } from 'inversify';\nimport { Emitter, type PositionSchema } from '@flowgram.ai/utils';\nimport { EntityManager } from '@flowgram.ai/core';\n\nimport {\n type WorkflowLineEntity,\n type WorkflowNodeEntity,\n type WorkflowPortEntity,\n} from '../entities';\n\n/**\n * 可 Hover 的节点 类型\n */\nexport type WorkflowEntityHoverable = WorkflowNodeEntity | WorkflowLineEntity | WorkflowPortEntity;\n\nexport interface HoverPosition {\n position: PositionSchema;\n target?: HTMLElement;\n}\n\n/** @deprecated */\nexport type WorkfloEntityHoverable = WorkflowEntityHoverable;\n/**\n * hover 状态管理\n */\n@injectable()\nexport class WorkflowHoverService {\n @inject(EntityManager) protected entityManager: EntityManager;\n\n protected onHoveredChangeEmitter = new Emitter<string>();\n\n protected onUpdateHoverPositionEmitter = new Emitter<HoverPosition>();\n\n readonly onHoveredChange = this.onHoveredChangeEmitter.event;\n\n readonly onUpdateHoverPosition = this.onUpdateHoverPositionEmitter.event;\n\n // 当前鼠标 hover 位置\n hoveredPos: PositionSchema = { x: 0, y: 0 };\n\n /**\n * 当前 hovered 的 节点或者线条或者点\n * 1: nodeId / lineId (节点 / 线条)\n * 2: nodeId:portKey (节点连接点)\n */\n hoveredKey = '';\n\n /**\n * 更新 hover 的内容\n * @param hoveredKey hovered key\n */\n updateHoveredKey(hoveredKey: string): void {\n if (this.hoveredKey !== hoveredKey) {\n this.hoveredKey = hoveredKey;\n this.onHoveredChangeEmitter.fire(hoveredKey);\n }\n }\n\n updateHoverPosition(position: PositionSchema, target?: HTMLElement): void {\n this.hoveredPos = position;\n this.onUpdateHoverPositionEmitter.fire({\n position,\n target,\n });\n }\n\n /**\n * 清空 hover 内容\n */\n clearHovered(): void {\n this.updateHoveredKey('');\n }\n\n /**\n * 判断是否 hover\n * @param nodeId hoveredKey\n * @returns 是否 hover\n */\n isHovered(nodeId: string): boolean {\n return nodeId === this.hoveredKey;\n }\n\n isSomeHovered(): boolean {\n return !!this.hoveredKey;\n }\n\n /**\n * 获取被 hover 的节点或线条\n */\n get hoveredNode(): WorkfloEntityHoverable | undefined {\n return this.entityManager.getEntityById(this.hoveredKey);\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport type React from 'react';\n\nimport { nanoid } from 'nanoid';\nimport { inject, injectable, postConstruct } from 'inversify';\nimport {\n domUtils,\n type IPoint,\n PromiseDeferred,\n Emitter,\n type PositionSchema,\n DisposableCollection,\n Rectangle,\n delay,\n Disposable,\n} from '@flowgram.ai/utils';\nimport {\n FlowNodeTransformData,\n FlowNodeType,\n FlowOperationBaseService,\n type FlowNodeEntity,\n} from '@flowgram.ai/document';\nimport { FlowNodeBaseType } from '@flowgram.ai/document';\nimport {\n CommandService,\n MouseTouchEvent,\n PlaygroundConfigEntity,\n PlaygroundDrag,\n type PlaygroundDragEvent,\n TransformData,\n} from '@flowgram.ai/core';\n\nimport { WorkflowLinesManager } from '../workflow-lines-manager';\nimport { WorkflowDocumentOptions } from '../workflow-document-option';\nimport { WorkflowDocument } from '../workflow-document';\nimport { LineEventProps, NodesDragEvent, OnDragLineEnd } from '../typings/workflow-drag';\nimport { LinePointLocation, type WorkflowNodeJSON, type WorkflowNodeMeta } from '../typings';\nimport { WorkflowNodePortsData } from '../entity-datas';\nimport {\n type WorkflowLineEntity,\n type WorkflowLinePortInfo,\n type WorkflowNodeEntity,\n type WorkflowPortEntity,\n} from '../entities';\nimport { WorkflowSelectService } from './workflow-select-service';\nimport { WorkflowHoverService } from './workflow-hover-service';\n\nconst DRAG_TIMEOUT = 100;\nconst DRAG_MIN_DELTA = 5;\nfunction checkDragSuccess(\n time: number,\n e: PlaygroundDragEvent,\n originLine?: WorkflowLineEntity\n): boolean {\n if (\n !originLine ||\n time > DRAG_TIMEOUT ||\n Math.abs(e.endPos.x - e.startPos.x) >= DRAG_MIN_DELTA ||\n Math.abs(e.endPos.y - e.startPos.y) >= DRAG_MIN_DELTA\n ) {\n return true;\n }\n return false;\n}\n\nfunction reverseLocation(sourceLocation: LinePointLocation): LinePointLocation {\n switch (sourceLocation) {\n case 'bottom':\n return 'top';\n case 'left':\n return 'right';\n case 'top':\n return 'bottom';\n case 'right':\n return 'left';\n }\n}\n\n@injectable()\nexport class WorkflowDragService {\n @inject(PlaygroundConfigEntity)\n protected playgroundConfig: PlaygroundConfigEntity;\n\n @inject(WorkflowHoverService) protected hoverService: WorkflowHoverService;\n\n @inject(WorkflowDocument) protected document: WorkflowDocument;\n\n @inject(WorkflowLinesManager) protected linesManager: WorkflowLinesManager;\n\n @inject(CommandService) protected commandService: CommandService;\n\n @inject(WorkflowSelectService) protected selectService: WorkflowSelectService;\n\n @inject(FlowOperationBaseService)\n protected operationService: FlowOperationBaseService;\n\n @inject(WorkflowDocumentOptions)\n readonly options: WorkflowDocumentOptions;\n\n private _onDragLineEventEmitter = new Emitter<LineEventProps>();\n\n readonly onDragLineEventChange = this._onDragLineEventEmitter.event;\n\n isDragging = false;\n\n private _nodesDragEmitter = new Emitter<NodesDragEvent>();\n\n readonly onNodesDrag = this._nodesDragEmitter.event;\n\n protected _toDispose = new DisposableCollection();\n\n private _droppableTransforms: FlowNodeTransformData[] = [];\n\n private _dropNode?: FlowNodeEntity;\n\n private posAdjusters: Set<\n (params: { selectedNodes: WorkflowNodeEntity[]; position: IPoint }) => IPoint\n > = new Set();\n\n private _onDragLineEndCallbacks: Map<string, OnDragLineEnd> = new Map();\n\n @postConstruct()\n init() {\n this._toDispose.pushAll([this._onDragLineEventEmitter, this._nodesDragEmitter]);\n if (this.options.onDragLineEnd) {\n this._toDispose.push(this.onDragLineEnd(this.options.onDragLineEnd));\n }\n }\n\n dispose() {\n this._toDispose.dispose();\n }\n\n /**\n * 拖拽选中节点\n * @param triggerEvent\n */\n async startDragSelectedNodes(triggerEvent: MouseEvent | React.MouseEvent): Promise<boolean> {\n let { selectedNodes } = this.selectService;\n if (\n selectedNodes.length === 0 ||\n this.playgroundConfig.readonly ||\n this.playgroundConfig.disabled ||\n this.isDragging\n ) {\n return Promise.resolve(false);\n }\n this.isDragging = true;\n const sameParent = this.childrenOfContainer(selectedNodes);\n if (sameParent && sameParent.flowNodeType !== FlowNodeBaseType.ROOT) {\n selectedNodes = [sameParent];\n }\n // 节点整体开始位置\n let startPosition = this.getNodesPosition(selectedNodes);\n // 单个节点开始位置\n let startPositions = selectedNodes.map((node) => {\n const transform = node.getData(TransformData);\n return { x: transform.position.x, y: transform.position.y };\n });\n let dragSuccess = false;\n const startTime = Date.now();\n const dragger = new PlaygroundDrag({\n onDragStart: (dragEvent) => {\n this._nodesDragEmitter.fire({\n type: 'onDragStart',\n nodes: selectedNodes,\n startPositions,\n dragEvent,\n triggerEvent,\n dragger,\n });\n },\n onDrag: (dragEvent) => {\n if (!dragSuccess && checkDragSuccess(Date.now() - startTime, dragEvent)) {\n dragSuccess = true;\n }\n\n // 计算拖拽偏移量\n const offset: IPoint = this.getDragPosOffset({\n event: dragEvent,\n selectedNodes,\n startPosition,\n });\n\n const positions: PositionSchema[] = [];\n\n selectedNodes.forEach((node, index) => {\n const transform = node.getData(TransformData);\n const nodeStartPosition = startPositions[index];\n const newPosition = {\n x: nodeStartPosition.x + offset.x,\n y: nodeStartPosition.y + offset.y,\n };\n transform.update({\n position: newPosition,\n });\n this.document.layout.updateAffectedTransform(node);\n positions.push(newPosition);\n });\n\n this._nodesDragEmitter.fire({\n type: 'onDragging',\n nodes: selectedNodes,\n startPositions,\n positions,\n dragEvent,\n triggerEvent,\n dragger,\n });\n },\n onDragEnd: (dragEvent) => {\n this.isDragging = false;\n this._nodesDragEmitter.fire({\n type: 'onDragEnd',\n nodes: selectedNodes,\n startPositions,\n dragEvent,\n triggerEvent,\n dragger,\n });\n },\n });\n const { clientX, clientY } = MouseTouchEvent.getEventCoord(triggerEvent);\n return dragger.start(clientX, clientY, this.playgroundConfig)?.then(() => dragSuccess);\n }\n\n /**\n * 通过拖入卡片添加\n * @param type\n * @param event\n * @param data 节点数据\n */\n async dropCard(\n type: string,\n event: { clientX: number; clientY: number },\n data?: Partial<WorkflowNodeJSON>,\n parent?: WorkflowNodeEntity\n ): Promise<WorkflowNodeEntity | undefined> {\n const mousePos = this.playgroundConfig.getPosFromMouseEvent(event);\n if (!this.playgroundConfig.getViewport().contains(mousePos.x, mousePos.y)) {\n // 鼠标范围不在画布之内\n return;\n }\n const position = this.adjustSubNodePosition(type, parent, mousePos);\n\n const node: WorkflowNodeEntity = await this.document.createWorkflowNodeByType(\n type,\n position,\n data,\n parent?.id\n );\n return node;\n }\n\n /**\n * 拖拽卡片到画布\n * 返回创建结果\n * @param type\n * @param event\n */\n async startDragCard(\n type: string,\n event: React.MouseEvent,\n data: Partial<WorkflowNodeJSON>,\n cloneNode?: (e: PlaygroundDragEvent) => HTMLDivElement // 创建拖拽的dom\n ): Promise<WorkflowNodeEntity | undefined> {\n let domNode: HTMLDivElement;\n let startPos: IPoint = { x: 0, y: 0 };\n const deferred = new PromiseDeferred<WorkflowNodeEntity | undefined>();\n const dragger = new PlaygroundDrag({\n onDragStart: (e) => {\n const targetNode = event.currentTarget as HTMLDivElement;\n domNode = cloneNode ? cloneNode(e) : (targetNode.cloneNode(true) as HTMLDivElement);\n const bounds = targetNode.getBoundingClientRect();\n startPos = { x: bounds.left + window.scrollX, y: bounds.top + window.scrollY };\n domUtils.setStyle(domNode, {\n zIndex: 1000,\n position: 'absolute',\n left: startPos.x,\n top: startPos.y,\n boxShadow: '0 6px 8px 0 rgba(28, 31, 35, .2)',\n });\n document.body.appendChild(domNode);\n this.updateDroppableTransforms();\n },\n onDrag: (e) => {\n const deltaX = e.endPos.x - e.startPos.x;\n const deltaY = e.endPos.y - e.startPos.y;\n const left = startPos.x + deltaX;\n const right = startPos.y + deltaY;\n domNode.style.left = `${left}px`;\n domNode.style.top = `${right}px`;\n // 节点类型拖拽碰撞检测\n const { x, y } = this.playgroundConfig.getPosFromMouseEvent(e);\n const draggingRect = new Rectangle(x, y, 170, 90);\n const collisionTransform = this._droppableTransforms.find((transform) => {\n const { bounds, entity } = transform;\n const padding = this.document.layout.getPadding(entity);\n const transformRect = new Rectangle(\n bounds.x + padding.left + padding.right,\n bounds.y,\n bounds.width,\n bounds.height\n );\n // 检测两个正方形是否相互碰撞\n return Rectangle.intersects(draggingRect, transformRect);\n });\n this.updateDropNode(collisionTransform?.entity);\n },\n onDragEnd: async (e) => {\n const dropNode = this._dropNode;\n const { allowDrop } = this.canDropToNode({\n dragNodeType: type,\n dropNodeType: dropNode?.flowNodeType,\n dropNode,\n });\n const dragNode = allowDrop ? await this.dropCard(type, e, data, dropNode) : undefined;\n this.clearDrop();\n if (dragNode) {\n domNode.remove();\n deferred.resolve(dragNode);\n } else {\n domNode.style.transition = 'all ease .2s';\n domNode.style.left = `${startPos.x}px`;\n domNode.style.top = `${startPos.y}px`;\n const TIMEOUT = 200;\n await delay(TIMEOUT);\n domNode.remove();\n deferred.resolve();\n }\n },\n });\n await dragger.start(event.clientX, event.clientY);\n return deferred.promise;\n }\n\n /**\n * 如果存在容器节点,且传入鼠标坐标,需要用容器的坐标减去传入的鼠标坐标\n */\n public adjustSubNodePosition(\n subNodeType?: string,\n containerNode?: WorkflowNodeEntity,\n mousePos?: IPoint\n ): IPoint {\n if (!mousePos) {\n return { x: 0, y: 0 };\n }\n if (!subNodeType || !containerNode || containerNode.flowNodeType === FlowNodeBaseType.ROOT) {\n return mousePos;\n }\n const isParentEmpty = !containerNode.children || containerNode.children.length === 0;\n const parentPadding = this.document.layout.getPadding(containerNode);\n const containerWorldTransform = containerNode.transform.transform.worldTransform;\n if (isParentEmpty) {\n // 确保空容器节点不偏移\n return {\n x: 0,\n y: parentPadding.top,\n };\n } else {\n return {\n x: mousePos.x - containerWorldTransform.tx,\n y: mousePos.y - containerWorldTransform.ty,\n };\n }\n }\n\n /**\n * 注册位置调整\n */\n public registerPosAdjuster(\n adjuster: (params: { selectedNodes: WorkflowNodeEntity[]; position: IPoint }) => IPoint\n ) {\n this.posAdjusters.add(adjuster);\n return {\n dispose: () => this.posAdjusters.delete(adjuster),\n };\n }\n\n /**\n * 判断是否可以放置节点\n */\n\n public canDropToNode(params: {\n dragNodeType?: FlowNodeType;\n dragNode?: WorkflowNodeEntity;\n dropNode?: WorkflowNodeEntity;\n dropNodeType?: FlowNodeType;\n }): {\n allowDrop: boolean;\n message?: string;\n dropNode?: WorkflowNodeEntity;\n } {\n const { canDropToNode } = this.document.options;\n const { dragNodeType, dropNode } = params;\n if (canDropToNode) {\n const result = canDropToNode(params);\n if (result) {\n return {\n allowDrop: true,\n dropNode,\n };\n }\n return {\n allowDrop: false,\n };\n }\n if (!dragNodeType) {\n return {\n allowDrop: false,\n message: 'Please select a node to drop',\n };\n }\n return {\n allowDrop: true,\n dropNode,\n };\n }\n\n /**\n * 获取拖拽偏移\n */\n private getDragPosOffset(params: {\n event: PlaygroundDragEvent;\n selectedNodes: WorkflowNodeEntity[];\n startPosition: IPoint;\n }) {\n const { event, selectedNodes, startPosition } = params;\n const { finalScale } = this.playgroundConfig;\n const mouseOffset: IPoint = {\n x: (event.endPos.x - event.startPos.x) / finalScale,\n y: (event.endPos.y - event.startPos.y) / finalScale,\n };\n const wholePosition: IPoint = {\n x: startPosition.x + mouseOffset.x,\n y: startPosition.y + mouseOffset.y,\n };\n const adjustedOffsets: IPoint[] = Array.from(this.posAdjusters.values()).map((adjuster) =>\n adjuster({\n selectedNodes,\n position: wholePosition,\n })\n );\n const offset: IPoint = adjustedOffsets.reduce(\n (offset, adjustOffset) => ({\n x: offset.x + adjustOffset.x,\n y: offset.y + adjustOffset.y,\n }),\n mouseOffset\n );\n return offset;\n }\n\n private updateDroppableTransforms() {\n this._droppableTransforms = this.document\n .getRenderDatas(FlowNodeTransformData, false)\n .filter((transform) => {\n const { entity } = transform;\n if (entity.originParent) {\n return this.nodeSelectable(entity) && this.nodeSelectable(entity.originParent);\n }\n return this.nodeSelectable(entity);\n })\n .filter((transform) => this.isContainer(transform.entity));\n }\n\n /** 是否容器节点 */\n private isContainer(node?: WorkflowNodeEntity): boolean {\n return node?.getNodeMeta<WorkflowNodeMeta>().isContainer ?? false;\n }\n\n /**\n * 获取节点整体位置\n */\n private getNodesPosition(nodes: WorkflowNodeEntity[]): IPoint {\n const selectedBounds = Rectangle.enlarge(\n nodes.map((n) => n.getData(FlowNodeTransformData)!.bounds)\n );\n const position: IPoint = {\n x: selectedBounds.x,\n y: selectedBounds.y,\n };\n return position;\n }\n\n private nodeSelectable(node: FlowNodeEntity) {\n const selectable = node.getNodeMeta().selectable;\n if (typeof selectable === 'function') {\n return selectable(node);\n } else {\n return selectable;\n }\n }\n\n private updateDropNode(node?: FlowNodeEntity) {\n if (this._dropNode) {\n if (this._dropNode.id === node?.id) {\n return;\n }\n this.selectService.clear();\n }\n if (node) {\n this.selectService.selectNode(node);\n }\n this._dropNode = node;\n }\n\n private clearDrop() {\n if (this._dropNode) {\n this.selectService.clear();\n }\n this._dropNode = undefined;\n this._droppableTransforms = [];\n }\n\n private setLineColor(line: WorkflowLineEntity, color: string) {\n line.highlightColor = color;\n this.hoverService.clearHovered();\n }\n\n private handleDragOnNode(\n toNode: WorkflowNodeEntity,\n fromPort: WorkflowPortEntity,\n line: WorkflowLineEntity,\n toPort?: WorkflowPortEntity,\n originLine?: WorkflowLineEntity\n ): {\n hasError: boolean;\n } {\n if (\n toPort &&\n (originLine?.toPort === toPort ||\n (toPort.portType === 'input' && this.linesManager.canAddLine(fromPort, toPort, true)))\n ) {\n // 同一条线条则不用在判断 canAddLine\n this.hoverService.updateHoveredKey(toPort.id);\n line.setToPort(toPort);\n this._onDragLineEventEmitter.fire({\n type: 'onDrag',\n onDragNodeId: toNode.id,\n });\n return {\n hasError: false,\n };\n } else if (this.isContainer(toNode)) {\n // 在容器内进行连线的情况,需忽略\n return {\n hasError: false,\n };\n } else {\n this.setLineColor(line, this.linesManager.lineColor.error);\n return {\n hasError: true,\n };\n }\n }\n\n private childrenOfContainer(nodes: WorkflowNodeEntity[]): WorkflowNodeEntity | undefined {\n if (nodes.length === 0) {\n return;\n }\n const sourceContainer = nodes[0]?.parent;\n if (!sourceContainer || sourceContainer.collapsedChildren.length !== nodes.length) {\n return;\n }\n const valid = nodes.every((node) => node?.parent === sourceContainer);\n if (!valid) {\n return;\n }\n return sourceContainer;\n }\n\n /**\n * 绘制线条\n * @param opts\n * @param event\n */\n async startDrawingLine(\n fromPort: WorkflowPortEntity,\n event: { clientX: number; clientY: number },\n originLine?: WorkflowLineEntity\n ): Promise<{\n dragSuccess?: boolean; // 是否拖拽成功,不成功则为选择节点\n newLine?: WorkflowLineEntity; // 新的线条\n }> {\n const isFromInActivePort = !originLine && fromPort.isErrorPort() && fromPort.disabled;\n if (\n originLine?.disabled ||\n isFromInActivePort ||\n this.playgroundConfig.readonly ||\n this.playgroundConfig.disabled\n ) {\n return { dragSuccess: false, newLine: undefined };\n }\n\n this.selectService.clear();\n const config = this.playgroundConfig;\n const deferred = new PromiseDeferred<{\n dragSuccess?: boolean;\n newLine?: WorkflowLineEntity; // 新的线条\n }>();\n const preCursor = config.cursor;\n let line: WorkflowLineEntity | undefined,\n toPort: WorkflowPortEntity | undefined,\n toNode: WorkflowNodeEntity | undefined,\n lineErrorReset = false;\n const startTime = Date.now();\n let dragSuccess = false;\n const dragger = new PlaygroundDrag({\n onDrag: (e) => {\n if (!line && checkDragSuccess(Date.now() - startTime, e, originLine)) {\n // 隐藏原来的线条\n if (originLine) {\n originLine.highlightColor = this.linesManager.lineColor.hidden;\n }\n dragSuccess = true;\n const pos = config.getPosFromMouseEvent(event);\n // 创建临时的线条\n line = this.linesManager.createLine({\n from: fromPort.node.id,\n fromPort: fromPort.portID,\n data: originLine?.lineData,\n drawingTo: {\n x: pos.x,\n y: pos.y,\n location: fromPort.location === 'right' ? 'left' : 'top',\n },\n });\n if (!line) {\n return;\n }\n config.updateCursor('grab');\n line.highlightColor = originLine?.lockedColor || this.linesManager.lineColor.drawing;\n this.hoverService.updateHoveredKey('');\n }\n if (!line) {\n return;\n }\n\n lineErrorReset = false;\n\n const dragPos = config.getPosFromMouseEvent(e);\n\n // 默认 toNode 获取\n toNode = this.linesManager.getNodeFromMousePos(dragPos);\n // 默认 toPort 获取\n toPort = this.linesManager.getPortFromMousePos(dragPos);\n\n if (!toPort) {\n line.setToPort(undefined);\n } else if (!this.linesManager.canAddLine(fromPort, toPort, true)) {\n line.highlightColor = this.linesManager.lineColor.error;\n lineErrorReset = true;\n line.setToPort(undefined);\n } else {\n line.setToPort(toPort);\n }\n\n this._onDragLineEventEmitter.fire({\n type: 'onDrag',\n });\n\n this.setLineColor(line, originLine?.lockedColor || this.linesManager.lineColor.drawing);\n if (toNode && this.canBuildContainerLine(toNode, dragPos)) {\n // 如果鼠标 hover 在 node 中的时候,默认连线到这个 node 的初始位置\n toPort = this.getNearestPort(toNode, dragPos);\n const { hasError } = this.handleDragOnNode(toNode, fromPort, line, toPort, originLine);\n lineErrorReset = hasError;\n }\n\n if (line.toPort) {\n line.drawingTo = {\n x: line.toPort.point.x,\n y: line.toPort.point.y,\n location: line.toPort.location,\n };\n } else {\n line.drawingTo = {\n x: dragPos.x,\n y: dragPos.y,\n location: reverseLocation(line.fromPort.location),\n };\n }\n\n // 触发原 toPort 的校验\n originLine?.validate();\n line.validate();\n },\n // eslint-disable-next-line complexity\n onDragEnd: async (e) => {\n const dragPos = config.getPosFromMouseEvent(e);\n const onDragLineEndCallbacks = Array.from(this._onDragLineEndCallbacks.values());\n config.updateCursor(preCursor);\n await Promise.all(\n onDragLineEndCallbacks.map((callback) =>\n callback({\n fromPort,\n toPort,\n mousePos: dragPos,\n line,\n originLine,\n event: e,\n })\n )\n );\n line?.dispose();\n this._onDragLineEventEmitter.fire({\n type: 'onDragEnd',\n });\n // 清除选中状态\n if (originLine) {\n originLine.highlightColor = '';\n }\n const end = () => {\n originLine?.validate();\n deferred.resolve({ dragSuccess });\n };\n if (dragSuccess) {\n // Step 1: check same line\n if (originLine && originLine.toPort === toPort) {\n // 线条没变化则直接返回,不做处理\n return end();\n }\n // 非 input 节点不能连接\n if (toPort && toPort.portType !== 'input') {\n return end();\n }\n const newLineInfo: Required<WorkflowLinePortInfo> | undefined = toPort\n ? {\n from: fromPort.node.id,\n fromPort: fromPort.portID,\n to: toPort.node.id,\n toPort: toPort.portID,\n data: originLine?.lineData,\n }\n : undefined;\n // Step2: 检测 reset\n const isReset = originLine && toPort;\n if (\n isReset &&\n !this.linesManager.canReset(\n originLine.fromPort,\n originLine.toPort as WorkflowPortEntity,\n toPort as WorkflowPortEntity\n )\n ) {\n return end();\n }\n // Step 3: delete line\n if (\n originLine &&\n (!this.linesManager.canRemove(originLine, newLineInfo, false) || lineErrorReset)\n ) {\n // 线条无法删除则返回,不再触发 canAddLine\n return end();\n } else {\n originLine?.dispose();\n }\n // Step 4: add line\n if (!toPort || !this.linesManager.canAddLine(fromPort, toPort, false)) {\n // 无法添加成功\n return end();\n }\n const newLine = this.linesManager.createLine(newLineInfo as WorkflowLinePortInfo);\n if (!newLine) {\n end();\n }\n deferred.resolve({\n dragSuccess,\n newLine,\n });\n } else {\n end();\n }\n },\n });\n const { clientX, clientY } = MouseTouchEvent.getEventCoord(event);\n await dragger.start(clientX, clientY, config);\n return deferred.promise;\n }\n\n /**\n * 重新连接线条\n * @param line\n * @param e\n */\n async resetLine(line: WorkflowLineEntity, e: MouseEvent): Promise<void> {\n const { fromPort } = line;\n const { dragSuccess } = await this.startDrawingLine(fromPort, e, line);\n if (!dragSuccess) {\n // 没有拖拽成功则表示为选中节点\n this.selectService.select(line);\n }\n }\n\n /** 线条拖拽结束 */\n public onDragLineEnd(callback: OnDragLineEnd): Disposable {\n const id = nanoid();\n this._onDragLineEndCallbacks.set(id, callback);\n return {\n dispose: () => {\n this._onDragLineEndCallbacks.delete(id);\n },\n };\n }\n\n /** 能否建立容器连线 */\n private canBuildContainerLine(node: WorkflowNodeEntity, mousePos: IPoint): boolean {\n const isContainer = this.isContainer(node);\n if (!isContainer) {\n return true;\n }\n const { padding, bounds } = node.transform;\n const contentRect = new Rectangle(bounds.x, bounds.y, (padding.left * 2) / 3, bounds.height);\n return contentRect.contains(mousePos.x, mousePos.y);\n }\n\n /** 获取最近的 port */\n private getNearestPort(node: WorkflowNodeEntity, mousePos: IPoint): WorkflowPortEntity {\n const portsData = node.getData(WorkflowNodePortsData)!;\n const distanceSortedPorts = portsData.inputPorts.sort((a, b) => {\n const aDistance = Math.abs(mousePos.y - a.point.y);\n const bDistance = Math.abs(mousePos.y - b.point.y);\n return aDistance - bDistance;\n });\n return distanceSortedPorts[0];\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { last } from 'lodash-es';\nimport { inject, injectable } from 'inversify';\nimport { DisposableCollection, Emitter, type IPoint } from '@flowgram.ai/utils';\nimport { FlowNodeRenderData, FlowNodeTransformData } from '@flowgram.ai/document';\nimport { EntityManager, PlaygroundConfigEntity } from '@flowgram.ai/core';\n\nimport { WorkflowDocumentOptions } from './workflow-document-option';\nimport { type WorkflowDocument } from './workflow-document';\nimport {\n LineColor,\n LineColors,\n LinePoint,\n LineRenderType,\n LineType,\n type WorkflowLineRenderContributionFactory,\n} from './typings/workflow-line';\nimport {\n type WorkflowContentChangeEvent,\n WorkflowContentChangeType,\n type WorkflowEdgeJSON,\n WorkflowNodeRegistry,\n} from './typings';\nimport { WorkflowHoverService, WorkflowSelectService } from './service';\nimport { WorkflowNodeLinesData } from './entity-datas/workflow-node-lines-data';\nimport { WorkflowLineRenderData, WorkflowNodePortsData } from './entity-datas';\nimport {\n LINE_HOVER_DISTANCE,\n WorkflowLineEntity,\n type WorkflowLinePortInfo,\n type WorkflowNodeEntity,\n WorkflowPortEntity,\n} from './entities';\n\n/**\n * 线条管理\n */\n@injectable()\nexport class WorkflowLinesManager {\n protected document: WorkflowDocument;\n\n protected toDispose = new DisposableCollection();\n // 线条类型\n\n protected _lineType: LineRenderType = LineType.BEZIER;\n\n protected onAvailableLinesChangeEmitter = new Emitter<WorkflowContentChangeEvent>();\n\n protected onForceUpdateEmitter = new Emitter<void>();\n\n @inject(WorkflowHoverService) hoverService: WorkflowHoverService;\n\n @inject(WorkflowSelectService) selectService: WorkflowSelectService;\n\n @inject(EntityManager) protected readonly entityManager: EntityManager;\n\n @inject(WorkflowDocumentOptions)\n readonly options: WorkflowDocumentOptions;\n\n /**\n * 有效的线条被添加或者删除时候触发,未连上的线条不算\n */\n readonly onAvailableLinesChange = this.onAvailableLinesChangeEmitter.event;\n\n /**\n * 强制渲染 lines\n */\n readonly onForceUpdate = this.onForceUpdateEmitter.event;\n\n readonly contributionFactories: WorkflowLineRenderContributionFactory[] = [];\n\n init(doc: WorkflowDocument): void {\n this.document = doc;\n }\n\n forceUpdate() {\n this.onForceUpdateEmitter.fire();\n }\n\n get lineType() {\n return this._lineType;\n }\n\n get lineColor(): LineColor {\n const color: LineColor = {\n default: LineColors.DEFUALT,\n error: LineColors.ERROR,\n hidden: LineColors.HIDDEN,\n drawing: LineColors.DRAWING,\n hovered: LineColors.HOVER,\n selected: LineColors.SELECTED,\n flowing: LineColors.FLOWING,\n };\n if (this.options.lineColor) {\n Object.assign(color, this.options.lineColor);\n }\n return color;\n }\n\n switchLineType(newType?: LineRenderType): LineRenderType {\n if (newType === undefined) {\n if (this._lineType === LineType.BEZIER) {\n newType = LineType.LINE_CHART;\n } else {\n newType = LineType.BEZIER;\n }\n }\n if (newType !== this._lineType) {\n this._lineType = newType;\n // 更新线条数据\n this.getAllLines().forEach((line) => {\n line.getData(WorkflowLineRenderData).update();\n });\n window.requestAnimationFrame(() => {\n // 触发线条重渲染\n this.entityManager.fireEntityChanged(WorkflowLineEntity.type);\n });\n }\n return this._lineType;\n }\n\n getAllLines(): WorkflowLineEntity[] {\n return this.entityManager.getEntities(WorkflowLineEntity);\n }\n\n hasLine(portInfo: Omit<WorkflowLinePortInfo, 'data'>): boolean {\n return !!this.entityManager.getEntityById<WorkflowLineEntity>(\n WorkflowLineEntity.portInfoToLineId(portInfo)\n );\n }\n\n getLine(portInfo: Omit<WorkflowLinePortInfo, 'data'>): WorkflowLineEntity | undefined {\n return this.entityManager.getEntityById<WorkflowLineEntity>(\n WorkflowLineEntity.portInfoToLineId(portInfo)\n );\n }\n\n getLineById(id: string): WorkflowLineEntity | undefined {\n return this.entityManager.getEntityById<WorkflowLineEntity>(id);\n }\n\n replaceLine(\n oldPortInfo: Omit<WorkflowLinePortInfo, 'data'>,\n newPortInfo: Omit<WorkflowLinePortInfo, 'data'>\n ): WorkflowLineEntity {\n const oldLine = this.getLine(oldPortInfo);\n if (oldLine) {\n oldLine.dispose();\n }\n return this.createLine(newPortInfo)!;\n }\n\n createLine(\n options: {\n drawingTo?: LinePoint; // 无连接的线条\n key?: string; // 自定义 key\n } & WorkflowLinePortInfo\n ): WorkflowLineEntity | undefined {\n const { from, to, drawingTo, fromPort, toPort, data } = options;\n const available = Boolean(from && to);\n const key = options.key || WorkflowLineEntity.portInfoToLineId(options);\n let line = this.entityManager.getEntityById<WorkflowLineEntity>(key)!;\n if (line) {\n // 如果之前有线条,则先把颜色去掉\n line.highlightColor = '';\n line.validate();\n return line;\n }\n\n const fromNode = this.entityManager\n .getEntityById<WorkflowNodeEntity>(from)\n ?.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData);\n const toNode = to\n ? this.entityManager\n .getEntityById<WorkflowNodeEntity>(to)!\n .getData<WorkflowNodeLinesData>(WorkflowNodeLinesData)!\n : undefined;\n\n if (!fromNode) {\n // 非法情况\n return;\n }\n\n this.isDrawing = Boolean(drawingTo);\n line = this.entityManager.createEntity<WorkflowLineEntity>(WorkflowLineEntity, {\n id: key,\n document: this.document,\n linesManager: this,\n from,\n fromPort,\n toPort,\n to,\n drawingTo,\n data,\n });\n\n this.registerData(line);\n\n fromNode.addLine(line);\n toNode?.addLine(line);\n line.onDispose(() => {\n if (drawingTo) {\n this.isDrawing = false;\n }\n fromNode.removeLine(line);\n toNode?.removeLine(line);\n });\n line.onDispose(() => {\n if (available) {\n this.onAvailableLinesChangeEmitter.fire({\n type: WorkflowContentChangeType.DELETE_LINE,\n toJSON: () => line.toJSON(),\n entity: line,\n });\n }\n });\n line.onLineDataChange(({ oldValue }) => {\n this.onAvailableLinesChangeEmitter.fire({\n type: WorkflowContentChangeType.LINE_DATA_CHANGE,\n toJSON: () => line.toJSON(),\n oldValue,\n entity: line,\n });\n });\n // 是否为有效的线条\n if (available) {\n this.onAvailableLinesChangeEmitter.fire({\n type: WorkflowContentChangeType.ADD_LINE,\n toJSON: () => line.toJSON(),\n entity: line,\n });\n }\n // 创建时检验 连线错误态 & 端口错误态\n line.validate();\n return line;\n }\n\n /**\n * 获取线条中距离鼠标位置最近的线条和距离\n * @param mousePos 鼠标位置\n * @param minDistance 最小检测距离\n * @returns 距离鼠标位置最近的线条 以及距离\n */\n getCloseInLineFromMousePos(\n mousePos: IPoint,\n minDistance: number = LINE_HOVER_DISTANCE\n ): WorkflowLineEntity | undefined {\n let targetLine: WorkflowLineEntity | undefined, targetLineDist: number | undefined;\n this.getAllLines().forEach((line) => {\n const dist = line.getHoverDist(mousePos);\n\n if (dist <= minDistance && (!targetLineDist || targetLineDist >= dist)) {\n targetLineDist = dist;\n targetLine = line;\n }\n });\n return targetLine;\n }\n\n /**\n * 是否在调整线条\n */\n isDrawing = false;\n\n dispose(): void {\n this.toDispose.dispose();\n }\n\n get disposed(): boolean {\n return this.toDispose.disposed;\n }\n\n isErrorLine(fromPort: WorkflowPortEntity, toPort?: WorkflowPortEntity, defaultValue?: boolean) {\n if (this.options.isErrorLine) {\n return this.options.isErrorLine(fromPort, toPort, this);\n }\n\n return !!defaultValue;\n }\n\n isReverseLine(line: WorkflowLineEntity, defaultValue = false): boolean {\n if (this.options.isReverseLine) {\n return this.options.isReverseLine(line);\n }\n\n return defaultValue;\n }\n\n isHideArrowLine(line: WorkflowLineEntity, defaultValue = false): boolean {\n if (this.options.isHideArrowLine) {\n return this.options.isHideArrowLine(line);\n }\n\n return defaultValue;\n }\n\n isFlowingLine(line: WorkflowLineEntity, defaultValue = false): boolean {\n if (this.options.isFlowingLine) {\n return this.options.isFlowingLine(line);\n }\n\n return defaultValue;\n }\n\n isDisabledLine(line: WorkflowLineEntity, defaultValue = false): boolean {\n if (this.options.isDisabledLine) {\n return this.options.isDisabledLine(line);\n }\n return defaultValue;\n }\n\n setLineRenderType(line: WorkflowLineEntity): LineRenderType | undefined {\n if (this.options.setLineRenderType) {\n return this.options.setLineRenderType(line);\n }\n return undefined;\n }\n\n setLineClassName(line: WorkflowLineEntity): string | undefined {\n if (this.options.setLineClassName) {\n return this.options.setLineClassName(line);\n }\n return undefined;\n }\n\n getLineColor(line: WorkflowLineEntity): string | undefined {\n // 隐藏的优先级比 hasError 高\n if (line.isHidden) {\n return this.lineColor.hidden;\n }\n // 颜色锁定\n if (line.lockedColor) {\n return line.lockedColor;\n }\n if (line.hasError) {\n return this.lineColor.error;\n }\n if (line.highlightColor) {\n return line.highlightColor;\n }\n if (line.drawingTo) {\n return this.lineColor.drawing;\n }\n if (this.hoverService.isHovered(line.id)) {\n return this.lineColor.hovered;\n }\n if (this.selectService.isSelected(line.id)) {\n return this.lineColor.selected;\n }\n // 检查是否为流动线条\n if (this.isFlowingLine(line)) {\n return this.lineColor.flowing;\n }\n return this.lineColor.default;\n }\n\n canAddLine(fromPort: WorkflowPortEntity, toPort: WorkflowPortEntity, silent?: boolean): boolean {\n if (\n fromPort === toPort ||\n fromPort.node === toPort.node ||\n fromPort.portType !== 'output' ||\n toPort.portType !== 'input' ||\n toPort.disabled\n ) {\n return false;\n }\n const fromCanAdd = fromPort.node.getNodeRegistry<WorkflowNodeRegistry>().canAddLine;\n const toCanAdd = toPort.node.getNodeRegistry<WorkflowNodeRegistry>().canAddLine;\n if (fromCanAdd && !fromCanAdd(fromPort, toPort, this, silent)) {\n return false;\n }\n if (toCanAdd && !toCanAdd(fromPort, toPort, this, silent)) {\n return false;\n }\n if (this.options.canAddLine) {\n return this.options.canAddLine(fromPort, toPort, this, silent);\n }\n // 默认不能连接自己\n return fromPort.node !== toPort.node;\n }\n\n toJSON(): WorkflowEdgeJSON[] {\n return this.getAllLines()\n .filter((l) => !l.isDrawing)\n .map((l) => l.toJSON());\n }\n\n getPortById(portId: string): WorkflowPortEntity | undefined {\n return this.entityManager.getEntityById<WorkflowPortEntity>(portId);\n }\n\n canRemove(\n line: WorkflowLineEntity,\n newLineInfo?: Required<Omit<WorkflowLinePortInfo, 'data'>>,\n silent?: boolean\n ): boolean {\n if (\n this.options &&\n this.options.canDeleteLine &&\n !this.options.canDeleteLine(line, newLineInfo, silent)\n ) {\n return false;\n }\n return true;\n }\n\n canReset(\n fromPort: WorkflowPortEntity,\n oldToPort: WorkflowPortEntity,\n newToPort: WorkflowPortEntity\n ): boolean {\n if (\n this.options &&\n this.options.canResetLine &&\n !this.options.canResetLine(fromPort, oldToPort, newToPort, this)\n ) {\n return false;\n }\n return true;\n }\n\n /**\n * 根据鼠标位置找到 port\n * @param pos\n */\n getPortFromMousePos(pos: IPoint): WorkflowPortEntity | undefined {\n const allNodes = this.getSortedNodes().reverse();\n const allPorts = allNodes.map((node) => node.getData(WorkflowNodePortsData).allPorts).flat();\n const targetPort = allPorts.find((port) => port.isHovered(pos.x, pos.y));\n if (targetPort) {\n const containNodes = this.getContainNodesFromMousePos(pos);\n const targetNode = last(containNodes);\n // 点位可能会被节点覆盖\n if (targetNode && targetNode !== targetPort.node) {\n return;\n }\n }\n return targetPort;\n }\n\n /**\n * 根据鼠标位置找到 node\n * @param pos - 鼠标位置\n */\n getNodeFromMousePos(pos: IPoint): WorkflowNodeEntity | undefined {\n // 先挑选出 bounds 区域符合的 node\n const { selection } = this.selectService;\n const containNodes = this.getContainNodesFromMousePos(pos);\n // 当有元素被选中的时候选中元素在顶层\n if (selection?.length) {\n const filteredNodes = containNodes.filter((node) =>\n selection.some((_node) => node.id === _node.id)\n );\n if (filteredNodes?.length) {\n return last(filteredNodes);\n }\n }\n // 默认取最顶层的\n return last(containNodes);\n }\n\n registerContribution(factory: WorkflowLineRenderContributionFactory): this {\n this.contributionFactories.push(factory);\n return this;\n }\n\n private registerData(line: WorkflowLineEntity) {\n line.addData(WorkflowLineRenderData);\n }\n\n private getSortedNodes() {\n return this.document.getAllNodes().sort((a, b) => this.getNodeIndex(a) - this.getNodeIndex(b));\n }\n\n /** 获取鼠标坐标位置的所有节点(stackIndex 从小到大排序) */\n private getContainNodesFromMousePos(pos: IPoint): WorkflowNodeEntity[] {\n const allNodes = this.getSortedNodes();\n const zoom =\n this.entityManager.getEntity<PlaygroundConfigEntity>(PlaygroundConfigEntity)?.config?.zoom ||\n 1;\n const containNodes = allNodes\n .map((node) => {\n const { bounds } = node.getData<FlowNodeTransformData>(FlowNodeTransformData);\n // 交互要求,节点边缘 4px 的时候就认为选中节点\n if (\n bounds\n .clone()\n .pad(4 / zoom)\n .contains(pos.x, pos.y)\n ) {\n return node;\n }\n })\n .filter(Boolean) as WorkflowNodeEntity[];\n return containNodes;\n }\n\n private getNodeIndex(node: WorkflowNodeEntity): number {\n const nodeRenderData = node.getData(FlowNodeRenderData);\n return nodeRenderData.stackIndex;\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { FlowNodeErrorData } from '@flowgram.ai/form-core';\nimport { FlowDocumentOptions, FlowNodeTransformData, FlowNodeType } from '@flowgram.ai/document';\nimport { TransformData } from '@flowgram.ai/core';\n\nimport { type WorkflowLinesManager } from './workflow-lines-manager';\nimport { initFormDataFromJSON, toFormJSON } from './utils/flow-node-form-data';\nimport {\n LineColor,\n LineRenderType,\n onDragLineEndParams,\n WorkflowNodeJSON,\n WorkflowNodeMeta,\n} from './typings';\nimport {\n type WorkflowLineEntity,\n type WorkflowLinePortInfo,\n type WorkflowNodeEntity,\n type WorkflowPortEntity,\n} from './entities';\n\nexport const WorkflowDocumentOptions = Symbol('WorkflowDocumentOptions');\n\n/**\n * 线条配置\n */\nexport interface WorkflowDocumentOptions extends FlowDocumentOptions {\n cursors?: {\n grab?: string;\n grabbing?: string;\n };\n /** 线条颜色 */\n lineColor?: Partial<LineColor>;\n /** 是否显示错误线条 */\n isErrorLine?: (\n fromPort: WorkflowPortEntity,\n toPort: WorkflowPortEntity | undefined,\n lines: WorkflowLinesManager\n ) => boolean;\n /** 是否错误端口 */\n isErrorPort?: (port: WorkflowPortEntity) => boolean;\n /** 是否禁用端口 */\n isDisabledPort?: (port: WorkflowPortEntity) => boolean;\n /** 是否反转线条箭头 */\n isReverseLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否隐藏线条箭头 */\n isHideArrowLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否流动线条 */\n isFlowingLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否禁用线条 */\n isDisabledLine?: (line: WorkflowLineEntity) => boolean;\n /** 拖拽线条结束 */\n onDragLineEnd?: (params: onDragLineEndParams) => Promise<void>;\n /** 获取线条渲染器 */\n setLineRenderType?: (line: WorkflowLineEntity) => LineRenderType | undefined;\n /** 设置线条样式 */\n setLineClassName?: (line: WorkflowLineEntity) => string | undefined;\n /** 能否添加线条 */\n canAddLine?: (\n fromPort: WorkflowPortEntity,\n toPort: WorkflowPortEntity,\n lines: WorkflowLinesManager,\n silent?: boolean\n ) => boolean;\n /** 能否删除节点 */\n canDeleteNode?: (node: WorkflowNodeEntity, silent?: boolean) => boolean;\n /** 能否删除线条 */\n canDeleteLine?: (\n line: WorkflowLineEntity,\n newLineInfo?: Required<Omit<WorkflowLinePortInfo, 'data'>>,\n silent?: boolean\n ) => boolean;\n /**\n * @param fromPort - 开始点\n * @param oldToPort - 旧的连接点\n * @param newToPort - 新的连接点\n * @param lines - 线条管理器\n */\n canResetLine?: (\n fromPort: WorkflowPortEntity,\n oldToPort: WorkflowPortEntity,\n newToPort: WorkflowPortEntity,\n lines: WorkflowLinesManager\n ) => boolean;\n /**\n * 是否允许拖入子画布 (loop or group)\n * Whether to allow dragging into the sub-canvas (loop or group)\n * @param params\n */\n canDropToNode?: (params: {\n dragNodeType?: FlowNodeType;\n dragNode?: WorkflowNodeEntity;\n dropNode?: WorkflowNodeEntity;\n dropNodeType?: FlowNodeType;\n }) => boolean;\n}\n\nexport const WorkflowDocumentOptionsDefault: WorkflowDocumentOptions = {\n cursors: {\n grab: 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMCAyMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC40ODczIDIuNjIzNzhDOS45MDczMSAyLjYyMzc4IDkuNDM3MTMgMy4wOTM5NiA5LjQzNzEzIDMuNjczOTZWNS4xNDM3NkM5LjM5NDI4IDQuNDAyNzQgOC43Nzk3OCAzLjgxNTA0IDguMDI4MDIgMy44MTUwNEM3LjI0ODQ4IDMuODE1MDQgNi42MTY1MyA0LjQ0Njk5IDYuNjE2NTMgNS4yMjY1M1YxMS44Mjg5TDUuNjc0MTggMTEuMDA0OUM1LjE1NDg3IDEwLjU1MDkgNC40MDk1IDEwLjQ2MzYgMy43OTkzOCAxMC43ODU1TDMuNjk2OTQgMTAuODM5NkMzLjA2MjE3IDExLjE3NDUgMi45MjI2IDEyLjAyMjggMy40MTY2MiAxMi41NDM0TDcuMzM5NTkgMTYuNjc3NVYxNy4zMjU5QzcuMzM5NTkgMTcuNzg2MiA3LjcxMjY5IDE4LjE1OTMgOC4xNzI5MiAxOC4xNTkzSDEzLjgwODRDMTQuMjY4NyAxOC4xNTkzIDE0LjY0MTcgMTcuNzg2MiAxNC42NDE3IDE3LjMyNTlWMTYuNzkzNUMxNS44MDk0IDE1LjY0ODUgMTYuNDY3MyAxNC4wODE5IDE2LjQ2NzMgMTIuNDQ2NVYxMS40OTY3TDE2LjQ2NzEgNi42MzY4NUMxNi40NjcxIDUuOTU2MyAxNS45MTU0IDUuNDA0NjEgMTUuMjM0OCA1LjQwNDYxQzE0LjU1NDMgNS40MDQ2MSAxNC4wMDI2IDUuOTU2MyAxNC4wMDI2IDYuNjM2ODVMMTQuMDAyMSA1LjA0NzI4QzE0LjAwMjEgNC4zNjY3MyAxMy40NTA0IDMuODE1MDQgMTIuNzY5OCAzLjgxNTA0QzEyLjA4OTMgMy44MTUwNCAxMS41Mzc2IDQuMzY2NzMgMTEuNTM3NiA1LjA0NzI4TDExLjUzNzUgMy42NzM5NUMxMS41Mzc1IDMuMDkzOTYgMTEuMDY3MyAyLjYyMzc4IDEwLjQ4NzMgMi42MjM3OFoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAuNDg3NCAxLjM3NDAyQzExLjM2MTIgMS4zNzQwMiAxMi4xMjExIDEuODYxMTggMTIuNTEwNSAyLjU3ODY4QzEyLjU5NTggMi41Njk4MyAxMi42ODIzIDIuNTY1MjggMTIuNzcgMi41NjUyOEMxMy44Mjc4IDIuNTY1MjggMTQuNzMxMSAzLjIyNzAxIDE1LjA4ODUgNC4xNTkxMUMxNS4xMzcgNC4xNTYyOSAxNS4xODU4IDQuMTU0ODYgMTUuMjM1IDQuMTU0ODZDMTYuNjA1OSA0LjE1NDg2IDE3LjcxNzIgNS4yNjYxOSAxNy43MTcyIDYuNjM3MDlMMTcuNzE3NCAxMi40NDY3QzE3LjcxNzQgMTQuMjM1NSAxNy4wNjQ0IDE1Ljk1NTkgMTUuODkxOSAxNy4yOTA0VjE3LjMyNjJDMTUuODkxOSAxOC40NzY4IDE0Ljk1OTEgMTkuNDA5NSAxMy44MDg1IDE5LjQwOTVIOC4xNzMwNkM3LjAyMjQ3IDE5LjQwOTUgNi4wODk3MyAxOC40NzY4IDYuMDg5NzMgMTcuMzI2MlYxNy4xNzY0TDIuNTEwMDMgMTMuNDA0MUMxLjQ0NTk5IDEyLjI4MjggMS43NDY2IDEwLjQ1NTUgMy4xMTM3OSA5LjczNDI0TDMuMjE2MjQgOS42ODAxOUMzLjg5MTY4IDkuMzIzODMgNC42NjE4NSA5LjI1NDAxIDUuMzY2NjYgOS40NTE5OFY1LjIyNjc4QzUuMzY2NjYgMy43NTY4NyA2LjU1ODI2IDIuNTY1MjggOC4wMjgxNiAyLjU2NTI4QzguMTcyOTMgMi41NjUyOCA4LjMxNDk5IDIuNTc2ODQgOC40NTM0NyAyLjU5OTA3QzguODM5NDMgMS44NzA0MiA5LjYwNTQ2IDEuMzc0MDIgMTAuNDg3NCAxLjM3NDAyWk0xMi40NDc2IDMuODU3ODdWOS40NzY0NkMxMi40NDc2IDkuNzI4NTIgMTIuMjQzMyA5LjkzMjg1IDExLjk5MTMgOS45MzI4NUMxMS43MzkyIDkuOTMyODUgMTEuNTM0OSA5LjcyODUyIDExLjUzNDkgOS40NzY0NlYzLjc5NjU1QzExLjUzNDkgMy43Nzk1NiAxMS41MzU4IDMuNzYyNzcgMTEuNTM3NiAzLjc0NjI2VjMuNjc0MkMxMS41Mzc2IDMuNDMyODIgMTEuNDU2MiAzLjIxMDQ2IDExLjMxOTMgMy4wMzMwOUMxMS4xMjcyIDIuNzg0MjggMTAuODI2MSAyLjYyNDAyIDEwLjQ4NzQgMi42MjQwMkMxMC4xMjM4IDIuNjI0MDIgOS44MDMzMiAyLjgwODg2IDkuNjE0ODMgMy4wODk3QzkuNTAyNjkgMy4yNTY3OSA5LjQzNzI2IDMuNDU3ODUgOS40MzcyNiAzLjY3NDJWMy43ODU3M0M5LjQzNzM1IDMuNzg5MzMgOS40MzczOSAzLjc5Mjk0IDkuNDM3MzkgMy43OTY1NVY5LjkwMTdDOS40MzczOSAxMC4xNTM3IDkuMjMzMDYgMTAuMzU4MSA4Ljk4MTAxIDEwLjM1ODFDOC43Mjg5NSAxMC4zNTgxIDguNTI0NjIgMTAuMTUzNyA4LjUyNDYyIDkuOTAxN1YzLjkwNTA3QzguNDE3NzMgMy44NjQ5IDguMzA0NjggMy44MzczMiA4LjE4NzI2IDMuODI0MTVDOC4xMzUwNCAzLjgxODI5IDguMDgxOTUgMy44MTUyOCA4LjAyODE2IDMuODE1MjhDNy4yNDg2MSAzLjgxNTI4IDYuNjE2NjYgNC40NDcyMyA2LjYxNjY2IDUuMjI2NzhWMTEuODI5Mkw1LjY3NDMxIDExLjAwNTJDNS41Nzg2OCAxMC45MjE2IDUuNDc1MzcgMTAuODUwNCA1LjM2NjY2IDEwLjc5MTlDNC44ODUwNiAxMC41MzI5IDQuMjk3MjggMTAuNTIzMSAzLjc5OTUyIDEwLjc4NThMMy42OTcwNyAxMC44Mzk4QzMuMDYyMzEgMTEuMTc0NyAyLjkyMjczIDEyLjAyMzEgMy40MTY3NSAxMi41NDM3TDcuMzM5NzMgMTYuNjc3N1YxNy4zMjYyQzcuMzM5NzMgMTcuNzg2NCA3LjcxMjgyIDE4LjE1OTUgOC4xNzMwNiAxOC4xNTk1SDEzLjgwODVDMTQuMjY4OCAxOC4xNTk1IDE0LjY0MTkgMTcuNzg2NCAxNC42NDE5IDE3LjMyNjJWMTYuNzkzOEMxNS43Mzc5IDE1LjcxOSAxNi4zODQ3IDE0LjI3MjggMTYuNDYgMTIuNzQ3QzE2LjQ2NDEgMTIuNjY0MSAxNi40NjY1IDEyLjU4MDkgMTYuNDY3MiAxMi40OTc1TDE2LjQ2NzQgMTIuNDQ2N0wxNi40NjcyIDYuNjM3MDlDMTYuNDY3MiA1Ljk2MjMgMTUuOTI0OCA1LjQxNDE5IDE1LjI1MjIgNS40MDQ5N0wxNS4yMzUgNS40MDQ4NkMxNS4xMjQ2IDUuNDA0ODYgMTUuMDE3NyA1LjQxOTM2IDE0LjkxNTkgNS40NDY1NlY5LjYwMjI2QzE0LjkxNTkgOS44NTQzMSAxNC43MTE2IDEwLjA1ODYgMTQuNDU5NSAxMC4wNTg2QzE0LjIwNzUgMTAuMDU4NiAxNC4wMDMxIDkuODU0MzEgMTQuMDAzMSA5LjYwMjI2VjYuNjA1MTRDMTQuMDAyOSA2LjYxNTc2IDE0LjAwMjcgNi42MjY0MSAxNC4wMDI3IDYuNjM3MDlWOS4yNzcwNUwxNC4wMDIyIDUuMDQ3NTJDMTQuMDAyMiA0Ljg2OTEzIDEzLjk2NDMgNC42OTk2IDEzLjg5NjEgNC41NDY1M0MxMy43MDY0IDQuMTIwNzIgMTMuMjgyMiAzLjgyMjM1IDEyLjc4NzYgMy44MTU0MUwxMi43NyAzLjgxNTI4QzEyLjY1ODQgMy44MTUyOCAxMi41NTA0IDMuODMwMSAxMi40NDc2IDMuODU3ODdaIiBmaWxsPSIjMUQxQzIzIi8+Cjwvc3ZnPg==\"), auto',\n grabbing:\n 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMCAyMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02LjYxODE3IDUuNTk4NzVDNi42MTgxNyA0LjgxOTIgNy4yNTAxMiA0LjE4NzI2IDguMDI5NjcgNC4xODcyNkM4Ljc3ODczIDQuMTg3MjYgOS4zOTE1MiA0Ljc3MDc1IDkuNDM4MjkgNS41MDgwMUM5LjQ1OTkyIDQuOTQ3MSA5LjkyMTQ3IDQuNDk5MDIgMTAuNDg3NyA0LjQ5OTAyQzExLjA2NzcgNC40OTkwMiAxMS41Mzc4IDQuOTY5MiAxMS41Mzc4IDUuNTQ5MTlWOC43NjI0NkwxMS41Mzc5IDYuNzExNUMxMS41Mzc5IDYuMDMwOTUgMTIuMDg5NiA1LjQ3OTI2IDEyLjc3MDIgNS40NzkyNkMxMy40NTA3IDUuNDc5MjYgMTQuMDAyNCA2LjAzMDk1IDE0LjAwMjQgNi43MTE1TDE0LjAwMjQgOC43NjI0NkwxNC4wMDI5IDguMDE5ODNDMTQuMDAyOSA3LjMzOTI5IDE0LjU1NDYgNi43ODc1OSAxNS4yMzUyIDYuNzg3NTlDMTUuOTE1NyA2Ljc4NzU5IDE2LjQ2NzQgNy4zMzkyOCAxNi40Njc0IDguMDE5ODNWMTEuNDk3TDE2LjQ2NzUgMTIuNDQ2N0MxNi40Njc1IDE0LjA4MjEgMTUuODA5NiAxNS42NDg3IDE0LjY0MiAxNi43OTM4VjE3LjMyNjJDMTQuNjQyIDE3Ljc4NjQgMTQuMjY4OSAxOC4xNTk1IDEzLjgwODcgMTguMTU5NUg4LjE3MzE3QzcuNzEyOTMgMTguMTU5NSA3LjMzOTg0IDE3Ljc4NjQgNy4zMzk4NCAxNy4zMjYyVjE1Ljk0MjRMNS4zNDU2MiAxNC43NTM0QzQuNTg5MjQgMTQuMzAyNCA0LjEyNTkxIDEzLjQ4NjcgNC4xMjU4OSAxMi42MDYxTDQuMTI1ODMgOS4yODM4M0M0LjEyNTgyIDguOTU0MjcgNC4zMjAwMyA4LjY1NTY2IDQuNjIxMjkgOC41MjIwNUw2LjYxODE3IDcuNjM2MzRWNS41OTg3NVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAuNDg3OCAzLjI0OTAyQzExLjI3OTYgMy4yNDkwMiAxMS45Nzc4IDMuNjQ5MDIgMTIuMzkxNyA0LjI1Nzk2QzEyLjUxNTEgNC4yMzkwNiAxMi42NDE2IDQuMjI5MjYgMTIuNzcwMyA0LjIyOTI2QzEzLjcyMjQgNC4yMjkyNiAxNC41NDkzIDQuNzY1MzEgMTQuOTY1NyA1LjU1MjA3QzE1LjA1NDMgNS41NDI1IDE1LjE0NDIgNS41Mzc1OSAxNS4yMzUzIDUuNTM3NTlDMTYuNjA2MiA1LjUzNzU5IDE3LjcxNzYgNi42NDg5MyAxNy43MTc2IDguMDE5ODNMMTcuNzE3NyAxMi40NDY3QzE3LjcxNzcgMTQuMjM1NSAxNy4wNjQ3IDE1Ljk1NTkgMTUuODkyMSAxNy4yOTA0VjE3LjMyNjJDMTUuODkyMSAxOC40NzY4IDE0Ljk1OTQgMTkuNDA5NSAxMy44MDg4IDE5LjQwOTVIOC4xNzMzMkM3LjAyMjczIDE5LjQwOTUgNi4wODk5OCAxOC40NzY4IDYuMDg5OTggMTcuMzI2MlYxNi42NTI0TDQuNzA1NjMgMTUuODI3QzMuNTcxMDYgMTUuMTUwNSAyLjg3NjA3IDEzLjkyNzEgMi44NzYwNCAxMi42MDYxTDIuODc1OTggOS4yODM4NUMyLjg3NTk2IDguNDU5OTYgMy4zNjE0OSA3LjcxMzQ1IDQuMTE0NjIgNy4zNzk0TDUuMzY4MzIgNi44MjMzM1Y1LjU5ODc1QzUuMzY4MzIgNC4xMjg4NSA2LjU1OTkxIDIuOTM3MjYgOC4wMjk4MiAyLjkzNzI2QzguNjA4MzEgMi45MzcyNiA5LjE0MzU1IDMuMTIxNyA5LjU4MDA1IDMuNDM1MDVDOS44NTg1MyAzLjMxNTMyIDEwLjE2NTQgMy4yNDkwMiAxMC40ODc4IDMuMjQ5MDJaTTEyLjQ0NzkgNS41MjE4NlY5LjQ3NTU3QzEyLjQ0NzkgOS43Mjc2MiAxMi4yNDM2IDkuOTMxOTUgMTEuOTkxNiA5LjkzMTk1QzExLjc1NjggOS45MzE5NSAxMS41NjM0IDkuNzU0NjUgMTEuNTM4IDkuNTI2NjNDMTEuNTM2MSA5LjUwOTg3IDExLjUzNTIgOS40OTI4MyAxMS41MzUyIDkuNDc1NTdWNS40NzE1OEMxMS41MTU0IDUuMjAwODMgMTEuMzkzIDQuOTU4NTggMTEuMjA2NiA0Ljc4MzU4QzExLjAxODggNC42MDcxMSAxMC43NjU5IDQuNDk5MDIgMTAuNDg3OCA0LjQ5OTAyQzEwLjQ3NjYgNC40OTkwMiAxMC40NjU0IDQuNDk5MTkgMTAuNDU0MiA0LjQ5OTU0QzkuOTAzNDcgNC41MTY4NCA5LjQ1OTY0IDQuOTU4MjQgOS40Mzg0NCA1LjUwODAxQzkuNDM4MiA1LjUwNDMgOS40Mzc5NSA1LjUwMDU4IDkuNDM3NjkgNS40OTY4OFY5LjkwMjQzQzkuNDM3NjkgMTAuMTU0NSA5LjIzMzM2IDEwLjM1ODggOC45ODEzMSAxMC4zNTg4QzguNzI5MjUgMTAuMzU4OCA4LjUyNDkyIDEwLjE1NDUgOC41MjQ5MiA5LjkwMjQzVjQuMjc2NTNDOC4zNzA4NiA0LjIxODgyIDguMjA0MDIgNC4xODcyNiA4LjAyOTgyIDQuMTg3MjZDNy4yNTAyNyA0LjE4NzI2IDYuNjE4MzIgNC44MTkyIDYuNjE4MzIgNS41OTg3NUw2LjYxODI3IDkuOTc1OTlDNi42MTgyNyAxMC4yMjggNi40MTM5NCAxMC40MzI0IDYuMTYxODkgMTAuNDMyNEM1LjkwOTgzIDEwLjQzMjQgNS43MDU1IDEwLjIyOCA1LjcwNTUgOS45NzU5OVY4LjA0MTIyTDQuNjIxNDQgOC41MjIwNUM0LjMyMDE4IDguNjU1NjYgNC4xMjU5NyA4Ljk1NDI3IDQuMTI1OTggOS4yODM4M0w0LjEyNjA0IDEyLjYwNjFDNC4xMjYwNiAxMy40ODY3IDQuNTg5MzkgMTQuMzAyNCA1LjM0NTc2IDE0Ljc1MzRMNy4zMzk5OCAxNS45NDI0VjE3LjMyNjJDNy4zMzk5OCAxNy43ODY0IDcuNzEzMDggMTguMTU5NSA4LjE3MzMyIDE4LjE1OTVIMTMuODA4OEMxNC4yNjkgMTguMTU5NSAxNC42NDIxIDE3Ljc4NjQgMTQuNjQyMSAxNy4zMjYyVjE2Ljc5MzhDMTUuNzM4MSAxNS43MTkgMTYuMzg1IDE0LjI3MjggMTYuNDYwMyAxMi43NDdDMTYuNDY0NiAxMi42NiAxNi40NjcgMTIuNTcyOCAxNi40Njc2IDEyLjQ4NTRMMTYuNDY3NyAxMi40NDY3TDE2LjQ2NzYgOC4wMTk4M0MxNi40Njc2IDcuMzQ1MDQgMTUuOTI1MiA2Ljc5NjkzIDE1LjI1MjUgNi43ODc3MUwxNS4yMzUzIDYuNzg3NTlDMTUuMTI1IDYuNzg3NTkgMTUuMDE4IDYuODAyMSAxNC45MTYyIDYuODI5MzFWOS42MDEzNkMxNC45MTYyIDkuODUzNDIgMTQuNzExOSAxMC4wNTc3IDE0LjQ1OTggMTAuMDU3N0MxNC4yMDc4IDEwLjA1NzcgMTQuMDAzNCA5Ljg1MzQxIDE0LjAwMzQgOS42MDEzNlY3Ljk4OTg1QzE0LjAwMzIgNy45OTk4MiAxNC4wMDMxIDguMDA5ODEgMTQuMDAzMSA4LjAxOTgzTDE0LjAwMzQgOS42MDEzNkwxNC4wMDI1IDYuNzExNUMxNC4wMDI1IDYuNDQ5NzQgMTMuOTIwOSA2LjIwNzA1IDEzLjc4MTggNi4wMDc0OEMxMy41NjIgNS42OTI0MiAxMy4xOTg5IDUuNDg0ODMgMTIuNzg3IDUuNDc5MzdMMTIuNzcwMyA1LjQ3OTI2QzEyLjY1ODggNS40NzkyNiAxMi41NTA3IDUuNDk0MDggMTIuNDQ3OSA1LjUyMTg2WiIgZmlsbD0iIzFEMUMyMyIvPgo8L3N2Zz4=\"), auto',\n },\n\n fromNodeJSON(node, json, isFirstCreate) {\n initFormDataFromJSON(node, json, isFirstCreate);\n return;\n },\n toNodeJSON(node: WorkflowNodeEntity): WorkflowNodeJSON {\n const nodeError = node.getData<FlowNodeErrorData>(FlowNodeErrorData)?.getError();\n // 如果节点有错误,这里抛出错误,避免后面的代码执行异常\n if (nodeError) {\n throw nodeError;\n }\n const transform = node.getData<TransformData>(TransformData)!;\n\n let formJSON = toFormJSON(node);\n const metaData: Record<string, unknown> = {};\n\n // 持久化子画布位置\n const nodeMeta = node.getNodeMeta<WorkflowNodeMeta>();\n const subCanvas = nodeMeta.subCanvas?.(node);\n if (subCanvas?.isCanvas === false) {\n const canvasNodeTransform =\n subCanvas.canvasNode.getData<FlowNodeTransformData>(FlowNodeTransformData);\n const { x, y } = canvasNodeTransform.transform.position;\n metaData.canvasPosition = { x, y };\n }\n\n const json: WorkflowNodeJSON = {\n id: node.id,\n type: node.flowNodeType,\n meta: {\n position: { x: transform.position.x, y: transform.position.y },\n ...metaData,\n },\n data: formJSON,\n };\n return json;\n },\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { FlowNodeFormData } from '@flowgram.ai/form-core';\nimport { FlowNodeEntity, FlowNodeJSON } from '@flowgram.ai/document';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport { WorkflowContentChangeType, type WorkflowNodeRegistry } from '../typings';\n\nexport function getFlowNodeFormData(node: FlowNodeEntity) {\n return node.getData(FlowNodeFormData) as FlowNodeFormData;\n}\n\nexport function toFormJSON(node: FlowNodeEntity) {\n const formData = node.getData(FlowNodeFormData) as FlowNodeFormData;\n if (!formData || !(node.getNodeRegistry() as WorkflowNodeRegistry).formMeta) return undefined;\n return formData.toJSON();\n}\n\nexport function initFormDataFromJSON(\n node: FlowNodeEntity,\n json: FlowNodeJSON,\n isFirstCreate: boolean\n) {\n const formData = node.getData(FlowNodeFormData)!;\n const registry = node.getNodeRegistry();\n const { formMeta } = registry;\n\n if (formData && formMeta) {\n if (isFirstCreate) {\n formData.createForm(formMeta, json.data);\n formData.onDataChange(() => {\n (node.document as WorkflowDocument).fireContentChange({\n type: WorkflowContentChangeType.NODE_DATA_CHANGE,\n toJSON: () => formData.toJSON(),\n entity: node,\n });\n });\n } else {\n formData.updateFormValues(json.data);\n }\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { type WorkflowLineEntity, type WorkflowNodeEntity } from '../entities';\nimport { type WorkflowNodeJSON } from './workflow-node';\nimport { type WorkflowEdgeJSON } from './workflow-edge';\n\nexport interface WorkflowJSON {\n nodes: WorkflowNodeJSON[];\n edges: WorkflowEdgeJSON[];\n}\n\nexport enum WorkflowContentChangeType {\n /**\n * 添加节点\n */\n ADD_NODE = 'ADD_NODE',\n /**\n * 删除节点\n */\n DELETE_NODE = 'DELETE_NODE',\n /**\n * 移动节点\n */\n MOVE_NODE = 'MOVE_NODE',\n /**\n * 节点数据更新 (表单引擎数据 或者 extInfo 数据)\n */\n NODE_DATA_CHANGE = 'NODE_DATA_CHANGE',\n /**\n * 添加线条\n */\n ADD_LINE = 'ADD_LINE',\n /**\n * 删除线条\n */\n DELETE_LINE = 'DELETE_LINE',\n /**\n * 线条数据修改\n */\n LINE_DATA_CHANGE = 'LINE_DATA_CHANGE',\n /**\n * 节点Meta信息变更\n */\n META_CHANGE = 'META_CHANGE',\n}\n\nexport interface WorkflowContentChangeEvent {\n type: WorkflowContentChangeType;\n /**\n * 当前触发的元素的json数据,toJSON 需要主动触发\n */\n toJSON: () => any;\n /**\n * oldValue\n */\n oldValue?: any;\n /*\n * 当前的事件的 entity\n */\n entity: WorkflowNodeEntity | WorkflowLineEntity;\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport type { Rectangle, IPoint } from '@flowgram.ai/utils';\n\nimport { type WorkflowLineEntity } from '../entities';\n\nexport enum LineType {\n BEZIER, // 贝塞尔曲线\n LINE_CHART, // 折叠线\n STRAIGHT, // 直线\n}\n\nexport type LineRenderType = LineType | string;\n\nexport type LinePointLocation = 'left' | 'top' | 'right' | 'bottom';\n\nexport interface LinePoint {\n x: number;\n y: number;\n location: LinePointLocation;\n}\n\nexport interface LinePosition {\n from: LinePoint;\n to: LinePoint;\n}\n\nexport interface LineColor {\n hidden: string;\n default: string;\n drawing: string;\n hovered: string;\n selected: string;\n error: string;\n flowing: string;\n}\n\nexport enum LineColors {\n HIDDEN = 'var(--g-workflow-line-color-hidden,transparent)', // 隐藏线条\n DEFUALT = 'var(--g-workflow-line-color-default,#4d53e8)',\n DRAWING = 'var(--g-workflow-line-color-drawing, #5DD6E3)', // '#b5bbf8', // '#9197F1',\n HOVER = 'var(--g-workflow-line-color-hover,#37d0ff)',\n SELECTED = 'var(--g-workflow-line-color-selected,#37d0ff)',\n ERROR = 'var(--g-workflow-line-color-error,red)',\n FLOWING = 'var(--g-workflow-line-color-flowing,#4d53e8)', // 流动线条,默认使用主题色\n}\n\nexport interface LineCenterPoint {\n x: number;\n y: number;\n labelX: number; // Relative to where the line begins\n labelY: number; // Relative to where the line begins\n}\n\nexport interface WorkflowLineRenderContribution {\n entity: WorkflowLineEntity;\n path: string;\n center?: LineCenterPoint;\n bounds: Rectangle;\n update: (params: { fromPos: LinePoint; toPos: LinePoint }) => void;\n calcDistance: (pos: IPoint) => number;\n}\n\nexport type WorkflowLineRenderContributionFactory = (new (\n entity: WorkflowLineEntity\n) => WorkflowLineRenderContribution) & {\n type: LineRenderType;\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { IPoint, Event } from '@flowgram.ai/utils';\nimport {\n FlowNodeEntity,\n FlowNodeEntityOrId,\n FlowOperationBaseService,\n} from '@flowgram.ai/document';\n\nexport interface NodePostionUpdateEvent {\n node: FlowNodeEntity;\n oldPosition: IPoint;\n newPosition: IPoint;\n}\n\nexport interface WorkflowOperationBaseService extends FlowOperationBaseService {\n /**\n * 节点位置更新事件\n */\n readonly onNodePostionUpdate: Event<NodePostionUpdateEvent>;\n /**\n * 更新节点位置\n * @param nodeOrId\n * @param position\n * @returns\n */\n updateNodePosition(nodeOrId: FlowNodeEntityOrId, position: IPoint): void;\n}\n\nexport const WorkflowOperationBaseService = Symbol('WorkflowOperationBaseService');\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport * from './workflow-json';\nexport * from './workflow-edge';\nexport * from './workflow-node';\nexport * from './workflow-registry';\nexport * from './workflow-line';\nexport * from './workflow-sub-canvas';\nexport * from './workflow-operation';\nexport * from './workflow-drag';\n\nexport const URLParams = Symbol('');\n\nexport interface URLParams {\n [key: string]: string;\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { customAlphabet } from 'nanoid';\nimport { inject, injectable, optional, postConstruct } from 'inversify';\nimport { Emitter, type IPoint } from '@flowgram.ai/utils';\nimport { NodeEngineContext } from '@flowgram.ai/form-core';\nimport {\n AddNodeData,\n FlowDocument,\n FlowNodeBaseType,\n FlowNodeTransformData,\n} from '@flowgram.ai/document';\nimport {\n injectPlaygroundContext,\n PlaygroundConfigEntity,\n PlaygroundContext,\n PositionData,\n TransformData,\n} from '@flowgram.ai/core';\n\nimport { WorkflowLinesManager } from './workflow-lines-manager';\nimport {\n WorkflowDocumentOptions,\n WorkflowDocumentOptionsDefault,\n} from './workflow-document-option';\nimport { getFlowNodeFormData } from './utils/flow-node-form-data';\nimport { buildGroupJSON, delay, fitView, getAntiOverlapPosition } from './utils';\nimport {\n type WorkflowContentChangeEvent,\n WorkflowContentChangeType,\n WorkflowEdgeJSON,\n type WorkflowJSON,\n type WorkflowNodeJSON,\n type WorkflowNodeMeta,\n type WorkflowNodeRegistry,\n WorkflowSubCanvas,\n} from './typings';\nimport { WorkflowSelectService } from './service/workflow-select-service';\nimport { FREE_LAYOUT_KEY, type FreeLayout } from './layout';\nimport { WorkflowNodeLinesData } from './entity-datas';\nimport {\n WorkflowLineEntity,\n WorkflowLinePortInfo,\n WorkflowNodeEntity,\n WorkflowPortEntity,\n} from './entities';\n\nconst nanoid = customAlphabet('1234567890', 5);\n\nexport const WorkflowDocumentProvider = Symbol('WorkflowDocumentProvider');\nexport type WorkflowDocumentProvider = () => WorkflowDocument;\n\n@injectable()\nexport class WorkflowDocument extends FlowDocument {\n private _onContentChangeEmitter = new Emitter<WorkflowContentChangeEvent>();\n\n protected readonly onLoadedEmitter = new Emitter<void>();\n\n readonly onContentChange = this._onContentChangeEmitter.event;\n\n private _onReloadEmitter = new Emitter<WorkflowDocument>();\n\n readonly onReload = this._onReloadEmitter.event;\n\n /**\n * 数据加载完成\n */\n readonly onLoaded = this.onLoadedEmitter.event;\n\n protected _loading = false;\n\n @inject(WorkflowLinesManager) linesManager: WorkflowLinesManager;\n\n @inject(PlaygroundConfigEntity) playgroundConfig: PlaygroundConfigEntity;\n\n @injectPlaygroundContext() playgroundContext: PlaygroundContext;\n\n @inject(WorkflowDocumentOptions)\n options: WorkflowDocumentOptions = {};\n\n @inject(NodeEngineContext) @optional() nodeEngineContext: NodeEngineContext;\n\n @inject(WorkflowSelectService) selectServices: WorkflowSelectService;\n\n get loading(): boolean {\n return this._loading;\n }\n\n /**\n * use `ctx.tools.fitView()` instead\n * @deprecated\n * @param easing\n */\n async fitView(easing?: boolean): Promise<void> {\n return fitView(this, this.playgroundConfig, easing).then(() => {\n this.linesManager.forceUpdate();\n });\n }\n\n @postConstruct()\n init(): void {\n super.init();\n this.currentLayoutKey = this.options.defaultLayout || FREE_LAYOUT_KEY;\n this.linesManager.init(this);\n this.playgroundConfig.getCursors = () => this.options.cursors;\n this.linesManager.onAvailableLinesChange((e) => this.fireContentChange(e));\n this.playgroundConfig.onReadonlyOrDisabledChange(({ readonly }) => {\n if (this.nodeEngineContext) {\n this.nodeEngineContext.readonly = readonly;\n }\n });\n }\n\n async load(): Promise<void> {\n if (this.disposed) return;\n this._loading = true;\n await super.load();\n this._loading = false;\n this.onLoadedEmitter.fire();\n }\n\n async reload(json: WorkflowJSON, delayTime = 0): Promise<void> {\n if (this.disposed) return;\n this._loading = true;\n this.clear();\n this.fromJSON(json);\n // loading添加delay,避免reload时触发fireContentChange的副作用\n await delay(delayTime);\n this._loading = false;\n this._onReloadEmitter.fire(this);\n }\n\n /**\n * 从数据加载\n * @param json\n */\n fromJSON(json: Partial<WorkflowJSON>, fireRender = true): void {\n if (this.disposed) return;\n const workflowJSON: WorkflowJSON = {\n nodes: json.nodes ?? [],\n edges: json.edges ?? [],\n };\n // 触发画布更新\n this.entityManager.changeEntityLocked = true;\n\n // 逐层渲染\n this.renderJSON(workflowJSON);\n\n this.entityManager.changeEntityLocked = false;\n this.transformer.loading = false;\n // 批量触发画布更新\n if (fireRender) {\n this.fireRender();\n }\n }\n\n /**\n * 清空画布\n */\n clear(): void {\n this.getAllNodes().map((node) => node.dispose()); // 清空节点\n this.linesManager.getAllLines().map((line) => line.dispose()); // 清空线条\n this.getAllPorts().map((port) => port.dispose()); // 清空端口\n this.selectServices.clear(); // 清空选择\n }\n\n /**\n * 创建流程节点\n * @param json\n */\n createWorkflowNode(\n json: WorkflowNodeJSON,\n isClone: boolean = false,\n parentId?: string\n ): WorkflowNodeEntity {\n // 是否是一个已经存在的节点\n const isExistedNode = this.getNode(json.id);\n const parent = this.getNode(parentId ?? this.root.id) ?? this.root;\n const node = this.addNode(\n {\n ...json,\n parent,\n },\n undefined,\n true\n ) as WorkflowNodeEntity;\n\n const registry = node.getNodeRegistry() as WorkflowNodeRegistry;\n const { formMeta } = registry;\n const meta = node.getNodeMeta<WorkflowNodeMeta>();\n const formData = getFlowNodeFormData(node);\n\n const transform = node.getData<FlowNodeTransformData>(FlowNodeTransformData)!;\n const freeLayout = this.layout as FreeLayout;\n if (!isExistedNode) {\n transform.onDataChange(() => {\n // TODO 这个有点难以理解,其实是为了同步size 数据\n freeLayout.syncTransform(node);\n });\n }\n let { position } = meta;\n if (!position) {\n // 获取默认的位置\n position = this.getNodeDefaultPosition(json.type);\n }\n\n // 更新节点位置信息\n node.getData(TransformData)!.update({\n position,\n });\n\n // 初始化表单数据\n if (formMeta && formData && !formData.formModel.initialized) {\n // 如果表单数据在前置步骤(fromJSON)内已定义,则跳过表单初始化逻辑\n formData.createForm(formMeta, json.data);\n\n formData.onDataChange(() => {\n this.fireContentChange({\n type: WorkflowContentChangeType.NODE_DATA_CHANGE,\n toJSON: () => formData.toJSON(),\n entity: node,\n });\n });\n }\n // 位置变更\n const positionData = node.getData<PositionData>(PositionData)!;\n if (!isExistedNode) {\n positionData.onDataChange(() => {\n this.fireContentChange({\n type: WorkflowContentChangeType.MOVE_NODE,\n toJSON: () => positionData.toJSON(),\n entity: node,\n });\n });\n }\n\n const subCanvas = this.getNodeSubCanvas(node);\n\n if (!isExistedNode && !subCanvas?.isCanvas) {\n this.fireContentChange({\n type: WorkflowContentChangeType.ADD_NODE,\n entity: node,\n toJSON: () => this.toNodeJSON(node),\n });\n node.onDispose(() => {\n if (!node.parent || node.parent.flowNodeType === FlowNodeBaseType.ROOT) {\n return;\n }\n const parentTransform = node.parent.getData(FlowNodeTransformData);\n parentTransform.fireChange();\n });\n let lastDeleteNodeData: WorkflowNodeJSON | undefined;\n node.preDispose.onDispose(() => {\n lastDeleteNodeData = this.toNodeJSON(node);\n });\n node.onDispose(() => {\n this.fireContentChange({\n type: WorkflowContentChangeType.DELETE_NODE,\n entity: node,\n toJSON: () => lastDeleteNodeData,\n });\n });\n }\n\n // 若存在子节点,则创建子节点\n if (json.blocks) {\n this.renderJSON(\n { nodes: json.blocks, edges: json.edges ?? [] },\n {\n parent: node,\n isClone,\n }\n );\n }\n // 子画布联动\n if (subCanvas) {\n const canvasTransform = subCanvas.canvasNode.getData<TransformData>(TransformData);\n canvasTransform.update({\n position: subCanvas.parentNode.getNodeMeta()?.canvasPosition,\n });\n if (!isExistedNode) {\n subCanvas.parentNode.onDispose(() => {\n subCanvas.canvasNode.dispose();\n });\n subCanvas.canvasNode.onDispose(() => {\n subCanvas.parentNode.dispose();\n });\n }\n }\n if (!isExistedNode) {\n this.onNodeCreateEmitter.fire({\n node,\n data: json,\n json,\n });\n } else {\n this.onNodeUpdateEmitter.fire({\n node,\n data: json,\n json,\n });\n }\n\n return node;\n }\n\n /**\n * 添加节点,如果节点已经存在则不会重复创建\n * @param data\n * @param addedNodes\n */\n addNode(\n data: AddNodeData,\n addedNodes?: WorkflowNodeEntity[],\n ignoreCreateAndUpdateEvent?: boolean\n ): WorkflowNodeEntity {\n const { id, type = 'block', originParent, parent, meta, hidden, index } = data;\n let node = this.getNode(id);\n let isNew = false;\n const register = this.getNodeRegistry(type, data.originParent);\n // node 类型变化则全部删除重新来\n if (node && node.flowNodeType !== data.type) {\n node.dispose();\n node = undefined;\n }\n if (!node) {\n const { dataRegistries } = register;\n node = this.entityManager.createEntity<WorkflowNodeEntity>(WorkflowNodeEntity, {\n id,\n document: this,\n flowNodeType: type,\n originParent,\n meta,\n });\n const datas = dataRegistries\n ? this.nodeDataRegistries.concat(...dataRegistries)\n : this.nodeDataRegistries;\n node.addInitializeData(datas);\n node.onDispose(() => this.onNodeDisposeEmitter.fire({ node: node! }));\n this.options.fromNodeJSON?.(node, data, true);\n isNew = true;\n } else {\n this.options.fromNodeJSON?.(node, data, false);\n }\n // 初始化数据重制\n node.initData({\n originParent,\n parent,\n meta,\n hidden,\n index,\n });\n addedNodes?.push(node);\n // 自定义创建逻辑\n if (register.onCreate) {\n const extendNodes = register.onCreate(node, data);\n if (extendNodes && addedNodes) {\n addedNodes.push(...extendNodes);\n }\n }\n\n if (!ignoreCreateAndUpdateEvent) {\n if (isNew) {\n this.onNodeCreateEmitter.fire({\n node,\n data,\n json: data,\n });\n } else {\n this.onNodeUpdateEmitter.fire({ node, data, json: data });\n }\n }\n\n return node;\n }\n\n get layout(): FreeLayout {\n const layout = this.layouts.find((layout) => layout.name == this.currentLayoutKey);\n if (!layout) {\n throw new Error(`Unknown flow layout: ${this.currentLayoutKey}`);\n }\n return layout as FreeLayout;\n }\n\n /**\n * 获取默认的 x y 坐标, 默认为当前画布可视区域中心\n * @param type\n * @protected\n */\n getNodeDefaultPosition(type: string | number): IPoint {\n const { size } = this.getNodeRegistry(type).meta || {};\n // 当前可视区域的中心位置\n let position = this.playgroundConfig.getViewport(true).center;\n if (size) {\n position = {\n x: position.x,\n y: position.y - size.height / 2,\n };\n }\n // 去掉叠加的\n return getAntiOverlapPosition(this, position);\n }\n\n /**\n * 通过类型创建节点, 如果没有提供position 则直接放在画布中间\n * @param type\n */\n createWorkflowNodeByType(\n type: string | number,\n position?: IPoint,\n json: Partial<WorkflowNodeJSON> = {},\n parentID?: string\n ): WorkflowNodeEntity {\n let id: string = json.id as string;\n if (id === undefined) {\n // 保证 id 不要重复\n do {\n id = `1${nanoid()}`;\n } while (this.entityManager.getEntityById(id));\n } else {\n if (this.entityManager.getEntityById(id)) {\n throw new Error(`[WorkflowDocument.createWorkflowNodeByType] Node Id \"${id}\" duplicated.`);\n }\n }\n return this.createWorkflowNode(\n {\n ...json,\n id,\n type,\n meta: { position, ...json?.meta }, // TODO title 和 meta 要从注册数据去拿\n data: json?.data,\n blocks: json?.blocks,\n edges: json?.edges,\n },\n false,\n parentID\n );\n }\n\n getAllNodes(): WorkflowNodeEntity[] {\n return this.entityManager\n .getEntities<WorkflowNodeEntity>(WorkflowNodeEntity)\n .filter((n) => n.id !== FlowNodeBaseType.ROOT);\n }\n\n getAllPorts(): WorkflowPortEntity[] {\n return this.entityManager\n .getEntities<WorkflowPortEntity>(WorkflowPortEntity)\n .filter((p) => p.node.id !== FlowNodeBaseType.ROOT);\n }\n\n /**\n * 获取画布中的非游离节点\n * 1. 开始节点\n * 2. 从开始节点出发能走到的节点\n * 3. 结束节点\n * 4. 默认所有子画布内节点为游离节点\n */\n getAssociatedNodes(): WorkflowNodeEntity[] {\n const allNode = this.getAllNodes();\n\n const allLines = this.linesManager\n .getAllLines()\n .filter((line) => line.from && line.to)\n .map((line) => ({\n from: line.from.id,\n to: line.to!.id,\n }));\n\n const startNodeId = allNode.find((node) => node.isStart)?.id;\n const endNodeId = allNode.find((node) => node.isNodeEnd)?.id;\n\n // 子画布内节点无需开始/结束\n const nodeInContainer = allNode\n .filter((node) => node.parent?.getNodeMeta<WorkflowNodeMeta>().isContainer)\n .map((node) => node.id);\n\n const associatedCache = new Set(nodeInContainer);\n if (endNodeId) {\n associatedCache.add(endNodeId);\n }\n const bfs = (nodeId: string) => {\n if (associatedCache.has(nodeId)) {\n return;\n }\n associatedCache.add(nodeId);\n const nextNodes = allLines.reduce((ids, { from, to }) => {\n if (from === nodeId && !associatedCache.has(to)) {\n ids.push(to);\n }\n return ids;\n }, [] as string[]);\n\n nextNodes.forEach(bfs);\n };\n\n if (startNodeId) {\n bfs(startNodeId);\n }\n\n const associatedNodes = allNode.filter((node) => associatedCache.has(node.id));\n\n return associatedNodes;\n }\n\n /**\n * 触发渲染\n */\n fireRender() {\n this.entityManager.fireEntityChanged(WorkflowNodeEntity.type);\n this.entityManager.fireEntityChanged(WorkflowLineEntity.type);\n this.entityManager.fireEntityChanged(WorkflowPortEntity.type);\n }\n\n fireContentChange(event: WorkflowContentChangeEvent): void {\n if (this._loading || this.disposed || this.entityManager.changeEntityLocked) {\n return;\n }\n this._onContentChangeEmitter.fire(event);\n }\n\n toNodeJSON(node: WorkflowNodeEntity): WorkflowNodeJSON {\n // 如果是子画布,返回其父节点的JSON\n const subCanvas = this.getNodeSubCanvas(node);\n if (subCanvas?.isCanvas === true) {\n return this.toNodeJSON(subCanvas.parentNode);\n }\n\n const json = this.toNodeJSONFromOptions(node);\n const children = this.getNodeChildren(node);\n\n // 计算子节点 JSON\n const blocks = children.map((child) => this.toNodeJSON(child));\n\n // 计算子线条 JSON\n const linesMap = new Map<string, WorkflowEdgeJSON>();\n children.forEach((child) => {\n const childLinesData = child.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData);\n [...childLinesData.inputLines, ...childLinesData.outputLines]\n .filter(Boolean)\n .forEach((line) => {\n const lineJSON = this.toLineJSON(line);\n if (!lineJSON || linesMap.has(line.id)) {\n return;\n }\n linesMap.set(line.id, lineJSON);\n });\n });\n const edges = Array.from(linesMap.values()); // 使用 Map 防止线条重复\n\n // 拼接 JSON\n if (blocks.length > 0) json.blocks = blocks;\n if (edges.length > 0) json.edges = edges;\n\n return json;\n }\n\n /**\n * 节点转换为JSON, 没有format的过程\n * @param node\n * @returns\n */\n private toNodeJSONFromOptions(node: WorkflowNodeEntity): WorkflowNodeJSON {\n if (this.options.toNodeJSON) {\n return this.options.toNodeJSON(node) as WorkflowNodeJSON;\n }\n return WorkflowDocumentOptionsDefault.toNodeJSON!(node) as WorkflowNodeJSON;\n }\n\n copyNode(\n node: WorkflowNodeEntity,\n newNodeId?: string | undefined,\n format?: (json: WorkflowNodeJSON) => WorkflowNodeJSON,\n position?: IPoint\n ): WorkflowNodeEntity {\n let json = this.toNodeJSON(node);\n if (format) {\n json = format(json);\n }\n position = position || {\n x: json.meta!.position!.x + 30,\n y: json.meta!.position!.y + 30,\n };\n return this.createWorkflowNode(\n {\n id: newNodeId || `1${nanoid()}`,\n type: node.flowNodeType,\n meta: {\n ...json.meta,\n position,\n },\n data: json.data,\n blocks: json.blocks,\n edges: json.edges,\n },\n true,\n node.parent?.id\n );\n }\n\n copyNodeFromJSON(\n flowNodeType: string,\n nodeJSON: WorkflowNodeJSON,\n newNodeId?: string | undefined,\n position?: IPoint,\n parentId?: string\n ): WorkflowNodeEntity {\n position = position || {\n x: nodeJSON.meta!.position!.x + 30,\n y: nodeJSON.meta!.position!.y + 30,\n };\n return this.createWorkflowNode(\n {\n id: newNodeId || `1${nanoid()}`,\n type: flowNodeType,\n meta: {\n ...nodeJSON.meta,\n position,\n },\n data: nodeJSON.data,\n blocks: nodeJSON.blocks,\n edges: nodeJSON.edges,\n },\n true,\n parentId\n );\n }\n\n canRemove(node: WorkflowNodeEntity, silent?: boolean): boolean {\n const meta = node.getNodeMeta<WorkflowNodeMeta>();\n if (meta.deleteDisable) {\n return false;\n }\n if (this.options.canDeleteNode && !this.options.canDeleteNode(node, silent)) {\n return false;\n }\n return true;\n }\n\n /**\n * 判断端口是否为错误态\n */\n isErrorPort(port: WorkflowPortEntity, defaultValue = false) {\n if (typeof this.options.isErrorPort === 'function') {\n return this.options.isErrorPort(port);\n }\n\n return defaultValue;\n }\n\n /**\n * 导出数据\n */\n toJSON(): WorkflowJSON {\n if (this.disposed) {\n throw new Error(\n 'The WorkflowDocument has been disposed and it is no longer possible to call toJSON.'\n );\n }\n const rootJSON = this.toNodeJSON(this.root);\n const json = {\n nodes: rootJSON.blocks ?? [],\n edges: rootJSON.edges ?? [],\n };\n return json;\n }\n\n dispose() {\n super.dispose();\n this._onReloadEmitter.dispose();\n }\n\n /**\n * 批量添加节点\n * @deprecated use 'batchAddFromJSON' instead\n * @param json\n * @param options\n */\n public renderJSON(\n json: WorkflowJSON,\n options?: {\n parent?: WorkflowNodeEntity;\n isClone?: boolean;\n }\n ): {\n nodes: WorkflowNodeEntity[];\n edges: WorkflowLineEntity[];\n } {\n return this.batchAddFromJSON(json, options);\n }\n\n /**\n * 批量添加节点\n */\n public batchAddFromJSON(\n json: WorkflowJSON,\n options?: {\n parent?: WorkflowNodeEntity;\n isClone?: boolean;\n }\n ): {\n nodes: WorkflowNodeEntity[];\n edges: WorkflowLineEntity[];\n } {\n const { parent = this.root, isClone = false } = options ?? {};\n // 创建节点\n const containerID = this.getNodeSubCanvas(parent)?.canvasNode.id ?? parent.id;\n const processedJSON = buildGroupJSON(json);\n const nodes = processedJSON.nodes.map((nodeJSON: WorkflowNodeJSON) =>\n this.createWorkflowNode(nodeJSON, isClone, containerID)\n );\n // 创建线条\n const edges = processedJSON.edges\n .map((edge) => this.createWorkflowLine(edge, containerID))\n .filter(Boolean) as WorkflowLineEntity[];\n return { nodes, edges };\n }\n\n private getNodeSubCanvas(node: WorkflowNodeEntity): WorkflowSubCanvas | undefined {\n if (!node) return;\n const nodeMeta = node.getNodeMeta<WorkflowNodeMeta>();\n const subCanvas = nodeMeta.subCanvas?.(node);\n return subCanvas;\n }\n\n private getNodeChildren(node: WorkflowNodeEntity): WorkflowNodeEntity[] {\n if (!node || node.flowNodeType === FlowNodeBaseType.GROUP) return [];\n const subCanvas = this.getNodeSubCanvas(node);\n // get real children\n const realChildren = subCanvas ? subCanvas.canvasNode.blocks : node.blocks;\n // filter sub canvas node\n const childrenWithoutSubCanvas = realChildren\n .filter((child) => {\n const childMeta = child.getNodeMeta<WorkflowNodeMeta>();\n return !childMeta.subCanvas?.(node)?.isCanvas;\n })\n .filter(Boolean);\n // flat group nodes\n const children = childrenWithoutSubCanvas\n .map((child) => {\n if (child.flowNodeType === FlowNodeBaseType.GROUP) {\n return [child, ...child.blocks];\n }\n return child;\n })\n .flat();\n return children;\n }\n\n private toLineJSON(line: WorkflowLineEntity): WorkflowEdgeJSON | undefined {\n const lineJSON = line.toJSON();\n if (\n !line.from ||\n !line.info.from ||\n !line.fromPort ||\n !line.to ||\n !line.info.to ||\n !line.toPort\n ) {\n return;\n }\n // 父子节点之间连线,需替换子画布为父节点\n const fromSubCanvas = this.getNodeSubCanvas(line.from);\n const toSubCanvas = this.getNodeSubCanvas(line.to);\n if (fromSubCanvas && !fromSubCanvas.isCanvas && toSubCanvas && toSubCanvas.isCanvas) {\n // 忽略子画布与父节点的连线\n return;\n }\n if (line.from === line.to.parent && fromSubCanvas) {\n return {\n ...lineJSON,\n sourceNodeID: fromSubCanvas.parentNode.id,\n };\n }\n if (line.to === line.from.parent && toSubCanvas) {\n return {\n ...lineJSON,\n targetNodeID: toSubCanvas.parentNode.id,\n };\n }\n return lineJSON;\n }\n\n private createWorkflowLine(\n json: WorkflowEdgeJSON,\n parentId?: string\n ): WorkflowLineEntity | undefined {\n const fromNode = this.getNode(json.sourceNodeID);\n const toNode = this.getNode(json.targetNodeID);\n // 脏数据清除\n if (!fromNode || !toNode) {\n return;\n }\n const lineInfo: WorkflowLinePortInfo = {\n from: json.sourceNodeID,\n fromPort: json.sourcePortID,\n to: json.targetNodeID,\n toPort: json.targetPortID,\n data: json.data,\n };\n if (!parentId) {\n return this.linesManager.createLine(lineInfo);\n }\n // 父子节点之间连线,需替换父节点为子画布\n const canvasNode = this.getNode(parentId);\n if (!canvasNode) {\n return this.linesManager.createLine(lineInfo);\n }\n const parentSubCanvas = this.getNodeSubCanvas(canvasNode);\n if (!parentSubCanvas) {\n return this.linesManager.createLine(lineInfo);\n }\n if (lineInfo.from === parentSubCanvas.parentNode.id) {\n return this.linesManager.createLine({\n ...lineInfo,\n from: parentSubCanvas.canvasNode.id,\n });\n }\n if (lineInfo.to === parentSubCanvas.parentNode.id) {\n return this.linesManager.createLine({\n ...lineInfo,\n to: parentSubCanvas.canvasNode.id,\n });\n }\n return this.linesManager.createLine(lineInfo);\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { inject, injectable } from 'inversify';\nimport {\n type IPoint,\n PaddingSchema,\n Rectangle,\n type ScrollSchema,\n SizeSchema,\n} from '@flowgram.ai/utils';\nimport {\n type FlowDocument,\n type FlowLayout,\n type FlowNodeEntity,\n FlowDocumentProvider,\n FlowNodeTransformData,\n} from '@flowgram.ai/document';\nimport { PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\n\nexport const FREE_LAYOUT_KEY = 'free-layout';\n/**\n * 自由画布布局\n */\n@injectable()\nexport class FreeLayout implements FlowLayout {\n name = FREE_LAYOUT_KEY;\n\n @inject(PlaygroundConfigEntity) playgroundConfig: PlaygroundConfigEntity;\n\n @inject(FlowDocumentProvider)\n protected documentProvider: FlowDocumentProvider;\n\n get document(): FlowDocument {\n return this.documentProvider();\n }\n\n /**\n * 更新布局\n */\n update(): void {\n if (this.document.root.getData(FlowNodeTransformData)?.localDirty) {\n this.document.root.clearMemoGlobal();\n // this.document.root.getData(FlowNodeTransformData)!.localDirty = false\n }\n // 自由画布同步同步大小, TODO 这个移动到 createWorkflowNode\n // this.document.root.allChildren.forEach(this.syncTransform.bind(this))\n }\n\n syncTransform(node: FlowNodeEntity): void {\n const transform = node.getData<FlowNodeTransformData>(FlowNodeTransformData)!;\n if (!transform.localDirty) {\n return;\n }\n node.clearMemoGlobal();\n node.clearMemoLocal();\n // 同步 size 给原始的 transform\n transform.transform.update({\n size: transform.data.size,\n });\n if (!node.parent) {\n return;\n }\n node.parent.clearMemoGlobal();\n node.parent.clearMemoLocal();\n const parentTransform = node.parent.getData<FlowNodeTransformData>(FlowNodeTransformData);\n parentTransform.transform.fireChange();\n }\n\n /**\n * 更新所有受影响的上下游节点\n */\n updateAffectedTransform(node: FlowNodeEntity): void {\n const transformData = node.transform;\n if (!transformData.localDirty) {\n return;\n }\n const allParents = this.getAllParents(node);\n const allBlocks = this.getAllBlocks(node).reverse();\n const affectedNodes = [...allBlocks, ...allParents];\n affectedNodes.forEach((node) => {\n this.fireChange(node);\n });\n }\n\n /**\n * 获取节点的 padding 数据\n * @param node\n */\n getPadding(node: FlowNodeEntity): PaddingSchema {\n const { padding } = node.getNodeMeta();\n const transform = node.getData<FlowNodeTransformData>(FlowNodeTransformData);\n if (padding) {\n return typeof padding === 'function' ? padding(transform) : padding;\n }\n return PaddingSchema.empty();\n }\n\n /**\n * 默认滚动到 fitview 区域\n * @param contentSize\n */\n getInitScroll(contentSize: SizeSchema): ScrollSchema {\n const bounds = Rectangle.enlarge(\n this.document.getAllNodes().map((node) => node.getData<TransformData>(TransformData).bounds)\n ).pad(30, 30); // 留出 30 像素的边界\n const viewport = this.playgroundConfig.getViewport(false);\n const zoom = SizeSchema.fixSize(bounds, viewport);\n return {\n scrollX: (bounds.x + bounds.width / 2) * zoom - this.playgroundConfig.config.width / 2,\n scrollY: (bounds.y + bounds.height / 2) * zoom - this.playgroundConfig.config.height / 2,\n };\n }\n\n /**\n * 获取默认输入点\n */\n getDefaultInputPoint(node: FlowNodeEntity): IPoint {\n return node.getData<TransformData>(TransformData)!.bounds.leftCenter;\n }\n\n /**\n * 获取默认输出点\n */\n getDefaultOutputPoint(node: FlowNodeEntity): IPoint {\n return node.getData<TransformData>(TransformData)!.bounds.rightCenter;\n }\n\n /**\n * 水平中心点\n */\n getDefaultNodeOrigin(): IPoint {\n return { x: 0.5, y: 0 };\n }\n\n private getAllParents(node: FlowNodeEntity): FlowNodeEntity[] {\n const parents: FlowNodeEntity[] = [];\n let current = node.parent;\n\n while (current) {\n parents.push(current);\n current = current.parent;\n }\n\n return parents;\n }\n\n private getAllBlocks(node: FlowNodeEntity): FlowNodeEntity[] {\n return node.blocks.reduce<FlowNodeEntity[]>(\n (acc, child) => [...acc, ...this.getAllBlocks(child)],\n [node]\n );\n }\n\n private fireChange(node?: FlowNodeEntity): void {\n const transformData = node?.transform;\n if (!node || !transformData?.localDirty) {\n return;\n }\n node.clearMemoGlobal();\n node.clearMemoLocal();\n transformData.transform.fireChange();\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { inject, injectable, postConstruct } from 'inversify';\nimport { PlaygroundConfigEntity } from '@flowgram.ai/core';\nimport { EntityManager } from '@flowgram.ai/core';\nimport { DisposableCollection, Emitter, type IPoint } from '@flowgram.ai/utils';\n\nimport { WorkflowDocument } from '../workflow-document';\nimport { layoutToPositions } from '../utils/layout-to-positions';\nimport { fitView } from '../utils';\nimport { WorkflowNodeEntity } from '../entities';\n\nexport type PositionMap = Record<string, IPoint>;\n\n/**\n * 重置布局服务\n */\n@injectable()\nexport class WorkflowResetLayoutService {\n @inject(PlaygroundConfigEntity)\n private _config: PlaygroundConfigEntity;\n\n @inject(WorkflowDocument)\n private _document: WorkflowDocument;\n\n @inject(EntityManager)\n private _entityManager: EntityManager;\n\n private _resetLayoutEmitter = new Emitter<{\n nodeIds: string[];\n positionMap: PositionMap;\n oldPositionMap: PositionMap;\n }>();\n\n /**\n * reset layout事件\n */\n readonly onResetLayout = this._resetLayoutEmitter.event;\n\n private _toDispose = new DisposableCollection();\n\n /**\n * 初始化\n */\n @postConstruct()\n init() {\n this._toDispose.push(this._resetLayoutEmitter);\n }\n\n /**\n * 触发重置布局\n * @param nodeIds 节点id\n * @param positionMap 新布局数据\n * @param oldPositionMap 老布局数据\n */\n fireResetLayout(nodeIds: string[], positionMap: PositionMap, oldPositionMap: PositionMap) {\n this._resetLayoutEmitter.fire({\n nodeIds,\n positionMap,\n oldPositionMap,\n });\n }\n\n /**\n * 根据数据重新布局\n * @param positionMap\n * @returns\n */\n async layoutToPositions(nodeIds: string[], positionMap: PositionMap) {\n const nodes = nodeIds\n .map(id => this._entityManager.getEntityById(id))\n .filter(Boolean) as WorkflowNodeEntity[];\n const positions = await layoutToPositions(nodes, positionMap);\n fitView(this._document, this._config, true);\n return positions;\n }\n\n /**\n * 销毁\n */\n dispose() {\n this._toDispose.dispose();\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { type IPoint } from '@flowgram.ai/utils';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { TransformData, startTween } from '@flowgram.ai/core';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport { type WorkflowNodeEntity } from '../entities';\n\n/**\n * Coze 中节点坐标,以卡片顶部中间为原点。\n * autoLayout 计算出来的对齐的坐标以节点正中为原点,需要上移当前节点一般高度。\n * 即: newPosition.y - transform.bounds.height / 2\n * bounds 的原点坐标为左上角。\n */\nexport const layoutToPositions = async (\n nodes: WorkflowNodeEntity[],\n nodePositionMap: Record<string, IPoint>\n): Promise<Record<string, IPoint>> => {\n // 缓存上次位置,用来还原位置\n const newNodePositionMap: Record<string, IPoint> = {};\n nodes.forEach((node) => {\n const transform = node.getData(TransformData);\n const nodeTransform = node.getData(FlowNodeTransformData);\n\n newNodePositionMap[node.id] = {\n x: transform.position.x,\n y: transform.position.y + nodeTransform.bounds.height / 2,\n };\n });\n\n return new Promise((resolve) => {\n startTween({\n from: { d: 0 },\n to: { d: 100 },\n duration: 300,\n onUpdate: (v) => {\n nodes.forEach((node) => {\n const transform = node.getData(TransformData);\n const deltaX = ((nodePositionMap[node.id].x - transform.position.x) * v.d) / 100;\n const deltaY =\n ((nodePositionMap[node.id].y - transform.bounds.height / 2 - transform.position.y) *\n v.d) /\n 100;\n\n transform.update({\n position: {\n x: transform.position.x + deltaX,\n y: transform.position.y + deltaY,\n },\n });\n\n const document = node.document as WorkflowDocument;\n document.layout.updateAffectedTransform(node);\n });\n },\n onComplete: () => {\n resolve(newNodePositionMap);\n },\n });\n });\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { inject } from 'inversify';\nimport { IPoint, Emitter } from '@flowgram.ai/utils';\nimport { FlowNodeEntityOrId, FlowOperationBaseServiceImpl } from '@flowgram.ai/document';\nimport { TransformData } from '@flowgram.ai/core';\n\nimport { WorkflowDocument } from '../workflow-document';\nimport {\n NodePostionUpdateEvent,\n WorkflowOperationBaseService,\n} from '../typings/workflow-operation';\n\nexport class WorkflowOperationBaseServiceImpl\n extends FlowOperationBaseServiceImpl\n implements WorkflowOperationBaseService\n{\n @inject(WorkflowDocument)\n protected declare document: WorkflowDocument;\n\n private onNodePostionUpdateEmitter = new Emitter<NodePostionUpdateEvent>();\n\n public readonly onNodePostionUpdate = this.onNodePostionUpdateEmitter.event;\n\n updateNodePosition(nodeOrId: FlowNodeEntityOrId, position: IPoint): void {\n const node = this.toNodeEntity(nodeOrId);\n\n if (!node) {\n return;\n }\n\n const transformData = node.getData(TransformData);\n const oldPosition = {\n x: transformData.position.x,\n y: transformData.position.y,\n };\n transformData.update({\n position,\n });\n\n this.onNodePostionUpdateEmitter.fire({\n node,\n oldPosition,\n newPosition: position,\n });\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { useEffect } from 'react';\n\nimport { usePlayground, useRefresh } from '@flowgram.ai/core';\nimport { type Disposable } from '@flowgram.ai/utils';\n\n/**\n * 获取 readonly 状态\n */\nexport function usePlaygroundReadonlyState(listenChange?: boolean): boolean {\n const playground = usePlayground();\n const refresh = useRefresh();\n useEffect(() => {\n let dispose: Disposable | undefined = undefined;\n if (listenChange) {\n dispose = playground.config.onReadonlyOrDisabledChange(() => refresh());\n }\n return () => dispose?.dispose();\n }, [listenChange]);\n return playground.config.readonly;\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { FlowNodeRenderData } from '@flowgram.ai/document';\nimport { useEntityFromContext } from '@flowgram.ai/core';\n\nimport { type WorkflowNodeEntity } from '../entities';\n\n/**\n * 获取当前渲染的 dom 节点\n */\nexport function useCurrentDomNode(): HTMLDivElement {\n const entity = useEntityFromContext<WorkflowNodeEntity>();\n const renderData = entity.getData(FlowNodeRenderData)!;\n return renderData.node;\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { useEntityFromContext } from '@flowgram.ai/core';\n\nimport { type WorkflowNodeEntity } from '../entities';\n\n/**\n * 获取当前节点\n */\nexport function useCurrentEntity(): WorkflowNodeEntity {\n return useEntityFromContext<WorkflowNodeEntity>();\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { useService } from '@flowgram.ai/core';\n\nimport { WorkflowDocument } from '../workflow-document';\n\nexport function useWorkflowDocument(): WorkflowDocument {\n return useService<WorkflowDocument>(WorkflowDocument);\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport enum EditorCursorState {\n GRAB = 'GRAB',\n SELECT = 'SELECT',\n}\n\nexport enum InteractiveType {\n /** 鼠标优先交互模式 */\n MOUSE = 'MOUSE',\n\n /** 触控板优先交互模式 */\n PAD = 'PAD',\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { ContainerModule } from 'inversify';\nimport { bindContributions } from '@flowgram.ai/utils';\nimport { FlowDocument, FlowDocumentContribution } from '@flowgram.ai/document';\n\nimport { WorkflowLinesManager } from './workflow-lines-manager';\nimport {\n WorkflowDocumentOptions,\n WorkflowDocumentOptionsDefault,\n} from './workflow-document-option';\nimport { WorkflowDocumentContribution } from './workflow-document-contribution';\nimport { WorkflowDocument, WorkflowDocumentProvider } from './workflow-document';\nimport { getUrlParams } from './utils/get-url-params';\nimport { URLParams, WorkflowOperationBaseService } from './typings';\nimport {\n WorkflowDragService,\n WorkflowHoverService,\n WorkflowSelectService,\n WorkflowResetLayoutService,\n WorkflowOperationBaseServiceImpl,\n} from './service';\nimport { FreeLayout } from './layout';\n\nexport const WorkflowDocumentContainerModule = new ContainerModule(\n (bind, unbind, isBound, rebind) => {\n bind(WorkflowDocument).toSelf().inSingletonScope();\n bind(WorkflowLinesManager).toSelf().inSingletonScope();\n bind(FreeLayout).toSelf().inSingletonScope();\n bind(WorkflowDragService).toSelf().inSingletonScope();\n bind(WorkflowSelectService).toSelf().inSingletonScope();\n bind(WorkflowHoverService).toSelf().inSingletonScope();\n bind(WorkflowResetLayoutService).toSelf().inSingletonScope();\n bind(WorkflowOperationBaseService).to(WorkflowOperationBaseServiceImpl).inSingletonScope();\n bind(URLParams)\n .toDynamicValue(() => getUrlParams())\n .inSingletonScope();\n bindContributions(bind, WorkflowDocumentContribution, [FlowDocumentContribution]);\n bind(WorkflowDocumentOptions).toConstantValue({\n ...WorkflowDocumentOptionsDefault,\n });\n rebind(FlowDocument).toService(WorkflowDocument);\n bind(WorkflowDocumentProvider)\n .toDynamicValue((ctx) => () => ctx.container.get(WorkflowDocument))\n .inSingletonScope();\n }\n);\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { injectable, inject } from 'inversify';\nimport {\n type FlowDocumentContribution,\n FlowNodeRenderData,\n FlowNodeTransformData,\n} from '@flowgram.ai/document';\n\nimport { WorkflowDocument } from './workflow-document';\nimport { FreeLayout } from './layout';\nimport { WorkflowNodeLinesData, WorkflowNodePortsData } from './entity-datas';\n\n@injectable()\nexport class WorkflowDocumentContribution implements FlowDocumentContribution<WorkflowDocument> {\n @inject(FreeLayout) freeLayout: FreeLayout;\n\n registerDocument(document: WorkflowDocument): void {\n // 注册节点数据\n document.registerNodeDatas(\n FlowNodeTransformData,\n FlowNodeRenderData,\n WorkflowNodePortsData,\n WorkflowNodeLinesData,\n );\n document.registerLayout(this.freeLayout);\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport function getUrlParams(): Record<string, string> {\n return location.search\n .replace(/^\\?/, '')\n .split('&')\n .reduce((res: Record<string, string>, key) => {\n const [k, v] = key.split('=');\n res[k] = v;\n return res;\n }, {} satisfies Record<string, string>);\n}\n"],"mappings":"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","names":["WorkflowCommands","import_core","import_react","import_document","import_core","import_core","import_utils","import_core","import_utils","nanoidOrigin","import_utils","import_core","import_utils","import_document","import_lodash_es","import_utils","import_core","import_document","import_core","import_utils","import_document","import_core","location","point","document","import_utils","import_core","import_utils","import_core","fitView","import_inversify","import_utils","import_core","import_nanoid","import_inversify","import_utils","import_document","import_core","import_lodash_es","import_inversify","import_utils","import_document","import_core","import_form_core","import_document","import_core","WorkflowContentChangeType","LineType","LineColors","import_nanoid","import_inversify","import_utils","import_form_core","import_document","import_core","import_inversify","import_utils","import_document","import_core","node","nanoid","layout","offset","import_inversify","import_core","import_utils","import_document","import_core","document","import_inversify","import_utils","import_document","import_core","import_core","import_document","import_core","import_core","import_core","EditorCursorState","InteractiveType","import_inversify","import_utils","import_document","import_inversify","import_document","document"]}