@flowgram.ai/free-lines-plugin 0.4.3 → 0.4.4
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/esm/index.js +83 -130
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +9 -30
- package/dist/index.d.ts +9 -30
- package/dist/index.js +96 -141
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/workflow-port-render/index.tsx","../../src/constants/points.ts","../../src/components/workflow-port-render/style.ts","../../src/components/workflow-port-render/cross-hair.tsx","../../src/constants/lines.ts","../../src/create-free-lines-plugin.ts","../../src/layer/workflow-lines-layer.tsx","../../src/components/workflow-line-render/index.tsx","../../src/components/workflow-line-render/line-svg.tsx","../../src/components/workflow-line-render/index.style.ts","../../src/components/workflow-line-render/arrow.tsx","../../src/contributions/bezier/index.ts","../../src/contributions/bezier/bezier-controls.ts","../../src/contributions/fold/index.ts","../../src/contributions/fold/fold-line.ts","../../src/contributions/straight/index.ts","../../src/contributions/straight/point-on-line.ts","../../src/contributions/arc/index.ts"],"sourcesContent":["/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport ReactDOM from 'react-dom';\nimport React, { useEffect, useState } from 'react';\n\nimport classNames from 'clsx';\nimport {\n WorkflowHoverService,\n type WorkflowPortEntity,\n usePlaygroundReadonlyState,\n WorkflowLinesManager,\n} from '@flowgram.ai/free-layout-core';\nimport { MouseTouchEvent, useService } from '@flowgram.ai/core';\n\nimport { PORT_BG_CLASS_NAME } from '../../constants/points';\nimport { WorkflowPointStyle } from './style';\nimport CrossHair from './cross-hair';\n\nexport interface WorkflowPortRenderProps {\n entity: WorkflowPortEntity;\n className?: string;\n style?: React.CSSProperties;\n onClick?: (e: React.MouseEvent<HTMLDivElement>, port: WorkflowPortEntity) => void;\n /** 激活状态颜色 (linked/hovered) */\n primaryColor?: string;\n /** 默认状态颜色 */\n secondaryColor?: string;\n /** 错误状态颜色 */\n errorColor?: string;\n /** 背景颜色 */\n backgroundColor?: string;\n}\n\nexport const WorkflowPortRender: React.FC<WorkflowPortRenderProps> =\n // eslint-disable-next-line react/display-name\n React.memo<WorkflowPortRenderProps>((props: WorkflowPortRenderProps) => {\n const hoverService = useService<WorkflowHoverService>(WorkflowHoverService);\n const linesManager = useService<WorkflowLinesManager>(WorkflowLinesManager);\n const { entity, onClick } = props;\n const { portType, relativePosition, disabled } = entity;\n const [targetElement, setTargetElement] = useState(entity.targetElement);\n const [posX, updatePosX] = useState(relativePosition.x);\n const [posY, updatePosY] = useState(relativePosition.y);\n const [hovered, setHovered] = useState(false);\n const [linked, setLinked] = useState(Boolean(entity?.lines?.length));\n const [hasError, setHasError] = useState(props.entity.hasError);\n const readonly = usePlaygroundReadonlyState();\n\n useEffect(() => {\n // useEffect 时序问题可能导致 port.hasError 非最新,需重新触发一次 validate\n entity.validate();\n setHasError(entity.hasError);\n const dispose = entity.onEntityChange(() => {\n // 如果有挂载的节点,不需要更新位置信息\n if (entity.targetElement) {\n if (entity.targetElement !== targetElement) {\n setTargetElement(entity.targetElement);\n }\n return;\n }\n const newPos = entity.relativePosition;\n // 加上 round 避免点位抖动\n updatePosX(Math.round(newPos.x));\n updatePosY(Math.round(newPos.y));\n });\n const dispose2 = hoverService.onHoveredChange((id) => {\n setHovered(hoverService.isHovered(entity.id));\n });\n const dispose3 = entity.onErrorChanged(() => {\n setHasError(entity.hasError);\n });\n const dispose4 = linesManager.onAvailableLinesChange(() => {\n setTimeout(() => {\n if (linesManager.disposed || entity.disposed) return;\n setLinked(Boolean(entity.lines.length));\n }, 0);\n });\n return () => {\n dispose.dispose();\n dispose2.dispose();\n dispose3.dispose();\n dispose4.dispose();\n };\n }, [hoverService, entity, targetElement]);\n\n // 监听变化\n const className = classNames('workflow-port-render', props.className || '', {\n hovered: !readonly && hovered && !disabled && portType !== 'input',\n // 有线条链接的时候深蓝色小圆点\n linked,\n });\n\n // 构建 CSS 自定义属性用于颜色覆盖\n const colorStyles: Record<string, string> = {};\n if (props.primaryColor) {\n colorStyles['--g-workflow-port-color-primary'] = props.primaryColor;\n }\n if (props.secondaryColor) {\n colorStyles['--g-workflow-port-color-secondary'] = props.secondaryColor;\n }\n if (props.errorColor) {\n colorStyles['--g-workflow-port-color-error'] = props.errorColor;\n }\n if (props.backgroundColor) {\n colorStyles['--g-workflow-port-color-background'] = props.backgroundColor;\n }\n\n const combinedStyle = targetElement\n ? { ...props.style, ...colorStyles }\n : { ...props.style, ...colorStyles, left: posX, top: posY };\n\n const content = (\n <WorkflowPointStyle\n className={className}\n style={combinedStyle}\n onClick={(e) => onClick?.(e, entity)}\n onTouchStart={(e) => {\n if (!onClick) {\n return;\n }\n MouseTouchEvent.onTouched(e, (mouseEvent) => {\n onClick(mouseEvent as unknown as React.MouseEvent<HTMLDivElement>, entity);\n });\n }}\n data-port-entity-id={entity.id}\n data-port-entity-type={entity.portType}\n data-testid=\"sdk.workflow.canvas.node.port\"\n >\n <div className={classNames('bg-circle', 'workflow-bg-circle')}></div>\n <div\n className={classNames({\n bg: true,\n [PORT_BG_CLASS_NAME]: true,\n 'workflow-point-bg': true,\n hasError,\n })}\n >\n <CrossHair />\n </div>\n <div className=\"focus-circle\" />\n </WorkflowPointStyle>\n );\n if (targetElement) {\n return ReactDOM.createPortal(content, targetElement);\n }\n return content;\n });\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\n// 连接点半径\n\nexport const STROKE_WIDTH_SLECTED = 3;\n\nexport const STROKE_WIDTH = 2;\n\nexport const PORT_BG_CLASS_NAME = 'workflow-port-bg';\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport styled from 'styled-components';\n\nexport const WorkflowPointStyle = styled.div`\n width: 20px;\n height: 20px;\n border-radius: 50%;\n margin-top: -10px;\n margin-left: -10px;\n left: 50%;\n top: 50%;\n position: absolute;\n // 非 hover 状态下的样式\n border: none;\n\n & > .symbol {\n opacity: 0;\n }\n\n .bg-circle {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n border-radius: 50%;\n width: 20px;\n height: 20px;\n background-color: var(--g-workflow-port-color-background, #fff);\n transform: scale(0.5);\n transition: all 0.2s linear 0s;\n }\n\n .bg {\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n background: var(--g-workflow-port-color-secondary, #9197f1);\n transform: scale(0.4, 0.4);\n transition: all 0.2s linear 0s;\n\n &.hasError {\n background: var(--g-workflow-port-color-error, red);\n }\n\n .symbol {\n position: absolute;\n width: 14px;\n height: 14px;\n opacity: 0;\n pointer-events: none;\n color: var(--g-workflow-port-color-background, #fff);\n transition: opacity 0.2s linear 0s;\n\n & > svg {\n width: 14px;\n height: 14px;\n }\n }\n\n .focus-circle {\n position: absolute;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 8px;\n height: 8px;\n opacity: 0;\n background: var(--g-workflow-port-color-secondary, #9197f1);\n border-radius: 50%;\n transition: opacity 0.2s linear 0s;\n }\n }\n\n &.linked .bg:not(.hasError) {\n background: var(--g-workflow-port-color-primary, #4d53e8);\n }\n\n &.hovered .bg:not(.hasError) {\n border: none;\n cursor: crosshair;\n transform: scale(1, 1);\n background: var(--g-workflow-port-color-primary, #4d53e8);\n\n & > .symbol {\n opacity: 1;\n }\n }\n\n .cross-hair {\n position: relative;\n left: 2px;\n top: 2px;\n\n &::after,\n &::before {\n content: '';\n background: var(--g-workflow-port-color-background, #fff);\n border-radius: 2px;\n position: absolute;\n }\n\n &::after {\n left: 4px;\n width: 2px;\n height: 6px;\n box-shadow: 0 4px var(--g-workflow-port-color-background, #fff);\n }\n\n &::before {\n top: 4px;\n width: 6px;\n height: 2px;\n box-shadow: 4px 0 var(--g-workflow-port-color-background, #fff);\n }\n`;\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport React from 'react';\n\n// demo 环境自绘 cross-hair,正式环境使用 IconAdd\nexport default function CrossHair(): JSX.Element {\n return (\n <div className=\"symbol\">\n <div className=\"cross-hair\" />\n </div>\n );\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\n// 箭头宽度\nexport const LINE_OFFSET = 6;\n\nexport const LINE_PADDING = 12;\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { WorkflowLinesManager } from '@flowgram.ai/free-layout-core';\nimport { definePluginCreator, PluginContext } from '@flowgram.ai/core';\n\nimport { FreeLinesPluginOptions } from './type';\nimport { WorkflowLinesLayer } from './layer';\nimport { WorkflowBezierLineContribution, WorkflowFoldLineContribution } from './contributions';\n\nexport const createFreeLinesPlugin = definePluginCreator({\n singleton: true,\n onInit: (ctx: PluginContext, opts: FreeLinesPluginOptions) => {\n ctx.playground.registerLayer(WorkflowLinesLayer, {\n ...opts,\n });\n },\n onReady: (ctx: PluginContext, opts: FreeLinesPluginOptions) => {\n const linesManager = ctx.container.get(WorkflowLinesManager);\n linesManager\n .registerContribution(WorkflowBezierLineContribution)\n .registerContribution(WorkflowFoldLineContribution);\n\n if (opts.contributions) {\n opts.contributions.forEach((contribution) => {\n linesManager.registerContribution(contribution);\n });\n }\n\n if (opts.defaultLineType) {\n linesManager.switchLineType(opts.defaultLineType);\n }\n },\n});\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport ReactDOM from 'react-dom';\nimport React, { ReactNode, useLayoutEffect, useState } from 'react';\n\nimport { inject, injectable } from 'inversify';\nimport { domUtils } from '@flowgram.ai/utils';\nimport { FlowRendererRegistry } from '@flowgram.ai/renderer';\nimport { StackingContextManager } from '@flowgram.ai/free-stack-plugin';\nimport {\n nanoid,\n WorkflowDocument,\n WorkflowHoverService,\n WorkflowLineEntity,\n WorkflowLineRenderData,\n WorkflowNodeEntity,\n WorkflowPortEntity,\n WorkflowSelectService,\n} from '@flowgram.ai/free-layout-core';\nimport { Layer, observeEntities, observeEntityDatas, TransformData } from '@flowgram.ai/core';\n\nimport { LineRenderProps, LinesLayerOptions } from '../type';\nimport { WorkflowLineRender } from '../components';\n\n@injectable()\nexport class WorkflowLinesLayer extends Layer<LinesLayerOptions> {\n static type = 'WorkflowLinesLayer';\n\n @inject(WorkflowHoverService) hoverService: WorkflowHoverService;\n\n @inject(WorkflowSelectService) selectService: WorkflowSelectService;\n\n @inject(StackingContextManager) stackContext: StackingContextManager;\n\n @inject(FlowRendererRegistry) rendererRegistry: FlowRendererRegistry;\n\n @observeEntities(WorkflowLineEntity) readonly lines: WorkflowLineEntity[];\n\n @observeEntities(WorkflowPortEntity) readonly ports: WorkflowPortEntity[];\n\n @observeEntityDatas(WorkflowNodeEntity, TransformData)\n readonly trans: TransformData[];\n\n @inject(WorkflowDocument) protected workflowDocument: WorkflowDocument;\n\n private layerID = nanoid();\n\n private mountedLines: Map<\n string,\n {\n line: WorkflowLineEntity;\n portal: ReactNode;\n version: string;\n }\n > = new Map();\n\n private _version = 0;\n\n /**\n * 节点线条\n */\n public node = domUtils.createDivWithClass('gedit-playground-layer gedit-flow-lines-layer');\n\n public onZoom(scale: number): void {\n this.node.style.transform = `scale(${scale})`;\n }\n\n public onReady() {\n this.pipelineNode.appendChild(this.node);\n this.toDispose.pushAll([\n this.selectService.onSelectionChanged(() => this.render()),\n this.hoverService.onHoveredChange(() => this.render()),\n this.workflowDocument.linesManager.onForceUpdate(() => {\n this.mountedLines.clear();\n this.bumpVersion();\n this.render();\n }),\n ]);\n }\n\n public dispose() {\n this.mountedLines.clear();\n }\n\n public render(): JSX.Element {\n const [, forceUpdate] = useState({});\n\n useLayoutEffect(() => {\n const updateLines = (): void => {\n let needsUpdate = false;\n\n // 批量处理所有线条的更新\n this.lines.forEach((line) => {\n const renderData = line.getData(WorkflowLineRenderData);\n const oldVersion = renderData.renderVersion;\n renderData.update();\n // 如果有任何一条线发生变化,标记需要更新\n if (renderData.renderVersion !== oldVersion) {\n needsUpdate = true;\n }\n });\n\n // 只在确实需要更新时触发重渲染\n if (needsUpdate) {\n forceUpdate({});\n }\n };\n\n const rafId = requestAnimationFrame(updateLines);\n return () => cancelAnimationFrame(rafId);\n }, [this.lines]); // 依赖项包含 lines\n\n const lines = this.lines.map((line) => this.renderLine(line));\n return <>{lines}</>;\n }\n\n // 用来绕过 memo\n private bumpVersion() {\n this._version = this._version + 1;\n if (this._version === Number.MAX_SAFE_INTEGER) {\n this._version = 0;\n }\n }\n\n private lineProps(line: WorkflowLineEntity): LineRenderProps {\n const { lineType } = this.workflowDocument.linesManager;\n const selected = this.selectService.isSelected(line.id);\n const hovered = this.hoverService.isHovered(line.id);\n const version = this.lineVersion(line);\n\n return {\n key: line.id,\n color: line.color,\n selected,\n hovered,\n line,\n lineType,\n version,\n strokePrefix: this.layerID,\n rendererRegistry: this.rendererRegistry,\n };\n }\n\n private lineVersion(line: WorkflowLineEntity): string {\n const renderData = line.getData(WorkflowLineRenderData);\n const { renderVersion } = renderData;\n const selected = this.selectService.isSelected(line.id);\n const hovered = this.hoverService.isHovered(line.id);\n const { version: lineVersion, color } = line;\n\n const version = `v:${this._version},lv:${lineVersion},rv:${renderVersion},c:${color},s:${\n selected ? 'T' : 'F'\n },h:${hovered ? 'T' : 'F'}`;\n\n return version;\n }\n\n private lineComponent(props: LineRenderProps): ReactNode {\n const RenderInsideLine = this.options.renderInsideLine ?? (() => <></>);\n return (\n <WorkflowLineRender {...props}>\n <RenderInsideLine {...props} />\n </WorkflowLineRender>\n );\n }\n\n private renderLine(line: WorkflowLineEntity): ReactNode {\n const lineProps = this.lineProps(line);\n const cache = this.mountedLines.get(line.id);\n const isCached = cache !== undefined;\n const { portal: cachedPortal, version: cachedVersion } = cache ?? {};\n if (isCached && cachedVersion === lineProps.version) {\n // 如果已有缓存且版本相同,则直接返回缓存的 portal\n return cachedPortal;\n }\n if (!isCached) {\n // 如果缓存不存在,则将 line 挂载到 renderElement 上\n this.renderElement.appendChild(line.node);\n line.onDispose(() => {\n this.mountedLines.delete(line.id);\n line.node.remove();\n });\n }\n // 刷新缓存\n const portal = ReactDOM.createPortal(this.lineComponent(lineProps), line.node);\n this.mountedLines.set(line.id, { line, portal, version: lineProps.version });\n return portal;\n }\n\n private get renderElement(): HTMLElement {\n return this.stackContext.node;\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { memo } from 'react';\n\nimport { LineSVG } from './line-svg';\n\nexport const WorkflowLineRender = memo(\n LineSVG,\n (prevProps, nextProps) => prevProps.version === nextProps.version\n);\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport React from 'react';\n\nimport clsx from 'clsx';\nimport { type IPoint } from '@flowgram.ai/utils';\nimport { POINT_RADIUS } from '@flowgram.ai/free-layout-core';\nimport { WorkflowLineRenderData } from '@flowgram.ai/free-layout-core';\n\nimport { type ArrowRendererComponent } from '../../types/arrow-renderer';\nimport { LineRenderProps } from '../../type';\nimport { STROKE_WIDTH_SLECTED, STROKE_WIDTH } from '../../constants/points';\nimport { LINE_OFFSET } from '../../constants/lines';\nimport { LineStyle } from './index.style';\nimport { ArrowRenderer } from './arrow';\n\nconst PADDING = 12;\n\nexport const LineSVG = (props: LineRenderProps) => {\n const { line, color, selected, children, strokePrefix, rendererRegistry } = props;\n const { position, reverse, hideArrow, vertical } = line;\n\n const renderData = line.getData(WorkflowLineRenderData);\n const { bounds, path: bezierPath } = renderData;\n\n // 相对位置转换函数\n const toRelative = (p: IPoint): IPoint => ({\n x: p.x - bounds.x + PADDING,\n y: p.y - bounds.y + PADDING,\n });\n\n const fromPos = toRelative(position.from);\n const toPos = toRelative(position.to);\n\n // 箭头位置计算\n const arrowToPos: IPoint =\n position.to.location === 'top'\n ? { x: toPos.x, y: toPos.y - POINT_RADIUS }\n : { x: toPos.x - POINT_RADIUS, y: toPos.y };\n const arrowFromPos: IPoint =\n position.from.location === 'bottom'\n ? { x: fromPos.x, y: fromPos.y + POINT_RADIUS + LINE_OFFSET }\n : { x: fromPos.x + POINT_RADIUS + LINE_OFFSET, y: fromPos.y };\n\n const strokeWidth = selected\n ? line.uiState.strokeWidthSelected ?? STROKE_WIDTH_SLECTED\n : line.uiState.strokeWidth ?? STROKE_WIDTH;\n\n const strokeID = strokePrefix ? `${strokePrefix}-${line.id}` : line.id;\n\n // 获取自定义箭头渲染器,如果没有则使用默认的\n const CustomArrowRenderer = rendererRegistry?.tryToGetRendererComponent('arrow-renderer')\n ?.renderer as ArrowRendererComponent;\n const ArrowComponent = CustomArrowRenderer || ArrowRenderer;\n\n const path = (\n <path\n d={bezierPath}\n fill=\"none\"\n stroke={`url(#${strokeID})`}\n strokeWidth={strokeWidth}\n className={line.processing || line.flowing ? 'dashed-line flowing-line' : ''}\n />\n );\n\n return (\n <LineStyle\n className={clsx('gedit-flow-activity-edge', line.className)}\n style={{\n ...line.uiState.style,\n left: bounds.x - PADDING,\n top: bounds.y - PADDING,\n position: 'absolute',\n }}\n >\n {children}\n <svg width={bounds.width + PADDING * 2} height={bounds.height + PADDING * 2}>\n <defs>\n <linearGradient\n x1={vertical ? '100%' : '0%'}\n y1={vertical ? '0%' : '100%'}\n x2=\"100%\"\n y2=\"100%\"\n id={strokeID}\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop stopColor={color} offset=\"0%\" />\n <stop stopColor={color} offset=\"100%\" />\n </linearGradient>\n </defs>\n <g>\n {path}\n <ArrowComponent\n id={strokeID}\n reverseArrow={reverse}\n pos={reverse ? arrowFromPos : arrowToPos}\n strokeWidth={strokeWidth}\n vertical={vertical}\n hide={hideArrow}\n line={line}\n />\n </g>\n </svg>\n </LineStyle>\n );\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport styled from 'styled-components';\n\n// 添加一个固定类名,用于选中该节点\n\nexport const LineStyle = styled.div`\n position: absolute;\n\n @keyframes flowingDash {\n to {\n stroke-dashoffset: -13;\n }\n }\n\n .dashed-line {\n stroke-dasharray: 8, 5;\n }\n\n .flowing-line {\n animation: flowingDash 0.5s linear infinite;\n }\n`;\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport React from 'react';\n\nimport { type ArrowRendererProps } from '../../types/arrow-renderer';\nimport { LINE_OFFSET } from '../../constants/lines';\n\nexport function ArrowRenderer({\n id,\n pos,\n reverseArrow,\n strokeWidth,\n vertical,\n hide,\n}: ArrowRendererProps) {\n if (hide) {\n return null;\n }\n const arrowPath = vertical\n ? reverseArrow\n ? `M ${pos.x - LINE_OFFSET},${pos.y} L ${pos.x},${pos.y - LINE_OFFSET} L ${\n pos.x + LINE_OFFSET\n },${pos.y}`\n : `M ${pos.x - LINE_OFFSET},${pos.y - LINE_OFFSET} L ${pos.x},${pos.y} L ${\n pos.x + LINE_OFFSET\n },${pos.y - LINE_OFFSET}`\n : reverseArrow\n ? `M ${pos.x},${pos.y + LINE_OFFSET} L ${pos.x - LINE_OFFSET},${pos.y} L ${pos.x},${\n pos.y - LINE_OFFSET\n }`\n : `M ${pos.x - LINE_OFFSET},${pos.y - LINE_OFFSET} L ${pos.x},${pos.y} L ${\n pos.x - LINE_OFFSET\n },${pos.y + LINE_OFFSET}`;\n\n return (\n <path\n d={arrowPath}\n strokeLinecap=\"round\"\n stroke={`url(#${id})`}\n fill=\"none\"\n strokeWidth={strokeWidth}\n />\n );\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Bezier } from 'bezier-js';\nimport { IPoint, Point, Rectangle } from '@flowgram.ai/utils';\nimport {\n WorkflowLineEntity,\n WorkflowLineRenderContribution,\n LinePoint,\n} from '@flowgram.ai/free-layout-core';\nimport { LineType } from '@flowgram.ai/free-layout-core';\n\nimport { LINE_PADDING } from '../../constants/lines';\nimport { getBezierControlPoints } from './bezier-controls';\n\nexport interface BezierData {\n fromPos: IPoint;\n toPos: IPoint;\n bbox: Rectangle; // 外围矩形\n controls: IPoint[]; // 控制点\n bezier: Bezier;\n path: string;\n}\n\nexport class WorkflowBezierLineContribution implements WorkflowLineRenderContribution {\n public static type = LineType.BEZIER;\n\n public entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n this.entity = entity;\n }\n\n private data?: BezierData;\n\n public get path(): string {\n return this.data?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n if (!this.data) {\n return Number.MAX_SAFE_INTEGER;\n }\n return Point.getDistance(pos, this.data.bezier.project(pos));\n }\n\n public get bounds(): Rectangle {\n if (!this.data) {\n return new Rectangle();\n }\n return this.data.bbox;\n }\n\n public update(params: { fromPos: LinePoint; toPos: LinePoint }): void {\n this.data = this.calcBezier(params.fromPos, params.toPos);\n }\n\n private calcBezier(fromPos: LinePoint, toPos: LinePoint): BezierData {\n const controls = getBezierControlPoints(fromPos, toPos, this.entity.uiState.curvature);\n const bezier = new Bezier([fromPos, ...controls, toPos]);\n const bbox = bezier.bbox();\n const bboxBounds = new Rectangle(\n bbox.x.min,\n bbox.y.min,\n bbox.x.max - bbox.x.min,\n bbox.y.max - bbox.y.min\n );\n\n const path = this.getPath({ bbox: bboxBounds, fromPos, toPos, controls });\n\n this.data = {\n fromPos,\n toPos,\n bezier,\n bbox: bboxBounds,\n controls,\n path,\n };\n return this.data;\n }\n\n private getPath(params: {\n bbox: Rectangle;\n fromPos: LinePoint;\n toPos: LinePoint;\n controls: IPoint[];\n }): string {\n const { bbox } = params;\n // 相对位置转换函数\n const toRelative = (p: IPoint): IPoint => ({\n x: p.x - bbox.x + LINE_PADDING,\n y: p.y - bbox.y + LINE_PADDING,\n });\n const fromPos = toRelative(params.fromPos);\n const toPos = toRelative(params.toPos);\n\n const controls = params.controls.map((c) => toRelative(c));\n const shrink = this.entity.uiState.shrink;\n\n const renderFromPos: IPoint =\n params.fromPos.location === 'bottom'\n ? { x: fromPos.x, y: fromPos.y + shrink }\n : { x: fromPos.x + shrink, y: fromPos.y };\n\n const renderToPos: IPoint =\n params.toPos.location === 'top'\n ? { x: toPos.x, y: toPos.y - shrink }\n : { x: toPos.x - shrink, y: toPos.y };\n\n const controlPoints = controls.map((s) => `${s.x} ${s.y}`).join(',');\n return `M${renderFromPos.x} ${renderFromPos.y} C ${controlPoints}, ${renderToPos.x} ${renderToPos.y}`;\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 { LinePoint, LinePointLocation } from '@flowgram.ai/free-layout-core';\n\nfunction getControlOffset(distance: number, curvature: number): number {\n if (distance >= 0) {\n return 0.5 * distance;\n }\n\n return curvature * 25 * Math.sqrt(-distance);\n}\n\nfunction getControlWithCurvature({\n location,\n x1,\n y1,\n x2,\n y2,\n curvature,\n}: {\n location: LinePointLocation;\n curvature: number;\n x1: number;\n x2: number;\n y1: number;\n y2: number;\n}): IPoint {\n switch (location) {\n case 'left':\n return {\n x: x1 - getControlOffset(x1 - x2, curvature),\n y: y1,\n };\n case 'right':\n return {\n x: x1 + getControlOffset(x2 - x1, curvature),\n y: y1,\n };\n case 'top':\n return {\n x: x1,\n y: y1 - getControlOffset(y1 - y2, curvature),\n };\n case 'bottom':\n return {\n x: x1,\n y: y1 + getControlOffset(y2 - y1, curvature),\n };\n }\n}\n\nexport function getBezierControlPoints(\n fromPos: LinePoint,\n toPos: LinePoint,\n curvature = 0.25\n): IPoint[] {\n const fromControl = getControlWithCurvature({\n location: fromPos.location,\n x1: fromPos.x,\n y1: fromPos.y,\n x2: toPos.x,\n y2: toPos.y,\n curvature,\n });\n const toControl = getControlWithCurvature({\n location: toPos.location,\n x1: toPos.x,\n y1: toPos.y,\n x2: fromPos.x,\n y2: fromPos.y,\n curvature,\n });\n return [fromControl, toControl];\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 {\n POINT_RADIUS,\n WorkflowLineEntity,\n WorkflowLineRenderContribution,\n LinePoint,\n} from '@flowgram.ai/free-layout-core';\nimport { LineType } from '@flowgram.ai/free-layout-core';\n\nimport { LINE_PADDING } from '../../constants/lines';\nimport { FoldLine } from './fold-line';\n\nexport interface FoldData {\n points: IPoint[];\n path: string;\n bbox: Rectangle;\n}\n\nexport class WorkflowFoldLineContribution implements WorkflowLineRenderContribution {\n public static type = LineType.LINE_CHART;\n\n public entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n this.entity = entity;\n }\n\n private data?: FoldData;\n\n public get path(): string {\n return this.data?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n if (!this.data) {\n return Number.MAX_SAFE_INTEGER;\n }\n return FoldLine.getFoldLineToPointDistance(this.data.points, pos);\n }\n\n public get bounds(): Rectangle {\n if (!this.data) {\n return new Rectangle();\n }\n return this.data.bbox;\n }\n\n public update(params: { fromPos: LinePoint; toPos: LinePoint }): void {\n const { fromPos, toPos } = params;\n\n // 根据方向预先计算源点和目标点的偏移\n const sourceOffset = {\n x: fromPos.location === 'bottom' ? 0 : POINT_RADIUS,\n y: fromPos.location === 'bottom' ? POINT_RADIUS : 0,\n };\n const targetOffset = {\n x: toPos.location === 'top' ? 0 : -POINT_RADIUS,\n y: toPos.location === 'top' ? -POINT_RADIUS : 0,\n };\n\n const points = FoldLine.getPoints({\n source: {\n x: fromPos.x + sourceOffset.x,\n y: fromPos.y + sourceOffset.y,\n location: fromPos.location,\n },\n target: {\n x: toPos.x + targetOffset.x,\n y: toPos.y + targetOffset.y,\n location: toPos.location,\n },\n });\n\n const bbox = FoldLine.getBounds(points);\n\n // 调整所有点到 SVG 视口坐标系\n const adjustedPoints = points.map((p) => ({\n x: p.x - bbox.x + LINE_PADDING,\n y: p.y - bbox.y + LINE_PADDING,\n }));\n\n const path = FoldLine.getSmoothStepPath(adjustedPoints);\n\n this.data = {\n points,\n path,\n bbox,\n };\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { type IPoint, Point, Rectangle } from '@flowgram.ai/utils';\nimport { LinePoint } from '@flowgram.ai/free-layout-core';\n\n/**\n * 计算点到线段的距离\n * @param point 待测试点\n * @param segStart 线段起点\n * @param segEnd 线段终点\n */\nconst getPointToSegmentDistance = (point: IPoint, segStart: IPoint, segEnd: IPoint): number => {\n const { x: px, y: py } = point;\n const { x: x1, y: y1 } = segStart;\n const { x: x2, y: y2 } = segEnd;\n\n const A = px - x1;\n const B = py - y1;\n const C = x2 - x1;\n const D = y2 - y1;\n\n const dot = A * C + B * D;\n const lenSq = C * C + D * D;\n\n // 参数方程中的t参数\n const param = lenSq === 0 ? -1 : dot / lenSq;\n\n let xx: number;\n let yy: number;\n\n if (param < 0) {\n xx = x1;\n yy = y1;\n } else if (param > 1) {\n xx = x2;\n yy = y2;\n } else {\n xx = x1 + param * C;\n yy = y1 + param * D;\n }\n\n const dx = px - xx;\n const dy = py - yy;\n\n return Math.sqrt(dx * dx + dy * dy);\n};\n\n/**\n * Fork from: https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/edges/smoothstep-edge.ts\n * MIT License\n * Copyright (c) 2019-2024 webkid GmbH\n */\nexport namespace FoldLine {\n const EDGE_RADIUS = 5;\n const OFFSET = 20;\n\n function getEdgeCenter({ source, target }: { source: IPoint; target: IPoint }): [number, number] {\n const xOffset = Math.abs(target.x - source.x) / 2;\n const centerX = target.x < source.x ? target.x + xOffset : target.x - xOffset;\n\n const yOffset = Math.abs(target.y - source.y) / 2;\n const centerY = target.y < source.y ? target.y + yOffset : target.y - yOffset;\n\n return [centerX, centerY];\n }\n\n const getDirection = ({ source, target }: { source: LinePoint; target: LinePoint }): IPoint => {\n if (source.location === 'left' || source.location === 'right') {\n return source.x < target.x ? { x: 1, y: 0 } : { x: -1, y: 0 };\n }\n return source.y < target.y ? { x: 0, y: 1 } : { x: 0, y: -1 };\n };\n\n const handleDirections = {\n left: { x: -1, y: 0 },\n right: { x: 1, y: 0 },\n top: { x: 0, y: -1 },\n bottom: { x: 0, y: 1 },\n };\n // eslint-disable-next-line complexity\n export function getPoints({\n source,\n target,\n }: {\n source: LinePoint;\n target: LinePoint;\n }): IPoint[] {\n const sourceDir = handleDirections[source.location];\n const targetDir = handleDirections[target.location];\n const sourceGapped: LinePoint = {\n x: source.x + sourceDir.x * OFFSET,\n y: source.y + sourceDir.y * OFFSET,\n location: source.location,\n };\n const targetGapped: LinePoint = {\n x: target.x + targetDir.x * OFFSET,\n y: target.y + targetDir.y * OFFSET,\n location: target.location,\n };\n const dir = getDirection({\n source: sourceGapped,\n target: targetGapped,\n });\n const dirAccessor = dir.x !== 0 ? 'x' : 'y';\n const currDir = dir[dirAccessor];\n\n let points: IPoint[] = [];\n let centerX, centerY;\n\n const [defaultCenterX, defaultCenterY] = getEdgeCenter({\n source,\n target,\n });\n\n // 计算向量乘积\n if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {\n centerX = defaultCenterX;\n centerY = defaultCenterY;\n\n const verticalSplit: IPoint[] = [\n { x: centerX, y: sourceGapped.y },\n { x: centerX, y: targetGapped.y },\n ];\n\n const horizontalSplit: IPoint[] = [\n { x: sourceGapped.x, y: centerY },\n { x: targetGapped.x, y: centerY },\n ];\n\n if (sourceDir[dirAccessor] === currDir) {\n points = dirAccessor === 'x' ? verticalSplit : horizontalSplit;\n } else {\n points = dirAccessor === 'x' ? horizontalSplit : verticalSplit;\n }\n } else {\n // sourceTarget means we take x from source and y from target, targetSource is the opposite\n const sourceTarget: IPoint[] = [{ x: sourceGapped.x, y: targetGapped.y }];\n const targetSource: IPoint[] = [{ x: targetGapped.x, y: sourceGapped.y }];\n // this handles edges with same handle positions\n if (dirAccessor === 'x') {\n points = sourceDir.x === currDir ? targetSource : sourceTarget;\n } else {\n points = sourceDir.y === currDir ? sourceTarget : targetSource;\n }\n\n // these are conditions for handling mixed handle positions like Right -> Bottom for example\n const dirAccessorOpposite = dirAccessor === 'x' ? 'y' : 'x';\n const isSameDir = sourceDir[dirAccessor] === targetDir[dirAccessorOpposite];\n const sourceGtTargetOppo =\n sourceGapped[dirAccessorOpposite] > targetGapped[dirAccessorOpposite];\n const sourceLtTargetOppo =\n sourceGapped[dirAccessorOpposite] < targetGapped[dirAccessorOpposite];\n const flipSourceTarget =\n (sourceDir[dirAccessor] === 1 &&\n ((!isSameDir && sourceGtTargetOppo) || (isSameDir && sourceLtTargetOppo))) ||\n (sourceDir[dirAccessor] !== 1 &&\n ((!isSameDir && sourceLtTargetOppo) || (isSameDir && sourceGtTargetOppo)));\n\n if (flipSourceTarget) {\n points = dirAccessor === 'x' ? sourceTarget : targetSource;\n }\n\n const sourceGapPoint = { x: sourceGapped.x, y: sourceGapped.y };\n const targetGapPoint = { x: targetGapped.x, y: targetGapped.y };\n const maxXDistance = Math.max(\n Math.abs(sourceGapPoint.x - points[0].x),\n Math.abs(targetGapPoint.x - points[0].x)\n );\n const maxYDistance = Math.max(\n Math.abs(sourceGapPoint.y - points[0].y),\n Math.abs(targetGapPoint.y - points[0].y)\n );\n\n if (maxXDistance >= maxYDistance) {\n centerX = (sourceGapPoint.x + targetGapPoint.x) / 2;\n centerY = points[0].y;\n } else {\n centerX = points[0].x;\n centerY = (sourceGapPoint.y + targetGapPoint.y) / 2;\n }\n }\n\n const pathPoints = [\n source,\n { x: sourceGapped.x, y: sourceGapped.y },\n ...points,\n { x: targetGapped.x, y: targetGapped.y },\n target,\n ];\n\n return pathPoints;\n }\n\n function getBend(a: IPoint, b: IPoint, c: IPoint): string {\n const bendSize = Math.min(\n Point.getDistance(a, b) / 2,\n Point.getDistance(b, c) / 2,\n EDGE_RADIUS\n );\n const { x, y } = b;\n\n // no bend\n if ((a.x === x && x === c.x) || (a.y === y && y === c.y)) {\n return `L${x} ${y}`;\n }\n\n // first segment is horizontal\n if (a.y === y) {\n const xDir = a.x < c.x ? -1 : 1;\n const yDir = a.y < c.y ? 1 : -1;\n return `L ${x + bendSize * xDir},${y}Q ${x},${y} ${x},${y + bendSize * yDir}`;\n }\n\n const xDir = a.x < c.x ? 1 : -1;\n const yDir = a.y < c.y ? -1 : 1;\n return `L ${x},${y + bendSize * yDir}Q ${x},${y} ${x + bendSize * xDir},${y}`;\n }\n\n /**\n * 实现 reactFlow 原本的折叠线交互\n */\n export function getSmoothStepPath(points: IPoint[]): string {\n const path = points.reduce<string>((res, p, i) => {\n let segment = '';\n\n if (i > 0 && i < points.length - 1) {\n segment = getBend(points[i - 1], p, points[i + 1]);\n } else {\n segment = `${i === 0 ? 'M' : 'L'}${p.x} ${p.y}`;\n }\n\n res += segment;\n\n return res;\n }, '');\n\n return path;\n }\n export function getBounds(points: IPoint[]): Rectangle {\n const xList = points.map((p) => p.x);\n const yList = points.map((p) => p.y);\n const left = Math.min(...xList);\n const right = Math.max(...xList);\n const top = Math.min(...yList);\n const bottom = Math.max(...yList);\n return Rectangle.createRectangleWithTwoPoints(\n {\n x: left,\n y: top,\n },\n {\n x: right,\n y: bottom,\n }\n );\n }\n /**\n * 计算点到折线的最短距离\n * @param points 折线的所有端点\n * @param pos 待测试点\n * @returns 最短距离\n */\n export const getFoldLineToPointDistance = (points: IPoint[], pos: IPoint): number => {\n // 特殊情况处理\n if (points.length === 0) {\n return Infinity;\n }\n\n if (points.length === 1) {\n return Point.getDistance(points[0]!, pos);\n }\n\n // 构建线段数组\n const lines: [IPoint, IPoint][] = [];\n for (let i = 0; i < points.length - 1; i++) {\n lines.push([points[i]!, points[i + 1]!]);\n }\n\n // 计算点到每个线段的最短距离\n const distances = lines.map((line) => {\n const [p1, p2] = line;\n return getPointToSegmentDistance(pos, p1, p2);\n });\n\n return Math.min(...distances);\n };\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { IPoint, Point, Rectangle } from '@flowgram.ai/utils';\nimport {\n POINT_RADIUS,\n WorkflowLineEntity,\n WorkflowLineRenderContribution,\n LinePoint,\n} from '@flowgram.ai/free-layout-core';\n\nimport { LINE_PADDING } from '../../constants/lines';\nimport { projectPointOnLine } from './point-on-line';\n\nexport interface StraightData {\n points: IPoint[];\n path: string;\n bbox: Rectangle;\n}\n\nexport class WorkflowStraightLineContribution implements WorkflowLineRenderContribution {\n public static type = 'WorkflowStraightLineContribution';\n\n public entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n this.entity = entity;\n }\n\n private data?: StraightData;\n\n public get path(): string {\n return this.data?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n if (!this.data) {\n return Number.MAX_SAFE_INTEGER;\n }\n const [start, end] = this.data.points;\n return Point.getDistance(pos, projectPointOnLine(pos, start, end));\n }\n\n public get bounds(): Rectangle {\n if (!this.data) {\n return new Rectangle();\n }\n return this.data.bbox;\n }\n\n public update(params: { fromPos: LinePoint; toPos: LinePoint }): void {\n const { fromPos, toPos } = params;\n\n // 根据方向预先计算源点和目标点的偏移\n const sourceOffset = {\n x: fromPos.location === 'bottom' ? 0 : POINT_RADIUS,\n y: fromPos.location === 'bottom' ? POINT_RADIUS : 0,\n };\n const targetOffset = {\n x: toPos.location === 'top' ? 0 : -POINT_RADIUS,\n y: toPos.location === 'top' ? -POINT_RADIUS : 0,\n };\n\n const points = [\n {\n x: fromPos.x + sourceOffset.x,\n y: fromPos.y + sourceOffset.y,\n },\n {\n x: toPos.x + targetOffset.x,\n y: toPos.y + targetOffset.y,\n },\n ];\n\n const bbox = Rectangle.createRectangleWithTwoPoints(points[0], points[1]);\n\n // 调整所有点到 SVG 视口坐标系\n const adjustedPoints = points.map((p) => ({\n x: p.x - bbox.x + LINE_PADDING,\n y: p.y - bbox.y + LINE_PADDING,\n }));\n\n // 生成直线路径\n const path = `M ${adjustedPoints[0].x} ${adjustedPoints[0].y} L ${adjustedPoints[1].x} ${adjustedPoints[1].y}`;\n\n this.data = {\n points,\n path,\n bbox,\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';\n\nexport interface StraightData {\n points: IPoint[];\n path: string;\n bbox: Rectangle;\n}\n\n/**\n * 计算点到直线的投影点\n */\nexport function projectPointOnLine(point: IPoint, lineStart: IPoint, lineEnd: IPoint): IPoint {\n const dx = lineEnd.x - lineStart.x;\n const dy = lineEnd.y - lineStart.y;\n\n // 如果是垂直线\n if (dx === 0) {\n return { x: lineStart.x, y: point.y };\n }\n // 如果是水平线\n if (dy === 0) {\n return { x: point.x, y: lineStart.y };\n }\n\n const t = ((point.x - lineStart.x) * dx + (point.y - lineStart.y) * dy) / (dx * dx + dy * dy);\n const clampedT = Math.max(0, Math.min(1, t));\n\n return {\n x: lineStart.x + clampedT * dx,\n y: lineStart.y + clampedT * dy,\n };\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { IPoint, Point, Rectangle } from '@flowgram.ai/utils';\nimport {\n POINT_RADIUS,\n WorkflowLineEntity,\n WorkflowLineRenderContribution,\n} from '@flowgram.ai/free-layout-core';\n\nimport { LINE_PADDING } from '../../constants/lines';\n\nexport interface ArcData {\n fromPos: IPoint;\n toPos: IPoint;\n path: string;\n bbox: Rectangle;\n}\n\nexport class WorkflowArkLineContribution implements WorkflowLineRenderContribution {\n public static type = 'WorkflowArkLineContribution';\n\n public entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n this.entity = entity;\n }\n\n private data?: ArcData;\n\n public get path(): string {\n return this.data?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n if (!this.data) {\n return Number.MAX_SAFE_INTEGER;\n }\n\n const { fromPos, toPos, bbox } = this.data;\n\n // 首先检查点是否在包围盒范围内\n if (!bbox.contains(pos.x, pos.y)) {\n // 如果点在包围盒外,计算到包围盒边界的最短距离\n const dx = Math.max(bbox.x - pos.x, 0, pos.x - (bbox.x + bbox.width));\n const dy = Math.max(bbox.y - pos.y, 0, pos.y - (bbox.y + bbox.height));\n return Math.sqrt(dx * dx + dy * dy);\n }\n\n // 计算圆弧的中心点和半径\n const center = {\n x: (fromPos.x + toPos.x) / 2,\n y: (fromPos.y + toPos.y) / 2,\n };\n const radius = Point.getDistance(fromPos, center);\n\n // 计算点到圆心的距离\n const distanceToCenter = Point.getDistance(pos, center);\n\n // 返回点到圆弧的近似距离\n return Math.abs(distanceToCenter - radius);\n }\n\n public get bounds(): Rectangle {\n if (!this.data) {\n return new Rectangle();\n }\n return this.data.bbox;\n }\n\n public update(params: { fromPos: IPoint; toPos: IPoint }): void {\n const { fromPos, toPos } = params;\n const { vertical } = this.entity;\n\n const sourceOffset = {\n x: vertical ? 0 : POINT_RADIUS,\n y: vertical ? POINT_RADIUS : 0,\n };\n const targetOffset = {\n x: vertical ? 0 : -POINT_RADIUS,\n y: vertical ? -POINT_RADIUS : 0,\n };\n\n const start = {\n x: fromPos.x + sourceOffset.x,\n y: fromPos.y + sourceOffset.y,\n };\n const end = {\n x: toPos.x + targetOffset.x,\n y: toPos.y + targetOffset.y,\n };\n\n // 计算圆弧的包围盒\n const bbox = this.calculateArcBBox(start, end);\n\n // 生成圆弧路径\n const path = this.getArcPath(start, end, bbox);\n\n this.data = {\n fromPos: start,\n toPos: end,\n path,\n bbox,\n };\n }\n\n private calculateArcBBox(start: IPoint, end: IPoint): Rectangle {\n const dx = end.x - start.x;\n const dy = end.y - start.y;\n const radius = Math.sqrt(dx * dx + dy * dy) / 2;\n\n const centerX = (start.x + end.x) / 2;\n const centerY = (start.y + end.y) / 2;\n\n return new Rectangle(centerX - radius, centerY - radius, radius * 2, radius * 2);\n }\n\n private getArcPath(start: IPoint, end: IPoint, bbox: Rectangle): string {\n const dx = end.x - start.x;\n const dy = end.y - start.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n // 调整点到相对坐标\n const startRel = {\n x: start.x - bbox.x + LINE_PADDING,\n y: start.y - bbox.y + LINE_PADDING,\n };\n const endRel = {\n x: end.x - bbox.x + LINE_PADDING,\n y: end.y - bbox.y + LINE_PADDING,\n };\n\n // 使用 SVG 圆弧命令\n return `M ${startRel.x} ${startRel.y} A ${distance / 2} ${distance / 2} 0 0 1 ${endRel.x} ${\n endRel.y\n }`;\n }\n}\n"],"mappings":";;;;;;;;;;;;AAKA,OAAO,cAAc;AACrB,OAAOA,UAAS,WAAW,gBAAgB;AAE3C,OAAO,gBAAgB;AACvB;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB,kBAAkB;;;ACRrC,IAAM,uBAAuB;AAE7B,IAAM,eAAe;AAErB,IAAM,qBAAqB;;;ACNlC,OAAO,YAAY;AAEZ,IAAM,qBAAqB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACFzC,OAAO,WAAW;AAGH,SAAR,YAA0C;AAC/C,SACE,oCAAC,SAAI,WAAU,YACb,oCAAC,SAAI,WAAU,cAAa,CAC9B;AAEJ;;;AHsBO,IAAM;AAAA;AAAA,EAEXC,OAAM,KAA8B,CAAC,UAAmC;AACtE,UAAM,eAAe,WAAiC,oBAAoB;AAC1E,UAAM,eAAe,WAAiC,oBAAoB;AAC1E,UAAM,EAAE,QAAQ,QAAQ,IAAI;AAC5B,UAAM,EAAE,UAAU,kBAAkB,SAAS,IAAI;AACjD,UAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,OAAO,aAAa;AACvE,UAAM,CAAC,MAAM,UAAU,IAAI,SAAS,iBAAiB,CAAC;AACtD,UAAM,CAAC,MAAM,UAAU,IAAI,SAAS,iBAAiB,CAAC;AACtD,UAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,UAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,QAAQ,QAAQ,OAAO,MAAM,CAAC;AACnE,UAAM,CAAC,UAAU,WAAW,IAAI,SAAS,MAAM,OAAO,QAAQ;AAC9D,UAAM,WAAW,2BAA2B;AAE5C,cAAU,MAAM;AAEd,aAAO,SAAS;AAChB,kBAAY,OAAO,QAAQ;AAC3B,YAAM,UAAU,OAAO,eAAe,MAAM;AAE1C,YAAI,OAAO,eAAe;AACxB,cAAI,OAAO,kBAAkB,eAAe;AAC1C,6BAAiB,OAAO,aAAa;AAAA,UACvC;AACA;AAAA,QACF;AACA,cAAM,SAAS,OAAO;AAEtB,mBAAW,KAAK,MAAM,OAAO,CAAC,CAAC;AAC/B,mBAAW,KAAK,MAAM,OAAO,CAAC,CAAC;AAAA,MACjC,CAAC;AACD,YAAM,WAAW,aAAa,gBAAgB,CAAC,OAAO;AACpD,mBAAW,aAAa,UAAU,OAAO,EAAE,CAAC;AAAA,MAC9C,CAAC;AACD,YAAM,WAAW,OAAO,eAAe,MAAM;AAC3C,oBAAY,OAAO,QAAQ;AAAA,MAC7B,CAAC;AACD,YAAM,WAAW,aAAa,uBAAuB,MAAM;AACzD,mBAAW,MAAM;AACf,cAAI,aAAa,YAAY,OAAO,SAAU;AAC9C,oBAAU,QAAQ,OAAO,MAAM,MAAM,CAAC;AAAA,QACxC,GAAG,CAAC;AAAA,MACN,CAAC;AACD,aAAO,MAAM;AACX,gBAAQ,QAAQ;AAChB,iBAAS,QAAQ;AACjB,iBAAS,QAAQ;AACjB,iBAAS,QAAQ;AAAA,MACnB;AAAA,IACF,GAAG,CAAC,cAAc,QAAQ,aAAa,CAAC;AAGxC,UAAM,YAAY,WAAW,wBAAwB,MAAM,aAAa,IAAI;AAAA,MAC1E,SAAS,CAAC,YAAY,WAAW,CAAC,YAAY,aAAa;AAAA;AAAA,MAE3D;AAAA,IACF,CAAC;AAGD,UAAM,cAAsC,CAAC;AAC7C,QAAI,MAAM,cAAc;AACtB,kBAAY,iCAAiC,IAAI,MAAM;AAAA,IACzD;AACA,QAAI,MAAM,gBAAgB;AACxB,kBAAY,mCAAmC,IAAI,MAAM;AAAA,IAC3D;AACA,QAAI,MAAM,YAAY;AACpB,kBAAY,+BAA+B,IAAI,MAAM;AAAA,IACvD;AACA,QAAI,MAAM,iBAAiB;AACzB,kBAAY,oCAAoC,IAAI,MAAM;AAAA,IAC5D;AAEA,UAAM,gBAAgB,gBAClB,EAAE,GAAG,MAAM,OAAO,GAAG,YAAY,IACjC,EAAE,GAAG,MAAM,OAAO,GAAG,aAAa,MAAM,MAAM,KAAK,KAAK;AAE5D,UAAM,UACJ,gBAAAA,OAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAO;AAAA,QACP,SAAS,CAAC,MAAM,UAAU,GAAG,MAAM;AAAA,QACnC,cAAc,CAAC,MAAM;AACnB,cAAI,CAAC,SAAS;AACZ;AAAA,UACF;AACA,0BAAgB,UAAU,GAAG,CAAC,eAAe;AAC3C,oBAAQ,YAA2D,MAAM;AAAA,UAC3E,CAAC;AAAA,QACH;AAAA,QACA,uBAAqB,OAAO;AAAA,QAC5B,yBAAuB,OAAO;AAAA,QAC9B,eAAY;AAAA;AAAA,MAEZ,gBAAAA,OAAA,cAAC,SAAI,WAAW,WAAW,aAAa,oBAAoB,GAAG;AAAA,MAC/D,gBAAAA,OAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,WAAW;AAAA,YACpB,IAAI;AAAA,YACJ,CAAC,kBAAkB,GAAG;AAAA,YACtB,qBAAqB;AAAA,YACrB;AAAA,UACF,CAAC;AAAA;AAAA,QAED,gBAAAA,OAAA,cAAC,eAAU;AAAA,MACb;AAAA,MACA,gBAAAA,OAAA,cAAC,SAAI,WAAU,gBAAe;AAAA,IAChC;AAEF,QAAI,eAAe;AACjB,aAAO,SAAS,aAAa,SAAS,aAAa;AAAA,IACrD;AACA,WAAO;AAAA,EACT,CAAC;AAAA;;;AI/II,IAAM,cAAc;AAEpB,IAAM,eAAe;;;ACH5B,SAAS,wBAAAC,6BAA4B;AACrC,SAAS,2BAA0C;;;ACDnD,OAAOC,eAAc;AACrB,OAAOC,UAAoB,iBAAiB,YAAAC,iBAAgB;AAE5D,SAAS,QAAQ,kBAAkB;AACnC,SAAS,gBAAgB;AACzB,SAAS,4BAA4B;AACrC,SAAS,8BAA8B;AACvC;AAAA,EACE;AAAA,EACA;AAAA,EACA,wBAAAC;AAAA,EACA;AAAA,EACA,0BAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,OAAO,iBAAiB,oBAAoB,qBAAqB;;;ACjB1E,SAAS,YAAY;;;ACArB,OAAOC,YAAW;AAElB,OAAO,UAAU;AAEjB,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;;;ACLvC,OAAOC,aAAY;AAIZ,IAAM,YAAYA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACJhC,OAAOC,YAAW;AAKX,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,MAAI,MAAM;AACR,WAAO;AAAA,EACT;AACA,QAAM,YAAY,WACd,eACE,KAAK,IAAI,IAAI,WAAW,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,IAAI,WAAW,MACjE,IAAI,IAAI,WACV,IAAI,IAAI,CAAC,KACT,KAAK,IAAI,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,MACjE,IAAI,IAAI,WACV,IAAI,IAAI,IAAI,WAAW,KACzB,eACA,KAAK,IAAI,CAAC,IAAI,IAAI,IAAI,WAAW,MAAM,IAAI,IAAI,WAAW,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAC5E,IAAI,IAAI,WACV,KACA,KAAK,IAAI,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,MACjE,IAAI,IAAI,WACV,IAAI,IAAI,IAAI,WAAW;AAE3B,SACE,gBAAAC,OAAA;AAAA,IAAC;AAAA;AAAA,MACC,GAAG;AAAA,MACH,eAAc;AAAA,MACd,QAAQ,QAAQ,EAAE;AAAA,MAClB,MAAK;AAAA,MACL;AAAA;AAAA,EACF;AAEJ;;;AF3BA,IAAM,UAAU;AAET,IAAM,UAAU,CAAC,UAA2B;AACjD,QAAM,EAAE,MAAM,OAAO,UAAU,UAAU,cAAc,iBAAiB,IAAI;AAC5E,QAAM,EAAE,UAAU,SAAS,WAAW,SAAS,IAAI;AAEnD,QAAM,aAAa,KAAK,QAAQ,sBAAsB;AACtD,QAAM,EAAE,QAAQ,MAAM,WAAW,IAAI;AAGrC,QAAM,aAAa,CAAC,OAAuB;AAAA,IACzC,GAAG,EAAE,IAAI,OAAO,IAAI;AAAA,IACpB,GAAG,EAAE,IAAI,OAAO,IAAI;AAAA,EACtB;AAEA,QAAM,UAAU,WAAW,SAAS,IAAI;AACxC,QAAM,QAAQ,WAAW,SAAS,EAAE;AAGpC,QAAM,aACJ,SAAS,GAAG,aAAa,QACrB,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,IAAI,aAAa,IACxC,EAAE,GAAG,MAAM,IAAI,cAAc,GAAG,MAAM,EAAE;AAC9C,QAAM,eACJ,SAAS,KAAK,aAAa,WACvB,EAAE,GAAG,QAAQ,GAAG,GAAG,QAAQ,IAAI,eAAe,YAAY,IAC1D,EAAE,GAAG,QAAQ,IAAI,eAAe,aAAa,GAAG,QAAQ,EAAE;AAEhE,QAAM,cAAc,WAChB,KAAK,QAAQ,uBAAuB,uBACpC,KAAK,QAAQ,eAAe;AAEhC,QAAM,WAAW,eAAe,GAAG,YAAY,IAAI,KAAK,EAAE,KAAK,KAAK;AAGpE,QAAM,sBAAsB,kBAAkB,0BAA0B,gBAAgB,GACpF;AACJ,QAAM,iBAAiB,uBAAuB;AAE9C,QAAM,OACJ,gBAAAC,OAAA;AAAA,IAAC;AAAA;AAAA,MACC,GAAG;AAAA,MACH,MAAK;AAAA,MACL,QAAQ,QAAQ,QAAQ;AAAA,MACxB;AAAA,MACA,WAAW,KAAK,cAAc,KAAK,UAAU,6BAA6B;AAAA;AAAA,EAC5E;AAGF,SACE,gBAAAA,OAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,KAAK,4BAA4B,KAAK,SAAS;AAAA,MAC1D,OAAO;AAAA,QACL,GAAG,KAAK,QAAQ;AAAA,QAChB,MAAM,OAAO,IAAI;AAAA,QACjB,KAAK,OAAO,IAAI;AAAA,QAChB,UAAU;AAAA,MACZ;AAAA;AAAA,IAEC;AAAA,IACD,gBAAAA,OAAA,cAAC,SAAI,OAAO,OAAO,QAAQ,UAAU,GAAG,QAAQ,OAAO,SAAS,UAAU,KACxE,gBAAAA,OAAA,cAAC,cACC,gBAAAA,OAAA;AAAA,MAAC;AAAA;AAAA,QACC,IAAI,WAAW,SAAS;AAAA,QACxB,IAAI,WAAW,OAAO;AAAA,QACtB,IAAG;AAAA,QACH,IAAG;AAAA,QACH,IAAI;AAAA,QACJ,eAAc;AAAA;AAAA,MAEd,gBAAAA,OAAA,cAAC,UAAK,WAAW,OAAO,QAAO,MAAK;AAAA,MACpC,gBAAAA,OAAA,cAAC,UAAK,WAAW,OAAO,QAAO,QAAO;AAAA,IACxC,CACF,GACA,gBAAAA,OAAA,cAAC,WACE,MACD,gBAAAA,OAAA;AAAA,MAAC;AAAA;AAAA,QACC,IAAI;AAAA,QACJ,cAAc;AAAA,QACd,KAAK,UAAU,eAAe;AAAA,QAC9B;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN;AAAA;AAAA,IACF,CACF,CACF;AAAA,EACF;AAEJ;;;ADnGO,IAAM,qBAAqB;AAAA,EAChC;AAAA,EACA,CAAC,WAAW,cAAc,UAAU,YAAY,UAAU;AAC5D;;;ADgBO,IAAM,qBAAN,cAAiC,MAAyB;AAAA,EAA1D;AAAA;AAoBL,SAAQ,UAAU,OAAO;AAEzB,SAAQ,eAOJ,oBAAI,IAAI;AAEZ,SAAQ,WAAW;AAKnB;AAAA;AAAA;AAAA,SAAO,OAAO,SAAS,mBAAmB,+CAA+C;AAAA;AAAA,EAElF,OAAO,OAAqB;AACjC,SAAK,KAAK,MAAM,YAAY,SAAS,KAAK;AAAA,EAC5C;AAAA,EAEO,UAAU;AACf,SAAK,aAAa,YAAY,KAAK,IAAI;AACvC,SAAK,UAAU,QAAQ;AAAA,MACrB,KAAK,cAAc,mBAAmB,MAAM,KAAK,OAAO,CAAC;AAAA,MACzD,KAAK,aAAa,gBAAgB,MAAM,KAAK,OAAO,CAAC;AAAA,MACrD,KAAK,iBAAiB,aAAa,cAAc,MAAM;AACrD,aAAK,aAAa,MAAM;AACxB,aAAK,YAAY;AACjB,aAAK,OAAO;AAAA,MACd,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEO,UAAU;AACf,SAAK,aAAa,MAAM;AAAA,EAC1B;AAAA,EAEO,SAAsB;AAC3B,UAAM,CAAC,EAAE,WAAW,IAAIC,UAAS,CAAC,CAAC;AAEnC,oBAAgB,MAAM;AACpB,YAAM,cAAc,MAAY;AAC9B,YAAI,cAAc;AAGlB,aAAK,MAAM,QAAQ,CAAC,SAAS;AAC3B,gBAAM,aAAa,KAAK,QAAQC,uBAAsB;AACtD,gBAAM,aAAa,WAAW;AAC9B,qBAAW,OAAO;AAElB,cAAI,WAAW,kBAAkB,YAAY;AAC3C,0BAAc;AAAA,UAChB;AAAA,QACF,CAAC;AAGD,YAAI,aAAa;AACf,sBAAY,CAAC,CAAC;AAAA,QAChB;AAAA,MACF;AAEA,YAAM,QAAQ,sBAAsB,WAAW;AAC/C,aAAO,MAAM,qBAAqB,KAAK;AAAA,IACzC,GAAG,CAAC,KAAK,KAAK,CAAC;AAEf,UAAM,QAAQ,KAAK,MAAM,IAAI,CAAC,SAAS,KAAK,WAAW,IAAI,CAAC;AAC5D,WAAO,gBAAAC,OAAA,cAAAA,OAAA,gBAAG,KAAM;AAAA,EAClB;AAAA;AAAA,EAGQ,cAAc;AACpB,SAAK,WAAW,KAAK,WAAW;AAChC,QAAI,KAAK,aAAa,OAAO,kBAAkB;AAC7C,WAAK,WAAW;AAAA,IAClB;AAAA,EACF;AAAA,EAEQ,UAAU,MAA2C;AAC3D,UAAM,EAAE,SAAS,IAAI,KAAK,iBAAiB;AAC3C,UAAM,WAAW,KAAK,cAAc,WAAW,KAAK,EAAE;AACtD,UAAM,UAAU,KAAK,aAAa,UAAU,KAAK,EAAE;AACnD,UAAM,UAAU,KAAK,YAAY,IAAI;AAErC,WAAO;AAAA,MACL,KAAK,KAAK;AAAA,MACV,OAAO,KAAK;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc,KAAK;AAAA,MACnB,kBAAkB,KAAK;AAAA,IACzB;AAAA,EACF;AAAA,EAEQ,YAAY,MAAkC;AACpD,UAAM,aAAa,KAAK,QAAQD,uBAAsB;AACtD,UAAM,EAAE,cAAc,IAAI;AAC1B,UAAM,WAAW,KAAK,cAAc,WAAW,KAAK,EAAE;AACtD,UAAM,UAAU,KAAK,aAAa,UAAU,KAAK,EAAE;AACnD,UAAM,EAAE,SAAS,aAAa,MAAM,IAAI;AAExC,UAAM,UAAU,KAAK,KAAK,QAAQ,OAAO,WAAW,OAAO,aAAa,MAAM,KAAK,MACjF,WAAW,MAAM,GACnB,MAAM,UAAU,MAAM,GAAG;AAEzB,WAAO;AAAA,EACT;AAAA,EAEQ,cAAc,OAAmC;AACvD,UAAM,mBAAmB,KAAK,QAAQ,qBAAqB,MAAM,gBAAAC,OAAA,cAAAA,OAAA,cAAE;AACnE,WACE,gBAAAA,OAAA,cAAC,sBAAoB,GAAG,SACtB,gBAAAA,OAAA,cAAC,oBAAkB,GAAG,OAAO,CAC/B;AAAA,EAEJ;AAAA,EAEQ,WAAW,MAAqC;AACtD,UAAM,YAAY,KAAK,UAAU,IAAI;AACrC,UAAM,QAAQ,KAAK,aAAa,IAAI,KAAK,EAAE;AAC3C,UAAM,WAAW,UAAU;AAC3B,UAAM,EAAE,QAAQ,cAAc,SAAS,cAAc,IAAI,SAAS,CAAC;AACnE,QAAI,YAAY,kBAAkB,UAAU,SAAS;AAEnD,aAAO;AAAA,IACT;AACA,QAAI,CAAC,UAAU;AAEb,WAAK,cAAc,YAAY,KAAK,IAAI;AACxC,WAAK,UAAU,MAAM;AACnB,aAAK,aAAa,OAAO,KAAK,EAAE;AAChC,aAAK,KAAK,OAAO;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,UAAM,SAASC,UAAS,aAAa,KAAK,cAAc,SAAS,GAAG,KAAK,IAAI;AAC7E,SAAK,aAAa,IAAI,KAAK,IAAI,EAAE,MAAM,QAAQ,SAAS,UAAU,QAAQ,CAAC;AAC3E,WAAO;AAAA,EACT;AAAA,EAEA,IAAY,gBAA6B;AACvC,WAAO,KAAK,aAAa;AAAA,EAC3B;AACF;AAvKa,mBACJ,OAAO;AAEgB;AAAA,EAA7B,OAAOC,qBAAoB;AAAA,GAHjB,mBAGmB;AAEC;AAAA,EAA9B,OAAO,qBAAqB;AAAA,GALlB,mBAKoB;AAEC;AAAA,EAA/B,OAAO,sBAAsB;AAAA,GAPnB,mBAOqB;AAEF;AAAA,EAA7B,OAAO,oBAAoB;AAAA,GATjB,mBASmB;AAEgB;AAAA,EAA7C,gBAAgB,kBAAkB;AAAA,GAXxB,mBAWmC;AAEA;AAAA,EAA7C,gBAAgB,kBAAkB;AAAA,GAbxB,mBAamC;AAGrC;AAAA,EADR,mBAAmB,oBAAoB,aAAa;AAAA,GAf1C,mBAgBF;AAE2B;AAAA,EAAnC,OAAO,gBAAgB;AAAA,GAlBb,mBAkByB;AAlBzB,qBAAN;AAAA,EADN,WAAW;AAAA,GACC;;;AKvBb,SAAS,cAAc;AACvB,SAAiB,OAAO,iBAAiB;AAMzC,SAAS,gBAAgB;;;ACJzB,SAAS,iBAAiB,UAAkB,WAA2B;AACrE,MAAI,YAAY,GAAG;AACjB,WAAO,MAAM;AAAA,EACf;AAEA,SAAO,YAAY,KAAK,KAAK,KAAK,CAAC,QAAQ;AAC7C;AAEA,SAAS,wBAAwB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOW;AACT,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO;AAAA,QACL,GAAG,KAAK,iBAAiB,KAAK,IAAI,SAAS;AAAA,QAC3C,GAAG;AAAA,MACL;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,GAAG,KAAK,iBAAiB,KAAK,IAAI,SAAS;AAAA,QAC3C,GAAG;AAAA,MACL;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG,KAAK,iBAAiB,KAAK,IAAI,SAAS;AAAA,MAC7C;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG,KAAK,iBAAiB,KAAK,IAAI,SAAS;AAAA,MAC7C;AAAA,EACJ;AACF;AAEO,SAAS,uBACd,SACA,OACA,YAAY,MACF;AACV,QAAM,cAAc,wBAAwB;AAAA,IAC1C,UAAU,QAAQ;AAAA,IAClB,IAAI,QAAQ;AAAA,IACZ,IAAI,QAAQ;AAAA,IACZ,IAAI,MAAM;AAAA,IACV,IAAI,MAAM;AAAA,IACV;AAAA,EACF,CAAC;AACD,QAAM,YAAY,wBAAwB;AAAA,IACxC,UAAU,MAAM;AAAA,IAChB,IAAI,MAAM;AAAA,IACV,IAAI,MAAM;AAAA,IACV,IAAI,QAAQ;AAAA,IACZ,IAAI,QAAQ;AAAA,IACZ;AAAA,EACF,CAAC;AACD,SAAO,CAAC,aAAa,SAAS;AAChC;;;ADnDO,IAAM,iCAAN,MAA+E;AAAA,EAKpF,YAAY,QAA4B;AACtC,SAAK,SAAS;AAAA,EAChB;AAAA,EAIA,IAAW,OAAe;AACxB,WAAO,KAAK,MAAM,QAAQ;AAAA,EAC5B;AAAA,EAEO,aAAa,KAAqB;AACvC,QAAI,CAAC,KAAK,MAAM;AACd,aAAO,OAAO;AAAA,IAChB;AACA,WAAO,MAAM,YAAY,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,CAAC;AAAA,EAC7D;AAAA,EAEA,IAAW,SAAoB;AAC7B,QAAI,CAAC,KAAK,MAAM;AACd,aAAO,IAAI,UAAU;AAAA,IACvB;AACA,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EAEO,OAAO,QAAwD;AACpE,SAAK,OAAO,KAAK,WAAW,OAAO,SAAS,OAAO,KAAK;AAAA,EAC1D;AAAA,EAEQ,WAAW,SAAoB,OAA8B;AACnE,UAAM,WAAW,uBAAuB,SAAS,OAAO,KAAK,OAAO,QAAQ,SAAS;AACrF,UAAM,SAAS,IAAI,OAAO,CAAC,SAAS,GAAG,UAAU,KAAK,CAAC;AACvD,UAAM,OAAO,OAAO,KAAK;AACzB,UAAM,aAAa,IAAI;AAAA,MACrB,KAAK,EAAE;AAAA,MACP,KAAK,EAAE;AAAA,MACP,KAAK,EAAE,MAAM,KAAK,EAAE;AAAA,MACpB,KAAK,EAAE,MAAM,KAAK,EAAE;AAAA,IACtB;AAEA,UAAM,OAAO,KAAK,QAAQ,EAAE,MAAM,YAAY,SAAS,OAAO,SAAS,CAAC;AAExE,SAAK,OAAO;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,QAAQ,QAKL;AACT,UAAM,EAAE,KAAK,IAAI;AAEjB,UAAM,aAAa,CAAC,OAAuB;AAAA,MACzC,GAAG,EAAE,IAAI,KAAK,IAAI;AAAA,MAClB,GAAG,EAAE,IAAI,KAAK,IAAI;AAAA,IACpB;AACA,UAAM,UAAU,WAAW,OAAO,OAAO;AACzC,UAAM,QAAQ,WAAW,OAAO,KAAK;AAErC,UAAM,WAAW,OAAO,SAAS,IAAI,CAAC,MAAM,WAAW,CAAC,CAAC;AACzD,UAAM,SAAS,KAAK,OAAO,QAAQ;AAEnC,UAAM,gBACJ,OAAO,QAAQ,aAAa,WACxB,EAAE,GAAG,QAAQ,GAAG,GAAG,QAAQ,IAAI,OAAO,IACtC,EAAE,GAAG,QAAQ,IAAI,QAAQ,GAAG,QAAQ,EAAE;AAE5C,UAAM,cACJ,OAAO,MAAM,aAAa,QACtB,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,IAClC,EAAE,GAAG,MAAM,IAAI,QAAQ,GAAG,MAAM,EAAE;AAExC,UAAM,gBAAgB,SAAS,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,KAAK,GAAG;AACnE,WAAO,IAAI,cAAc,CAAC,IAAI,cAAc,CAAC,MAAM,aAAa,KAAK,YAAY,CAAC,IAAI,YAAY,CAAC;AAAA,EACrG;AACF;AAxFa,+BACG,OAAO,SAAS;;;AEtBhC,SAAiB,aAAAC,kBAAiB;AAClC;AAAA,EACE,gBAAAC;AAAA,OAIK;AACP,SAAS,YAAAC,iBAAgB;;;ACPzB,SAAsB,SAAAC,QAAO,aAAAC,kBAAiB;AAS9C,IAAM,4BAA4B,CAAC,OAAe,UAAkB,WAA2B;AAC7F,QAAM,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI;AACzB,QAAM,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI;AACzB,QAAM,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI;AAEzB,QAAM,IAAI,KAAK;AACf,QAAM,IAAI,KAAK;AACf,QAAM,IAAI,KAAK;AACf,QAAM,IAAI,KAAK;AAEf,QAAM,MAAM,IAAI,IAAI,IAAI;AACxB,QAAM,QAAQ,IAAI,IAAI,IAAI;AAG1B,QAAM,QAAQ,UAAU,IAAI,KAAK,MAAM;AAEvC,MAAI;AACJ,MAAI;AAEJ,MAAI,QAAQ,GAAG;AACb,SAAK;AACL,SAAK;AAAA,EACP,WAAW,QAAQ,GAAG;AACpB,SAAK;AACL,SAAK;AAAA,EACP,OAAO;AACL,SAAK,KAAK,QAAQ;AAClB,SAAK,KAAK,QAAQ;AAAA,EACpB;AAEA,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,KAAK;AAEhB,SAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACpC;AAOO,IAAU;AAAA,CAAV,CAAUC,cAAV;AACL,QAAM,cAAc;AACpB,QAAM,SAAS;AAEf,WAAS,cAAc,EAAE,QAAQ,OAAO,GAAyD;AAC/F,UAAM,UAAU,KAAK,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI;AAChD,UAAM,UAAU,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,UAAU,OAAO,IAAI;AAEtE,UAAM,UAAU,KAAK,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI;AAChD,UAAM,UAAU,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,UAAU,OAAO,IAAI;AAEtE,WAAO,CAAC,SAAS,OAAO;AAAA,EAC1B;AAEA,QAAM,eAAe,CAAC,EAAE,QAAQ,OAAO,MAAwD;AAC7F,QAAI,OAAO,aAAa,UAAU,OAAO,aAAa,SAAS;AAC7D,aAAO,OAAO,IAAI,OAAO,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,GAAG,EAAE;AAAA,IAC9D;AACA,WAAO,OAAO,IAAI,OAAO,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG;AAAA,EAC9D;AAEA,QAAM,mBAAmB;AAAA,IACvB,MAAM,EAAE,GAAG,IAAI,GAAG,EAAE;AAAA,IACpB,OAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACpB,KAAK,EAAE,GAAG,GAAG,GAAG,GAAG;AAAA,IACnB,QAAQ,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACvB;AAEO,WAAS,UAAU;AAAA,IACxB;AAAA,IACA;AAAA,EACF,GAGa;AACX,UAAM,YAAY,iBAAiB,OAAO,QAAQ;AAClD,UAAM,YAAY,iBAAiB,OAAO,QAAQ;AAClD,UAAM,eAA0B;AAAA,MAC9B,GAAG,OAAO,IAAI,UAAU,IAAI;AAAA,MAC5B,GAAG,OAAO,IAAI,UAAU,IAAI;AAAA,MAC5B,UAAU,OAAO;AAAA,IACnB;AACA,UAAM,eAA0B;AAAA,MAC9B,GAAG,OAAO,IAAI,UAAU,IAAI;AAAA,MAC5B,GAAG,OAAO,IAAI,UAAU,IAAI;AAAA,MAC5B,UAAU,OAAO;AAAA,IACnB;AACA,UAAM,MAAM,aAAa;AAAA,MACvB,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV,CAAC;AACD,UAAM,cAAc,IAAI,MAAM,IAAI,MAAM;AACxC,UAAM,UAAU,IAAI,WAAW;AAE/B,QAAI,SAAmB,CAAC;AACxB,QAAI,SAAS;AAEb,UAAM,CAAC,gBAAgB,cAAc,IAAI,cAAc;AAAA,MACrD;AAAA,MACA;AAAA,IACF,CAAC;AAGD,QAAI,UAAU,WAAW,IAAI,UAAU,WAAW,MAAM,IAAI;AAC1D,gBAAU;AACV,gBAAU;AAEV,YAAM,gBAA0B;AAAA,QAC9B,EAAE,GAAG,SAAS,GAAG,aAAa,EAAE;AAAA,QAChC,EAAE,GAAG,SAAS,GAAG,aAAa,EAAE;AAAA,MAClC;AAEA,YAAM,kBAA4B;AAAA,QAChC,EAAE,GAAG,aAAa,GAAG,GAAG,QAAQ;AAAA,QAChC,EAAE,GAAG,aAAa,GAAG,GAAG,QAAQ;AAAA,MAClC;AAEA,UAAI,UAAU,WAAW,MAAM,SAAS;AACtC,iBAAS,gBAAgB,MAAM,gBAAgB;AAAA,MACjD,OAAO;AACL,iBAAS,gBAAgB,MAAM,kBAAkB;AAAA,MACnD;AAAA,IACF,OAAO;AAEL,YAAM,eAAyB,CAAC,EAAE,GAAG,aAAa,GAAG,GAAG,aAAa,EAAE,CAAC;AACxE,YAAM,eAAyB,CAAC,EAAE,GAAG,aAAa,GAAG,GAAG,aAAa,EAAE,CAAC;AAExE,UAAI,gBAAgB,KAAK;AACvB,iBAAS,UAAU,MAAM,UAAU,eAAe;AAAA,MACpD,OAAO;AACL,iBAAS,UAAU,MAAM,UAAU,eAAe;AAAA,MACpD;AAGA,YAAM,sBAAsB,gBAAgB,MAAM,MAAM;AACxD,YAAM,YAAY,UAAU,WAAW,MAAM,UAAU,mBAAmB;AAC1E,YAAM,qBACJ,aAAa,mBAAmB,IAAI,aAAa,mBAAmB;AACtE,YAAM,qBACJ,aAAa,mBAAmB,IAAI,aAAa,mBAAmB;AACtE,YAAM,mBACH,UAAU,WAAW,MAAM,MACxB,CAAC,aAAa,sBAAwB,aAAa,uBACtD,UAAU,WAAW,MAAM,MACxB,CAAC,aAAa,sBAAwB,aAAa;AAEzD,UAAI,kBAAkB;AACpB,iBAAS,gBAAgB,MAAM,eAAe;AAAA,MAChD;AAEA,YAAM,iBAAiB,EAAE,GAAG,aAAa,GAAG,GAAG,aAAa,EAAE;AAC9D,YAAM,iBAAiB,EAAE,GAAG,aAAa,GAAG,GAAG,aAAa,EAAE;AAC9D,YAAM,eAAe,KAAK;AAAA,QACxB,KAAK,IAAI,eAAe,IAAI,OAAO,CAAC,EAAE,CAAC;AAAA,QACvC,KAAK,IAAI,eAAe,IAAI,OAAO,CAAC,EAAE,CAAC;AAAA,MACzC;AACA,YAAM,eAAe,KAAK;AAAA,QACxB,KAAK,IAAI,eAAe,IAAI,OAAO,CAAC,EAAE,CAAC;AAAA,QACvC,KAAK,IAAI,eAAe,IAAI,OAAO,CAAC,EAAE,CAAC;AAAA,MACzC;AAEA,UAAI,gBAAgB,cAAc;AAChC,mBAAW,eAAe,IAAI,eAAe,KAAK;AAClD,kBAAU,OAAO,CAAC,EAAE;AAAA,MACtB,OAAO;AACL,kBAAU,OAAO,CAAC,EAAE;AACpB,mBAAW,eAAe,IAAI,eAAe,KAAK;AAAA,MACpD;AAAA,IACF;AAEA,UAAM,aAAa;AAAA,MACjB;AAAA,MACA,EAAE,GAAG,aAAa,GAAG,GAAG,aAAa,EAAE;AAAA,MACvC,GAAG;AAAA,MACH,EAAE,GAAG,aAAa,GAAG,GAAG,aAAa,EAAE;AAAA,MACvC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AA/GO,EAAAA,UAAS;AAiHhB,WAAS,QAAQ,GAAW,GAAW,GAAmB;AACxD,UAAM,WAAW,KAAK;AAAA,MACpBF,OAAM,YAAY,GAAG,CAAC,IAAI;AAAA,MAC1BA,OAAM,YAAY,GAAG,CAAC,IAAI;AAAA,MAC1B;AAAA,IACF;AACA,UAAM,EAAE,GAAG,EAAE,IAAI;AAGjB,QAAK,EAAE,MAAM,KAAK,MAAM,EAAE,KAAO,EAAE,MAAM,KAAK,MAAM,EAAE,GAAI;AACxD,aAAO,IAAI,CAAC,IAAI,CAAC;AAAA,IACnB;AAGA,QAAI,EAAE,MAAM,GAAG;AACb,YAAMG,QAAO,EAAE,IAAI,EAAE,IAAI,KAAK;AAC9B,YAAMC,QAAO,EAAE,IAAI,EAAE,IAAI,IAAI;AAC7B,aAAO,KAAK,IAAI,WAAWD,KAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,WAAWC,KAAI;AAAA,IAC7E;AAEA,UAAM,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI;AAC7B,UAAM,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK;AAC9B,WAAO,KAAK,CAAC,IAAI,IAAI,WAAW,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,WAAW,IAAI,IAAI,CAAC;AAAA,EAC7E;AAKO,WAAS,kBAAkB,QAA0B;AAC1D,UAAM,OAAO,OAAO,OAAe,CAAC,KAAK,GAAG,MAAM;AAChD,UAAI,UAAU;AAEd,UAAI,IAAI,KAAK,IAAI,OAAO,SAAS,GAAG;AAClC,kBAAU,QAAQ,OAAO,IAAI,CAAC,GAAG,GAAG,OAAO,IAAI,CAAC,CAAC;AAAA,MACnD,OAAO;AACL,kBAAU,GAAG,MAAM,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;AAAA,MAC/C;AAEA,aAAO;AAEP,aAAO;AAAA,IACT,GAAG,EAAE;AAEL,WAAO;AAAA,EACT;AAhBO,EAAAF,UAAS;AAiBT,WAAS,UAAU,QAA6B;AACrD,UAAM,QAAQ,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;AACnC,UAAM,QAAQ,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;AACnC,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK;AAC9B,UAAM,QAAQ,KAAK,IAAI,GAAG,KAAK;AAC/B,UAAM,MAAM,KAAK,IAAI,GAAG,KAAK;AAC7B,UAAM,SAAS,KAAK,IAAI,GAAG,KAAK;AAChC,WAAOD,WAAU;AAAA,MACf;AAAA,QACE,GAAG;AAAA,QACH,GAAG;AAAA,MACL;AAAA,MACA;AAAA,QACE,GAAG;AAAA,QACH,GAAG;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAjBO,EAAAC,UAAS;AAwBT,EAAMA,UAAA,6BAA6B,CAAC,QAAkB,QAAwB;AAEnF,QAAI,OAAO,WAAW,GAAG;AACvB,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,WAAW,GAAG;AACvB,aAAOF,OAAM,YAAY,OAAO,CAAC,GAAI,GAAG;AAAA,IAC1C;AAGA,UAAM,QAA4B,CAAC;AACnC,aAAS,IAAI,GAAG,IAAI,OAAO,SAAS,GAAG,KAAK;AAC1C,YAAM,KAAK,CAAC,OAAO,CAAC,GAAI,OAAO,IAAI,CAAC,CAAE,CAAC;AAAA,IACzC;AAGA,UAAM,YAAY,MAAM,IAAI,CAAC,SAAS;AACpC,YAAM,CAAC,IAAI,EAAE,IAAI;AACjB,aAAO,0BAA0B,KAAK,IAAI,EAAE;AAAA,IAC9C,CAAC;AAED,WAAO,KAAK,IAAI,GAAG,SAAS;AAAA,EAC9B;AAAA,GAzOe;;;ADhCV,IAAM,+BAAN,MAA6E;AAAA,EAKlF,YAAY,QAA4B;AACtC,SAAK,SAAS;AAAA,EAChB;AAAA,EAIA,IAAW,OAAe;AACxB,WAAO,KAAK,MAAM,QAAQ;AAAA,EAC5B;AAAA,EAEO,aAAa,KAAqB;AACvC,QAAI,CAAC,KAAK,MAAM;AACd,aAAO,OAAO;AAAA,IAChB;AACA,WAAO,SAAS,2BAA2B,KAAK,KAAK,QAAQ,GAAG;AAAA,EAClE;AAAA,EAEA,IAAW,SAAoB;AAC7B,QAAI,CAAC,KAAK,MAAM;AACd,aAAO,IAAIK,WAAU;AAAA,IACvB;AACA,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EAEO,OAAO,QAAwD;AACpE,UAAM,EAAE,SAAS,MAAM,IAAI;AAG3B,UAAM,eAAe;AAAA,MACnB,GAAG,QAAQ,aAAa,WAAW,IAAIC;AAAA,MACvC,GAAG,QAAQ,aAAa,WAAWA,gBAAe;AAAA,IACpD;AACA,UAAM,eAAe;AAAA,MACnB,GAAG,MAAM,aAAa,QAAQ,IAAI,CAACA;AAAA,MACnC,GAAG,MAAM,aAAa,QAAQ,CAACA,gBAAe;AAAA,IAChD;AAEA,UAAM,SAAS,SAAS,UAAU;AAAA,MAChC,QAAQ;AAAA,QACN,GAAG,QAAQ,IAAI,aAAa;AAAA,QAC5B,GAAG,QAAQ,IAAI,aAAa;AAAA,QAC5B,UAAU,QAAQ;AAAA,MACpB;AAAA,MACA,QAAQ;AAAA,QACN,GAAG,MAAM,IAAI,aAAa;AAAA,QAC1B,GAAG,MAAM,IAAI,aAAa;AAAA,QAC1B,UAAU,MAAM;AAAA,MAClB;AAAA,IACF,CAAC;AAED,UAAM,OAAO,SAAS,UAAU,MAAM;AAGtC,UAAM,iBAAiB,OAAO,IAAI,CAAC,OAAO;AAAA,MACxC,GAAG,EAAE,IAAI,KAAK,IAAI;AAAA,MAClB,GAAG,EAAE,IAAI,KAAK,IAAI;AAAA,IACpB,EAAE;AAEF,UAAM,OAAO,SAAS,kBAAkB,cAAc;AAEtD,SAAK,OAAO;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAvEa,6BACG,OAAOC,UAAS;;;AEnBhC,SAAiB,SAAAC,QAAO,aAAAC,kBAAiB;AACzC;AAAA,EACE,gBAAAC;AAAA,OAIK;;;ACKA,SAAS,mBAAmB,OAAe,WAAmB,SAAyB;AAC5F,QAAM,KAAK,QAAQ,IAAI,UAAU;AACjC,QAAM,KAAK,QAAQ,IAAI,UAAU;AAGjC,MAAI,OAAO,GAAG;AACZ,WAAO,EAAE,GAAG,UAAU,GAAG,GAAG,MAAM,EAAE;AAAA,EACtC;AAEA,MAAI,OAAO,GAAG;AACZ,WAAO,EAAE,GAAG,MAAM,GAAG,GAAG,UAAU,EAAE;AAAA,EACtC;AAEA,QAAM,MAAM,MAAM,IAAI,UAAU,KAAK,MAAM,MAAM,IAAI,UAAU,KAAK,OAAO,KAAK,KAAK,KAAK;AAC1F,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AAE3C,SAAO;AAAA,IACL,GAAG,UAAU,IAAI,WAAW;AAAA,IAC5B,GAAG,UAAU,IAAI,WAAW;AAAA,EAC9B;AACF;;;ADdO,IAAM,mCAAN,MAAiF;AAAA,EAKtF,YAAY,QAA4B;AACtC,SAAK,SAAS;AAAA,EAChB;AAAA,EAIA,IAAW,OAAe;AACxB,WAAO,KAAK,MAAM,QAAQ;AAAA,EAC5B;AAAA,EAEO,aAAa,KAAqB;AACvC,QAAI,CAAC,KAAK,MAAM;AACd,aAAO,OAAO;AAAA,IAChB;AACA,UAAM,CAAC,OAAO,GAAG,IAAI,KAAK,KAAK;AAC/B,WAAOC,OAAM,YAAY,KAAK,mBAAmB,KAAK,OAAO,GAAG,CAAC;AAAA,EACnE;AAAA,EAEA,IAAW,SAAoB;AAC7B,QAAI,CAAC,KAAK,MAAM;AACd,aAAO,IAAIC,WAAU;AAAA,IACvB;AACA,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EAEO,OAAO,QAAwD;AACpE,UAAM,EAAE,SAAS,MAAM,IAAI;AAG3B,UAAM,eAAe;AAAA,MACnB,GAAG,QAAQ,aAAa,WAAW,IAAIC;AAAA,MACvC,GAAG,QAAQ,aAAa,WAAWA,gBAAe;AAAA,IACpD;AACA,UAAM,eAAe;AAAA,MACnB,GAAG,MAAM,aAAa,QAAQ,IAAI,CAACA;AAAA,MACnC,GAAG,MAAM,aAAa,QAAQ,CAACA,gBAAe;AAAA,IAChD;AAEA,UAAM,SAAS;AAAA,MACb;AAAA,QACE,GAAG,QAAQ,IAAI,aAAa;AAAA,QAC5B,GAAG,QAAQ,IAAI,aAAa;AAAA,MAC9B;AAAA,MACA;AAAA,QACE,GAAG,MAAM,IAAI,aAAa;AAAA,QAC1B,GAAG,MAAM,IAAI,aAAa;AAAA,MAC5B;AAAA,IACF;AAEA,UAAM,OAAOD,WAAU,6BAA6B,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AAGxE,UAAM,iBAAiB,OAAO,IAAI,CAAC,OAAO;AAAA,MACxC,GAAG,EAAE,IAAI,KAAK,IAAI;AAAA,MAClB,GAAG,EAAE,IAAI,KAAK,IAAI;AAAA,IACpB,EAAE;AAGF,UAAM,OAAO,KAAK,eAAe,CAAC,EAAE,CAAC,IAAI,eAAe,CAAC,EAAE,CAAC,MAAM,eAAe,CAAC,EAAE,CAAC,IAAI,eAAe,CAAC,EAAE,CAAC;AAE5G,SAAK,OAAO;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAvEa,iCACG,OAAO;;;AElBvB,SAAiB,SAAAE,QAAO,aAAAC,kBAAiB;AACzC;AAAA,EACE,gBAAAC;AAAA,OAGK;AAWA,IAAM,8BAAN,MAA4E;AAAA,EAKjF,YAAY,QAA4B;AACtC,SAAK,SAAS;AAAA,EAChB;AAAA,EAIA,IAAW,OAAe;AACxB,WAAO,KAAK,MAAM,QAAQ;AAAA,EAC5B;AAAA,EAEO,aAAa,KAAqB;AACvC,QAAI,CAAC,KAAK,MAAM;AACd,aAAO,OAAO;AAAA,IAChB;AAEA,UAAM,EAAE,SAAS,OAAO,KAAK,IAAI,KAAK;AAGtC,QAAI,CAAC,KAAK,SAAS,IAAI,GAAG,IAAI,CAAC,GAAG;AAEhC,YAAM,KAAK,KAAK,IAAI,KAAK,IAAI,IAAI,GAAG,GAAG,IAAI,KAAK,KAAK,IAAI,KAAK,MAAM;AACpE,YAAM,KAAK,KAAK,IAAI,KAAK,IAAI,IAAI,GAAG,GAAG,IAAI,KAAK,KAAK,IAAI,KAAK,OAAO;AACrE,aAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAAA,IACpC;AAGA,UAAM,SAAS;AAAA,MACb,IAAI,QAAQ,IAAI,MAAM,KAAK;AAAA,MAC3B,IAAI,QAAQ,IAAI,MAAM,KAAK;AAAA,IAC7B;AACA,UAAM,SAASC,OAAM,YAAY,SAAS,MAAM;AAGhD,UAAM,mBAAmBA,OAAM,YAAY,KAAK,MAAM;AAGtD,WAAO,KAAK,IAAI,mBAAmB,MAAM;AAAA,EAC3C;AAAA,EAEA,IAAW,SAAoB;AAC7B,QAAI,CAAC,KAAK,MAAM;AACd,aAAO,IAAIC,WAAU;AAAA,IACvB;AACA,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EAEO,OAAO,QAAkD;AAC9D,UAAM,EAAE,SAAS,MAAM,IAAI;AAC3B,UAAM,EAAE,SAAS,IAAI,KAAK;AAE1B,UAAM,eAAe;AAAA,MACnB,GAAG,WAAW,IAAIC;AAAA,MAClB,GAAG,WAAWA,gBAAe;AAAA,IAC/B;AACA,UAAM,eAAe;AAAA,MACnB,GAAG,WAAW,IAAI,CAACA;AAAA,MACnB,GAAG,WAAW,CAACA,gBAAe;AAAA,IAChC;AAEA,UAAM,QAAQ;AAAA,MACZ,GAAG,QAAQ,IAAI,aAAa;AAAA,MAC5B,GAAG,QAAQ,IAAI,aAAa;AAAA,IAC9B;AACA,UAAM,MAAM;AAAA,MACV,GAAG,MAAM,IAAI,aAAa;AAAA,MAC1B,GAAG,MAAM,IAAI,aAAa;AAAA,IAC5B;AAGA,UAAM,OAAO,KAAK,iBAAiB,OAAO,GAAG;AAG7C,UAAM,OAAO,KAAK,WAAW,OAAO,KAAK,IAAI;AAE7C,SAAK,OAAO;AAAA,MACV,SAAS;AAAA,MACT,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,iBAAiB,OAAe,KAAwB;AAC9D,UAAM,KAAK,IAAI,IAAI,MAAM;AACzB,UAAM,KAAK,IAAI,IAAI,MAAM;AACzB,UAAM,SAAS,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,IAAI;AAE9C,UAAM,WAAW,MAAM,IAAI,IAAI,KAAK;AACpC,UAAM,WAAW,MAAM,IAAI,IAAI,KAAK;AAEpC,WAAO,IAAID,WAAU,UAAU,QAAQ,UAAU,QAAQ,SAAS,GAAG,SAAS,CAAC;AAAA,EACjF;AAAA,EAEQ,WAAW,OAAe,KAAa,MAAyB;AACtE,UAAM,KAAK,IAAI,IAAI,MAAM;AACzB,UAAM,KAAK,IAAI,IAAI,MAAM;AACzB,UAAM,WAAW,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAG5C,UAAM,WAAW;AAAA,MACf,GAAG,MAAM,IAAI,KAAK,IAAI;AAAA,MACtB,GAAG,MAAM,IAAI,KAAK,IAAI;AAAA,IACxB;AACA,UAAM,SAAS;AAAA,MACb,GAAG,IAAI,IAAI,KAAK,IAAI;AAAA,MACpB,GAAG,IAAI,IAAI,KAAK,IAAI;AAAA,IACtB;AAGA,WAAO,KAAK,SAAS,CAAC,IAAI,SAAS,CAAC,MAAM,WAAW,CAAC,IAAI,WAAW,CAAC,UAAU,OAAO,CAAC,IACtF,OAAO,CACT;AAAA,EACF;AACF;AAtHa,4BACG,OAAO;;;AZVhB,IAAM,wBAAwB,oBAAoB;AAAA,EACvD,WAAW;AAAA,EACX,QAAQ,CAAC,KAAoB,SAAiC;AAC5D,QAAI,WAAW,cAAc,oBAAoB;AAAA,MAC/C,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA,EACA,SAAS,CAAC,KAAoB,SAAiC;AAC7D,UAAM,eAAe,IAAI,UAAU,IAAIE,qBAAoB;AAC3D,iBACG,qBAAqB,8BAA8B,EACnD,qBAAqB,4BAA4B;AAEpD,QAAI,KAAK,eAAe;AACtB,WAAK,cAAc,QAAQ,CAAC,iBAAiB;AAC3C,qBAAa,qBAAqB,YAAY;AAAA,MAChD,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,iBAAiB;AACxB,mBAAa,eAAe,KAAK,eAAe;AAAA,IAClD;AAAA,EACF;AACF,CAAC;","names":["React","React","WorkflowLinesManager","ReactDOM","React","useState","WorkflowHoverService","WorkflowLineRenderData","React","styled","React","React","React","useState","WorkflowLineRenderData","React","ReactDOM","WorkflowHoverService","Rectangle","POINT_RADIUS","LineType","Point","Rectangle","FoldLine","xDir","yDir","Rectangle","POINT_RADIUS","LineType","Point","Rectangle","POINT_RADIUS","Point","Rectangle","POINT_RADIUS","Point","Rectangle","POINT_RADIUS","Point","Rectangle","POINT_RADIUS","WorkflowLinesManager"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/workflow-port-render/index.tsx","../../src/constants/points.ts","../../src/components/workflow-port-render/style.ts","../../src/components/workflow-port-render/cross-hair.tsx","../../src/constants/lines.ts","../../src/create-free-lines-plugin.ts","../../src/layer/workflow-lines-layer.tsx","../../src/components/workflow-line-render/index.tsx","../../src/components/workflow-line-render/line-svg.tsx","../../src/components/workflow-line-render/index.style.ts","../../src/components/workflow-line-render/arrow.tsx","../../src/contributions/bezier/index.ts","../../src/contributions/utils.ts","../../src/contributions/bezier/bezier-controls.ts","../../src/contributions/fold/index.ts","../../src/contributions/fold/fold-line.ts","../../src/contributions/straight/index.ts","../../src/contributions/straight/point-on-line.ts"],"sourcesContent":["/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport ReactDOM from 'react-dom';\nimport React, { useEffect, useState } from 'react';\n\nimport classNames from 'clsx';\nimport {\n WorkflowHoverService,\n type WorkflowPortEntity,\n usePlaygroundReadonlyState,\n WorkflowLinesManager,\n} from '@flowgram.ai/free-layout-core';\nimport { MouseTouchEvent, useService } from '@flowgram.ai/core';\n\nimport { PORT_BG_CLASS_NAME } from '../../constants/points';\nimport { WorkflowPointStyle } from './style';\nimport CrossHair from './cross-hair';\n\nexport interface WorkflowPortRenderProps {\n entity: WorkflowPortEntity;\n className?: string;\n style?: React.CSSProperties;\n onClick?: (e: React.MouseEvent<HTMLDivElement>, port: WorkflowPortEntity) => void;\n /** 激活状态颜色 (linked/hovered) */\n primaryColor?: string;\n /** 默认状态颜色 */\n secondaryColor?: string;\n /** 错误状态颜色 */\n errorColor?: string;\n /** 背景颜色 */\n backgroundColor?: string;\n}\n\nexport const WorkflowPortRender: React.FC<WorkflowPortRenderProps> =\n // eslint-disable-next-line react/display-name\n React.memo<WorkflowPortRenderProps>((props: WorkflowPortRenderProps) => {\n const hoverService = useService<WorkflowHoverService>(WorkflowHoverService);\n const linesManager = useService<WorkflowLinesManager>(WorkflowLinesManager);\n const { entity, onClick } = props;\n const { portType, relativePosition, disabled } = entity;\n const [targetElement, setTargetElement] = useState(entity.targetElement);\n const [posX, updatePosX] = useState(relativePosition.x);\n const [posY, updatePosY] = useState(relativePosition.y);\n const [hovered, setHovered] = useState(false);\n const [linked, setLinked] = useState(Boolean(entity?.lines?.length));\n const [hasError, setHasError] = useState(props.entity.hasError);\n const readonly = usePlaygroundReadonlyState();\n\n useEffect(() => {\n // useEffect 时序问题可能导致 port.hasError 非最新,需重新触发一次 validate\n entity.validate();\n setHasError(entity.hasError);\n const dispose = entity.onEntityChange(() => {\n // 如果有挂载的节点,不需要更新位置信息\n if (entity.targetElement) {\n if (entity.targetElement !== targetElement) {\n setTargetElement(entity.targetElement);\n }\n return;\n }\n const newPos = entity.relativePosition;\n // 加上 round 避免点位抖动\n updatePosX(Math.round(newPos.x));\n updatePosY(Math.round(newPos.y));\n });\n const dispose2 = hoverService.onHoveredChange((id) => {\n setHovered(hoverService.isHovered(entity.id));\n });\n const dispose3 = entity.onErrorChanged(() => {\n setHasError(entity.hasError);\n });\n const dispose4 = linesManager.onAvailableLinesChange(() => {\n setTimeout(() => {\n if (linesManager.disposed || entity.disposed) return;\n setLinked(Boolean(entity.lines.length));\n }, 0);\n });\n return () => {\n dispose.dispose();\n dispose2.dispose();\n dispose3.dispose();\n dispose4.dispose();\n };\n }, [hoverService, entity, targetElement]);\n\n // 监听变化\n const className = classNames('workflow-port-render', props.className || '', {\n hovered: !readonly && hovered && !disabled && portType !== 'input',\n // 有线条链接的时候深蓝色小圆点\n linked,\n });\n\n // 构建 CSS 自定义属性用于颜色覆盖\n const colorStyles: Record<string, string> = {};\n if (props.primaryColor) {\n colorStyles['--g-workflow-port-color-primary'] = props.primaryColor;\n }\n if (props.secondaryColor) {\n colorStyles['--g-workflow-port-color-secondary'] = props.secondaryColor;\n }\n if (props.errorColor) {\n colorStyles['--g-workflow-port-color-error'] = props.errorColor;\n }\n if (props.backgroundColor) {\n colorStyles['--g-workflow-port-color-background'] = props.backgroundColor;\n }\n\n const combinedStyle = targetElement\n ? { ...props.style, ...colorStyles }\n : { ...props.style, ...colorStyles, left: posX, top: posY };\n\n const content = (\n <WorkflowPointStyle\n className={className}\n style={combinedStyle}\n onClick={(e) => onClick?.(e, entity)}\n onTouchStart={(e) => {\n if (!onClick) {\n return;\n }\n MouseTouchEvent.onTouched(e, (mouseEvent) => {\n onClick(mouseEvent as unknown as React.MouseEvent<HTMLDivElement>, entity);\n });\n }}\n data-port-entity-id={entity.id}\n data-port-entity-type={entity.portType}\n data-testid=\"sdk.workflow.canvas.node.port\"\n >\n <div className={classNames('bg-circle', 'workflow-bg-circle')}></div>\n <div\n className={classNames({\n bg: true,\n [PORT_BG_CLASS_NAME]: true,\n 'workflow-point-bg': true,\n hasError,\n })}\n >\n <CrossHair />\n </div>\n <div className=\"focus-circle\" />\n </WorkflowPointStyle>\n );\n if (targetElement) {\n return ReactDOM.createPortal(content, targetElement);\n }\n return content;\n });\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\n// 连接点半径\n\nexport const STROKE_WIDTH_SLECTED = 3;\n\nexport const STROKE_WIDTH = 2;\n\nexport const PORT_BG_CLASS_NAME = 'workflow-port-bg';\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport styled from 'styled-components';\n\nexport const WorkflowPointStyle = styled.div`\n width: 20px;\n height: 20px;\n border-radius: 50%;\n margin-top: -10px;\n margin-left: -10px;\n left: 50%;\n top: 50%;\n position: absolute;\n // 非 hover 状态下的样式\n border: none;\n\n & > .symbol {\n opacity: 0;\n }\n\n .bg-circle {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n border-radius: 50%;\n width: 20px;\n height: 20px;\n background-color: var(--g-workflow-port-color-background, #fff);\n transform: scale(0.5);\n transition: all 0.2s linear 0s;\n }\n\n .bg {\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n background: var(--g-workflow-port-color-secondary, #9197f1);\n transform: scale(0.4, 0.4);\n transition: all 0.2s linear 0s;\n\n &.hasError {\n background: var(--g-workflow-port-color-error, red);\n }\n\n .symbol {\n position: absolute;\n width: 14px;\n height: 14px;\n opacity: 0;\n pointer-events: none;\n color: var(--g-workflow-port-color-background, #fff);\n transition: opacity 0.2s linear 0s;\n\n & > svg {\n width: 14px;\n height: 14px;\n }\n }\n\n .focus-circle {\n position: absolute;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 8px;\n height: 8px;\n opacity: 0;\n background: var(--g-workflow-port-color-secondary, #9197f1);\n border-radius: 50%;\n transition: opacity 0.2s linear 0s;\n }\n }\n\n &.linked .bg:not(.hasError) {\n background: var(--g-workflow-port-color-primary, #4d53e8);\n }\n\n &.hovered .bg:not(.hasError) {\n border: none;\n cursor: crosshair;\n transform: scale(1, 1);\n background: var(--g-workflow-port-color-primary, #4d53e8);\n\n & > .symbol {\n opacity: 1;\n }\n }\n\n .cross-hair {\n position: relative;\n left: 2px;\n top: 2px;\n\n &::after,\n &::before {\n content: '';\n background: var(--g-workflow-port-color-background, #fff);\n border-radius: 2px;\n position: absolute;\n }\n\n &::after {\n left: 4px;\n width: 2px;\n height: 6px;\n box-shadow: 0 4px var(--g-workflow-port-color-background, #fff);\n }\n\n &::before {\n top: 4px;\n width: 6px;\n height: 2px;\n box-shadow: 4px 0 var(--g-workflow-port-color-background, #fff);\n }\n`;\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport React from 'react';\n\n// demo 环境自绘 cross-hair,正式环境使用 IconAdd\nexport default function CrossHair(): JSX.Element {\n return (\n <div className=\"symbol\">\n <div className=\"cross-hair\" />\n </div>\n );\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\n// 箭头宽度\nexport const LINE_OFFSET = 6;\n\nexport const LINE_PADDING = 12;\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { WorkflowLinesManager } from '@flowgram.ai/free-layout-core';\nimport { definePluginCreator, PluginContext } from '@flowgram.ai/core';\n\nimport { FreeLinesPluginOptions } from './type';\nimport { WorkflowLinesLayer } from './layer';\nimport {\n WorkflowBezierLineContribution,\n WorkflowFoldLineContribution,\n WorkflowStraightLineContribution,\n} from './contributions';\n\nexport const createFreeLinesPlugin = definePluginCreator({\n singleton: true,\n onInit: (ctx: PluginContext, opts: FreeLinesPluginOptions) => {\n ctx.playground.registerLayer(WorkflowLinesLayer, {\n ...opts,\n });\n },\n onReady: (ctx: PluginContext, opts: FreeLinesPluginOptions) => {\n const linesManager = ctx.container.get(WorkflowLinesManager);\n linesManager\n .registerContribution(WorkflowBezierLineContribution)\n .registerContribution(WorkflowFoldLineContribution)\n .registerContribution(WorkflowStraightLineContribution);\n\n if (opts.contributions) {\n opts.contributions.forEach((contribution) => {\n linesManager.registerContribution(contribution);\n });\n }\n\n if (opts.defaultLineType) {\n linesManager.switchLineType(opts.defaultLineType);\n }\n },\n});\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport ReactDOM from 'react-dom';\nimport React, { ReactNode, useLayoutEffect, useState } from 'react';\n\nimport { inject, injectable } from 'inversify';\nimport { domUtils } from '@flowgram.ai/utils';\nimport { FlowRendererRegistry } from '@flowgram.ai/renderer';\nimport { StackingContextManager } from '@flowgram.ai/free-stack-plugin';\nimport {\n nanoid,\n WorkflowDocument,\n WorkflowHoverService,\n WorkflowLineEntity,\n WorkflowLineRenderData,\n WorkflowNodeEntity,\n WorkflowPortEntity,\n WorkflowSelectService,\n} from '@flowgram.ai/free-layout-core';\nimport { Layer, observeEntities, observeEntityDatas, TransformData } from '@flowgram.ai/core';\n\nimport { LineRenderProps, LinesLayerOptions } from '../type';\nimport { WorkflowLineRender } from '../components';\n\n@injectable()\nexport class WorkflowLinesLayer extends Layer<LinesLayerOptions> {\n static type = 'WorkflowLinesLayer';\n\n @inject(WorkflowHoverService) hoverService: WorkflowHoverService;\n\n @inject(WorkflowSelectService) selectService: WorkflowSelectService;\n\n @inject(StackingContextManager) stackContext: StackingContextManager;\n\n @inject(FlowRendererRegistry) rendererRegistry: FlowRendererRegistry;\n\n @observeEntities(WorkflowLineEntity) readonly lines: WorkflowLineEntity[];\n\n @observeEntities(WorkflowPortEntity) readonly ports: WorkflowPortEntity[];\n\n @observeEntityDatas(WorkflowNodeEntity, TransformData)\n readonly trans: TransformData[];\n\n @inject(WorkflowDocument) protected workflowDocument: WorkflowDocument;\n\n private layerID = nanoid();\n\n private mountedLines: Map<\n string,\n {\n line: WorkflowLineEntity;\n portal: ReactNode;\n version: string;\n }\n > = new Map();\n\n private _version = 0;\n\n /**\n * 节点线条\n */\n public node = domUtils.createDivWithClass('gedit-playground-layer gedit-flow-lines-layer');\n\n public onZoom(scale: number): void {\n this.node.style.transform = `scale(${scale})`;\n }\n\n public onReady() {\n this.pipelineNode.appendChild(this.node);\n this.toDispose.pushAll([\n this.selectService.onSelectionChanged(() => this.render()),\n this.hoverService.onHoveredChange(() => this.render()),\n this.workflowDocument.linesManager.onForceUpdate(() => {\n this.mountedLines.clear();\n this.bumpVersion();\n this.render();\n }),\n ]);\n }\n\n public dispose() {\n this.mountedLines.clear();\n }\n\n public render(): JSX.Element {\n const [, forceUpdate] = useState({});\n\n useLayoutEffect(() => {\n const updateLines = (): void => {\n let needsUpdate = false;\n\n // 批量处理所有线条的更新\n this.lines.forEach((line) => {\n const renderData = line.getData(WorkflowLineRenderData);\n const oldVersion = renderData.renderVersion;\n renderData.update();\n // 如果有任何一条线发生变化,标记需要更新\n if (renderData.renderVersion !== oldVersion) {\n needsUpdate = true;\n }\n });\n\n // 只在确实需要更新时触发重渲染\n if (needsUpdate) {\n forceUpdate({});\n }\n };\n\n const rafId = requestAnimationFrame(updateLines);\n return () => cancelAnimationFrame(rafId);\n }, [this.lines]); // 依赖项包含 lines\n\n const lines = this.lines.map((line) => this.renderLine(line));\n return <>{lines}</>;\n }\n\n // 用来绕过 memo\n private bumpVersion() {\n this._version = this._version + 1;\n if (this._version === Number.MAX_SAFE_INTEGER) {\n this._version = 0;\n }\n }\n\n private lineProps(line: WorkflowLineEntity): LineRenderProps {\n const { lineType } = this.workflowDocument.linesManager;\n const selected = this.selectService.isSelected(line.id);\n const hovered = this.hoverService.isHovered(line.id);\n const version = this.lineVersion(line);\n\n return {\n key: line.id,\n color: line.color,\n selected,\n hovered,\n line,\n lineType,\n version,\n strokePrefix: this.layerID,\n rendererRegistry: this.rendererRegistry,\n };\n }\n\n private lineVersion(line: WorkflowLineEntity): string {\n const renderData = line.getData(WorkflowLineRenderData);\n const { renderVersion } = renderData;\n const selected = this.selectService.isSelected(line.id);\n const hovered = this.hoverService.isHovered(line.id);\n const { version: lineVersion, color } = line;\n\n const version = `v:${this._version},lv:${lineVersion},rv:${renderVersion},c:${color},s:${\n selected ? 'T' : 'F'\n },h:${hovered ? 'T' : 'F'}`;\n\n return version;\n }\n\n private lineComponent(props: LineRenderProps): ReactNode {\n const RenderInsideLine = this.options.renderInsideLine ?? (() => <></>);\n return (\n <WorkflowLineRender {...props}>\n <RenderInsideLine {...props} />\n </WorkflowLineRender>\n );\n }\n\n private renderLine(line: WorkflowLineEntity): ReactNode {\n const lineProps = this.lineProps(line);\n const cache = this.mountedLines.get(line.id);\n const isCached = cache !== undefined;\n const { portal: cachedPortal, version: cachedVersion } = cache ?? {};\n if (isCached && cachedVersion === lineProps.version) {\n // 如果已有缓存且版本相同,则直接返回缓存的 portal\n return cachedPortal;\n }\n if (!isCached) {\n // 如果缓存不存在,则将 line 挂载到 renderElement 上\n this.renderElement.appendChild(line.node);\n line.onDispose(() => {\n this.mountedLines.delete(line.id);\n line.node.remove();\n });\n }\n // 刷新缓存\n const portal = ReactDOM.createPortal(this.lineComponent(lineProps), line.node);\n this.mountedLines.set(line.id, { line, portal, version: lineProps.version });\n return portal;\n }\n\n private get renderElement(): HTMLElement {\n return this.stackContext.node;\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { memo } from 'react';\n\nimport { LineSVG } from './line-svg';\n\nexport const WorkflowLineRender = memo(\n LineSVG,\n (prevProps, nextProps) => prevProps.version === nextProps.version\n);\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport React from 'react';\n\nimport clsx from 'clsx';\nimport { type IPoint } from '@flowgram.ai/utils';\nimport { POINT_RADIUS } from '@flowgram.ai/free-layout-core';\nimport { WorkflowLineRenderData } from '@flowgram.ai/free-layout-core';\n\nimport { type ArrowRendererComponent } from '../../types/arrow-renderer';\nimport { LineRenderProps } from '../../type';\nimport { STROKE_WIDTH_SLECTED, STROKE_WIDTH } from '../../constants/points';\nimport { LINE_OFFSET } from '../../constants/lines';\nimport { LineStyle } from './index.style';\nimport { ArrowRenderer } from './arrow';\n\nconst PADDING = 12;\n\nexport const LineSVG = (props: LineRenderProps) => {\n const { line, color, selected, children, strokePrefix, rendererRegistry } = props;\n const { position, reverse, hideArrow, vertical } = line;\n\n const renderData = line.getData(WorkflowLineRenderData);\n const { bounds, path: bezierPath } = renderData;\n\n // 相对位置转换函数\n const toRelative = (p: IPoint): IPoint => ({\n x: p.x - bounds.x + PADDING,\n y: p.y - bounds.y + PADDING,\n });\n\n const fromPos = toRelative(position.from);\n const toPos = toRelative(position.to);\n\n // 箭头位置计算\n const arrowToPos: IPoint =\n position.to.location === 'top'\n ? { x: toPos.x, y: toPos.y - POINT_RADIUS }\n : { x: toPos.x - POINT_RADIUS, y: toPos.y };\n const arrowFromPos: IPoint =\n position.from.location === 'bottom'\n ? { x: fromPos.x, y: fromPos.y + POINT_RADIUS + LINE_OFFSET }\n : { x: fromPos.x + POINT_RADIUS + LINE_OFFSET, y: fromPos.y };\n\n const strokeWidth = selected\n ? line.uiState.strokeWidthSelected ?? STROKE_WIDTH_SLECTED\n : line.uiState.strokeWidth ?? STROKE_WIDTH;\n\n const strokeID = strokePrefix ? `${strokePrefix}-${line.id}` : line.id;\n\n // 获取自定义箭头渲染器,如果没有则使用默认的\n const CustomArrowRenderer = rendererRegistry?.tryToGetRendererComponent('arrow-renderer')\n ?.renderer as ArrowRendererComponent;\n const ArrowComponent = CustomArrowRenderer || ArrowRenderer;\n\n const path = (\n <path\n d={bezierPath}\n fill=\"none\"\n stroke={`url(#${strokeID})`}\n strokeWidth={strokeWidth}\n className={line.processing || line.flowing ? 'dashed-line flowing-line' : ''}\n />\n );\n\n return (\n <LineStyle\n className={clsx('gedit-flow-activity-edge', line.className)}\n style={{\n ...line.uiState.style,\n left: bounds.x - PADDING,\n top: bounds.y - PADDING,\n position: 'absolute',\n }}\n >\n {children}\n <svg width={bounds.width + PADDING * 2} height={bounds.height + PADDING * 2}>\n <defs>\n <linearGradient\n x1={vertical ? '100%' : '0%'}\n y1={vertical ? '0%' : '100%'}\n x2=\"100%\"\n y2=\"100%\"\n id={strokeID}\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop stopColor={color} offset=\"0%\" />\n <stop stopColor={color} offset=\"100%\" />\n </linearGradient>\n </defs>\n <g>\n {path}\n <ArrowComponent\n id={strokeID}\n reverseArrow={reverse}\n pos={reverse ? arrowFromPos : arrowToPos}\n strokeWidth={strokeWidth}\n vertical={vertical}\n hide={hideArrow}\n line={line}\n />\n </g>\n </svg>\n </LineStyle>\n );\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport styled from 'styled-components';\n\n// 添加一个固定类名,用于选中该节点\n\nexport const LineStyle = styled.div`\n position: absolute;\n\n @keyframes flowingDash {\n to {\n stroke-dashoffset: -13;\n }\n }\n\n .dashed-line {\n stroke-dasharray: 8, 5;\n }\n\n .flowing-line {\n animation: flowingDash 0.5s linear infinite;\n }\n`;\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport React from 'react';\n\nimport { type ArrowRendererProps } from '../../types/arrow-renderer';\nimport { LINE_OFFSET } from '../../constants/lines';\n\nexport function ArrowRenderer({\n id,\n pos,\n reverseArrow,\n strokeWidth,\n vertical,\n hide,\n}: ArrowRendererProps) {\n if (hide) {\n return null;\n }\n const arrowPath = vertical\n ? reverseArrow\n ? `M ${pos.x - LINE_OFFSET},${pos.y} L ${pos.x},${pos.y - LINE_OFFSET} L ${\n pos.x + LINE_OFFSET\n },${pos.y}`\n : `M ${pos.x - LINE_OFFSET},${pos.y - LINE_OFFSET} L ${pos.x},${pos.y} L ${\n pos.x + LINE_OFFSET\n },${pos.y - LINE_OFFSET}`\n : reverseArrow\n ? `M ${pos.x},${pos.y + LINE_OFFSET} L ${pos.x - LINE_OFFSET},${pos.y} L ${pos.x},${\n pos.y - LINE_OFFSET\n }`\n : `M ${pos.x - LINE_OFFSET},${pos.y - LINE_OFFSET} L ${pos.x},${pos.y} L ${\n pos.x - LINE_OFFSET\n },${pos.y + LINE_OFFSET}`;\n\n return (\n <path\n d={arrowPath}\n strokeLinecap=\"round\"\n stroke={`url(#${id})`}\n fill=\"none\"\n strokeWidth={strokeWidth}\n />\n );\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Bezier } from 'bezier-js';\nimport { IPoint, Point, Rectangle } from '@flowgram.ai/utils';\nimport {\n WorkflowLineEntity,\n WorkflowLineRenderContribution,\n LinePoint,\n LineCenterPoint,\n} from '@flowgram.ai/free-layout-core';\nimport { LineType } from '@flowgram.ai/free-layout-core';\n\nimport { toRelative } from '../utils';\nimport { getBezierControlPoints } from './bezier-controls';\n\nexport interface BezierData {\n fromPos: IPoint;\n toPos: IPoint;\n bbox: Rectangle; // 外围矩形\n controls: IPoint[]; // 控制点\n bezier: Bezier;\n path: string;\n center: LineCenterPoint;\n}\n\nexport class WorkflowBezierLineContribution implements WorkflowLineRenderContribution {\n public static type = LineType.BEZIER;\n\n public entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n this.entity = entity;\n }\n\n private data?: BezierData;\n\n public get path(): string {\n return this.data?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n if (!this.data) {\n return Number.MAX_SAFE_INTEGER;\n }\n return Point.getDistance(pos, this.data.bezier.project(pos));\n }\n\n public get bounds(): Rectangle {\n if (!this.data) {\n return Rectangle.EMPTY;\n }\n return this.data.bbox;\n }\n\n get center() {\n return this.data?.center;\n }\n\n public update(params: { fromPos: LinePoint; toPos: LinePoint }): void {\n this.data = this.calcBezier(params.fromPos, params.toPos);\n }\n\n private calcBezier(fromPos: LinePoint, toPos: LinePoint): BezierData {\n const { controls, center } = getBezierControlPoints(\n fromPos,\n toPos,\n this.entity.uiState.curvature\n );\n const bezier = new Bezier([fromPos, ...controls, toPos]);\n const bbox = bezier.bbox();\n const bboxBounds = new Rectangle(\n bbox.x.min,\n bbox.y.min,\n bbox.x.max - bbox.x.min,\n bbox.y.max - bbox.y.min\n );\n const centerPoint = toRelative(center, bboxBounds);\n\n const path = this.getPath({ bbox: bboxBounds, fromPos, toPos, controls });\n\n this.data = {\n fromPos,\n toPos,\n bezier,\n bbox: bboxBounds,\n controls,\n path,\n center: {\n ...center,\n labelX: centerPoint.x,\n labelY: centerPoint.y,\n },\n };\n return this.data;\n }\n\n private getPath(params: {\n bbox: Rectangle;\n fromPos: LinePoint;\n toPos: LinePoint;\n controls: [IPoint, IPoint];\n }): string {\n const { bbox } = params;\n // 相对位置转换函数\n const fromPos = toRelative(params.fromPos, bbox);\n const toPos = toRelative(params.toPos, bbox);\n\n const controls = params.controls.map((c) => toRelative(c, bbox));\n const shrink = this.entity.uiState.shrink;\n\n const renderFromPos: IPoint =\n params.fromPos.location === 'bottom'\n ? { x: fromPos.x, y: fromPos.y + shrink }\n : { x: fromPos.x + shrink, y: fromPos.y };\n\n const renderToPos: IPoint =\n params.toPos.location === 'top'\n ? { x: toPos.x, y: toPos.y - shrink }\n : { x: toPos.x - shrink, y: toPos.y };\n\n const controlPoints = controls.map((s) => `${s.x} ${s.y}`).join(',');\n return `M${renderFromPos.x} ${renderFromPos.y} C ${controlPoints}, ${renderToPos.x} ${renderToPos.y}`;\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 { LINE_PADDING } from '../constants/lines';\n\nexport function toRelative(p: IPoint, bbox: Rectangle): IPoint {\n return {\n x: p.x - bbox.x + LINE_PADDING,\n y: p.y - bbox.y + LINE_PADDING,\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 { LinePoint, LinePointLocation } from '@flowgram.ai/free-layout-core';\n\n/**\n * Fork from: https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/edges/bezier-edge.ts\n * MIT License\n * Copyright (c) 2019-2024 webkid GmbH\n */\nexport function getBezierEdgeCenter(\n fromPos: IPoint,\n toPos: IPoint,\n fromControl: IPoint,\n toControl: IPoint\n): IPoint {\n /*\n * cubic bezier t=0.5 mid point, not the actual mid point, but easy to calculate\n * https://stackoverflow.com/questions/67516101/how-to-find-distance-mid-point-of-bezier-curve\n */\n const x = fromPos.x * 0.125 + fromControl.x * 0.375 + toControl.x * 0.375 + toPos.x * 0.125;\n const y = fromPos.y * 0.125 + fromControl.y * 0.375 + toControl.y * 0.375 + toPos.y * 0.125;\n return {\n x,\n y,\n };\n}\n\nfunction getControlOffset(distance: number, curvature: number): number {\n if (distance >= 0) {\n return 0.5 * distance;\n }\n\n return curvature * 25 * Math.sqrt(-distance);\n}\n\nfunction getControlWithCurvature({\n location,\n x1,\n y1,\n x2,\n y2,\n curvature,\n}: {\n location: LinePointLocation;\n curvature: number;\n x1: number;\n x2: number;\n y1: number;\n y2: number;\n}): IPoint {\n switch (location) {\n case 'left':\n return {\n x: x1 - getControlOffset(x1 - x2, curvature),\n y: y1,\n };\n case 'right':\n return {\n x: x1 + getControlOffset(x2 - x1, curvature),\n y: y1,\n };\n case 'top':\n return {\n x: x1,\n y: y1 - getControlOffset(y1 - y2, curvature),\n };\n case 'bottom':\n return {\n x: x1,\n y: y1 + getControlOffset(y2 - y1, curvature),\n };\n }\n}\n\nexport function getBezierControlPoints(\n fromPos: LinePoint,\n toPos: LinePoint,\n curvature = 0.25\n): { controls: [IPoint, IPoint]; center: IPoint } {\n const fromControl = getControlWithCurvature({\n location: fromPos.location,\n x1: fromPos.x,\n y1: fromPos.y,\n x2: toPos.x,\n y2: toPos.y,\n curvature,\n });\n const toControl = getControlWithCurvature({\n location: toPos.location,\n x1: toPos.x,\n y1: toPos.y,\n x2: fromPos.x,\n y2: fromPos.y,\n curvature,\n });\n const center = getBezierEdgeCenter(fromPos, toPos, fromControl, toControl);\n return {\n controls: [fromControl, toControl],\n center,\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 {\n WorkflowLineEntity,\n WorkflowLineRenderContribution,\n LinePoint,\n LineCenterPoint,\n} from '@flowgram.ai/free-layout-core';\nimport { LineType } from '@flowgram.ai/free-layout-core';\n\nimport { toRelative } from '../utils';\nimport { FoldLine } from './fold-line';\n\nexport interface FoldData {\n points: IPoint[];\n path: string;\n bbox: Rectangle;\n center: LineCenterPoint;\n}\n\nexport class WorkflowFoldLineContribution implements WorkflowLineRenderContribution {\n public static type = LineType.LINE_CHART;\n\n public entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n this.entity = entity;\n }\n\n private data?: FoldData;\n\n public get path(): string {\n return this.data?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n if (!this.data) {\n return Number.MAX_SAFE_INTEGER;\n }\n return FoldLine.getFoldLineToPointDistance(this.data.points, pos);\n }\n\n public get bounds(): Rectangle {\n if (!this.data) {\n return new Rectangle();\n }\n return this.data.bbox;\n }\n\n get center() {\n return this.data?.center;\n }\n\n public update(params: { fromPos: LinePoint; toPos: LinePoint }): void {\n const { fromPos, toPos } = params;\n const shrink = this.entity.uiState.shrink;\n\n // 根据方向预先计算源点和目标点的偏移\n const sourceOffset = {\n x: fromPos.location === 'bottom' ? 0 : shrink,\n y: fromPos.location === 'bottom' ? shrink : 0,\n };\n const targetOffset = {\n x: toPos.location === 'top' ? 0 : -shrink,\n y: toPos.location === 'top' ? -shrink : 0,\n };\n\n const { points, center } = FoldLine.getPoints({\n source: {\n x: fromPos.x + sourceOffset.x,\n y: fromPos.y + sourceOffset.y,\n location: fromPos.location,\n },\n target: {\n x: toPos.x + targetOffset.x,\n y: toPos.y + targetOffset.y,\n location: toPos.location,\n },\n });\n\n const bbox = FoldLine.getBounds(points);\n\n // 调整所有点到 SVG 视口坐标系\n const adjustedPoints = points.map((p) => toRelative(p, bbox));\n\n const path = FoldLine.getSmoothStepPath(adjustedPoints);\n\n const relativeCenter = toRelative(center, bbox);\n this.data = {\n points,\n path,\n bbox,\n center: {\n x: center.x,\n y: center.y,\n labelX: relativeCenter.x,\n labelY: relativeCenter.y,\n },\n };\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { type IPoint, Point, Rectangle } from '@flowgram.ai/utils';\nimport { LinePoint } from '@flowgram.ai/free-layout-core';\n\n/**\n * 计算点到线段的距离\n * @param point 待测试点\n * @param segStart 线段起点\n * @param segEnd 线段终点\n */\nconst getPointToSegmentDistance = (point: IPoint, segStart: IPoint, segEnd: IPoint): number => {\n const { x: px, y: py } = point;\n const { x: x1, y: y1 } = segStart;\n const { x: x2, y: y2 } = segEnd;\n\n const A = px - x1;\n const B = py - y1;\n const C = x2 - x1;\n const D = y2 - y1;\n\n const dot = A * C + B * D;\n const lenSq = C * C + D * D;\n\n // 参数方程中的t参数\n const param = lenSq === 0 ? -1 : dot / lenSq;\n\n let xx: number;\n let yy: number;\n\n if (param < 0) {\n xx = x1;\n yy = y1;\n } else if (param > 1) {\n xx = x2;\n yy = y2;\n } else {\n xx = x1 + param * C;\n yy = y1 + param * D;\n }\n\n const dx = px - xx;\n const dy = py - yy;\n\n return Math.sqrt(dx * dx + dy * dy);\n};\n\n/**\n * Fork from: https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/edges/smoothstep-edge.ts\n * MIT License\n * Copyright (c) 2019-2024 webkid GmbH\n */\nexport namespace FoldLine {\n const EDGE_RADIUS = 5;\n const OFFSET = 20;\n\n function getEdgeCenter({ source, target }: { source: IPoint; target: IPoint }): [number, number] {\n const xOffset = Math.abs(target.x - source.x) / 2;\n const centerX = target.x < source.x ? target.x + xOffset : target.x - xOffset;\n\n const yOffset = Math.abs(target.y - source.y) / 2;\n const centerY = target.y < source.y ? target.y + yOffset : target.y - yOffset;\n\n return [centerX, centerY];\n }\n\n const getDirection = ({ source, target }: { source: LinePoint; target: LinePoint }): IPoint => {\n if (source.location === 'left' || source.location === 'right') {\n return source.x < target.x ? { x: 1, y: 0 } : { x: -1, y: 0 };\n }\n return source.y < target.y ? { x: 0, y: 1 } : { x: 0, y: -1 };\n };\n\n const handleDirections = {\n left: { x: -1, y: 0 },\n right: { x: 1, y: 0 },\n top: { x: 0, y: -1 },\n bottom: { x: 0, y: 1 },\n };\n // eslint-disable-next-line complexity\n export function getPoints({ source, target }: { source: LinePoint; target: LinePoint }): {\n points: IPoint[];\n center: IPoint;\n } {\n const sourceDir = handleDirections[source.location];\n const targetDir = handleDirections[target.location];\n const sourceGapped: LinePoint = {\n x: source.x + sourceDir.x * OFFSET,\n y: source.y + sourceDir.y * OFFSET,\n location: source.location,\n };\n const targetGapped: LinePoint = {\n x: target.x + targetDir.x * OFFSET,\n y: target.y + targetDir.y * OFFSET,\n location: target.location,\n };\n const dir = getDirection({\n source: sourceGapped,\n target: targetGapped,\n });\n const dirAccessor = dir.x !== 0 ? 'x' : 'y';\n const currDir = dir[dirAccessor];\n\n let points: IPoint[] = [];\n let centerX, centerY;\n\n const [defaultCenterX, defaultCenterY] = getEdgeCenter({\n source,\n target,\n });\n\n // 计算向量乘积\n if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {\n centerX = defaultCenterX;\n centerY = defaultCenterY;\n\n const verticalSplit: IPoint[] = [\n { x: centerX, y: sourceGapped.y },\n { x: centerX, y: targetGapped.y },\n ];\n\n const horizontalSplit: IPoint[] = [\n { x: sourceGapped.x, y: centerY },\n { x: targetGapped.x, y: centerY },\n ];\n\n if (sourceDir[dirAccessor] === currDir) {\n points = dirAccessor === 'x' ? verticalSplit : horizontalSplit;\n } else {\n points = dirAccessor === 'x' ? horizontalSplit : verticalSplit;\n }\n } else {\n // sourceTarget means we take x from source and y from target, targetSource is the opposite\n const sourceTarget: IPoint[] = [{ x: sourceGapped.x, y: targetGapped.y }];\n const targetSource: IPoint[] = [{ x: targetGapped.x, y: sourceGapped.y }];\n // this handles edges with same handle positions\n if (dirAccessor === 'x') {\n points = sourceDir.x === currDir ? targetSource : sourceTarget;\n } else {\n points = sourceDir.y === currDir ? sourceTarget : targetSource;\n }\n\n // these are conditions for handling mixed handle positions like Right -> Bottom for example\n const dirAccessorOpposite = dirAccessor === 'x' ? 'y' : 'x';\n const isSameDir = sourceDir[dirAccessor] === targetDir[dirAccessorOpposite];\n const sourceGtTargetOppo =\n sourceGapped[dirAccessorOpposite] > targetGapped[dirAccessorOpposite];\n const sourceLtTargetOppo =\n sourceGapped[dirAccessorOpposite] < targetGapped[dirAccessorOpposite];\n const flipSourceTarget =\n (sourceDir[dirAccessor] === 1 &&\n ((!isSameDir && sourceGtTargetOppo) || (isSameDir && sourceLtTargetOppo))) ||\n (sourceDir[dirAccessor] !== 1 &&\n ((!isSameDir && sourceLtTargetOppo) || (isSameDir && sourceGtTargetOppo)));\n\n if (flipSourceTarget) {\n points = dirAccessor === 'x' ? sourceTarget : targetSource;\n }\n\n const sourceGapPoint = { x: sourceGapped.x, y: sourceGapped.y };\n const targetGapPoint = { x: targetGapped.x, y: targetGapped.y };\n const maxXDistance = Math.max(\n Math.abs(sourceGapPoint.x - points[0].x),\n Math.abs(targetGapPoint.x - points[0].x)\n );\n const maxYDistance = Math.max(\n Math.abs(sourceGapPoint.y - points[0].y),\n Math.abs(targetGapPoint.y - points[0].y)\n );\n\n if (maxXDistance >= maxYDistance) {\n centerX = (sourceGapPoint.x + targetGapPoint.x) / 2;\n centerY = points[0].y;\n } else {\n centerX = points[0].x;\n centerY = (sourceGapPoint.y + targetGapPoint.y) / 2;\n }\n }\n\n const pathPoints = [\n source,\n { x: sourceGapped.x, y: sourceGapped.y },\n ...points,\n { x: targetGapped.x, y: targetGapped.y },\n target,\n ];\n\n return {\n points: pathPoints,\n center: {\n x: centerX,\n y: centerY,\n },\n };\n }\n\n function getBend(a: IPoint, b: IPoint, c: IPoint): string {\n const bendSize = Math.min(\n Point.getDistance(a, b) / 2,\n Point.getDistance(b, c) / 2,\n EDGE_RADIUS\n );\n const { x, y } = b;\n\n // no bend\n if ((a.x === x && x === c.x) || (a.y === y && y === c.y)) {\n return `L${x} ${y}`;\n }\n\n // first segment is horizontal\n if (a.y === y) {\n const xDir = a.x < c.x ? -1 : 1;\n const yDir = a.y < c.y ? 1 : -1;\n return `L ${x + bendSize * xDir},${y}Q ${x},${y} ${x},${y + bendSize * yDir}`;\n }\n\n const xDir = a.x < c.x ? 1 : -1;\n const yDir = a.y < c.y ? -1 : 1;\n return `L ${x},${y + bendSize * yDir}Q ${x},${y} ${x + bendSize * xDir},${y}`;\n }\n\n /**\n * 实现 reactFlow 原本的折叠线交互\n */\n export function getSmoothStepPath(points: IPoint[]): string {\n const path = points.reduce<string>((res, p, i) => {\n let segment = '';\n\n if (i > 0 && i < points.length - 1) {\n segment = getBend(points[i - 1], p, points[i + 1]);\n } else {\n segment = `${i === 0 ? 'M' : 'L'}${p.x} ${p.y}`;\n }\n\n res += segment;\n\n return res;\n }, '');\n\n return path;\n }\n export function getBounds(points: IPoint[]): Rectangle {\n const xList = points.map((p) => p.x);\n const yList = points.map((p) => p.y);\n const left = Math.min(...xList);\n const right = Math.max(...xList);\n const top = Math.min(...yList);\n const bottom = Math.max(...yList);\n return Rectangle.createRectangleWithTwoPoints(\n {\n x: left,\n y: top,\n },\n {\n x: right,\n y: bottom,\n }\n );\n }\n /**\n * 计算点到折线的最短距离\n * @param points 折线的所有端点\n * @param pos 待测试点\n * @returns 最短距离\n */\n export const getFoldLineToPointDistance = (points: IPoint[], pos: IPoint): number => {\n // 特殊情况处理\n if (points.length === 0) {\n return Infinity;\n }\n\n if (points.length === 1) {\n return Point.getDistance(points[0]!, pos);\n }\n\n // 构建线段数组\n const lines: [IPoint, IPoint][] = [];\n for (let i = 0; i < points.length - 1; i++) {\n lines.push([points[i]!, points[i + 1]!]);\n }\n\n // 计算点到每个线段的最短距离\n const distances = lines.map((line) => {\n const [p1, p2] = line;\n return getPointToSegmentDistance(pos, p1, p2);\n });\n\n return Math.min(...distances);\n };\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { IPoint, Point, Rectangle } from '@flowgram.ai/utils';\nimport {\n WorkflowLineEntity,\n WorkflowLineRenderContribution,\n LinePoint,\n LineCenterPoint,\n getLineCenter,\n LineType,\n} from '@flowgram.ai/free-layout-core';\n\nimport { LINE_PADDING } from '../../constants/lines';\nimport { projectPointOnLine } from './point-on-line';\n\nexport interface StraightData {\n points: IPoint[];\n path: string;\n bbox: Rectangle;\n center: LineCenterPoint;\n}\n\nexport class WorkflowStraightLineContribution implements WorkflowLineRenderContribution {\n public static type = LineType.STRAIGHT;\n\n public entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n this.entity = entity;\n }\n\n private data?: StraightData;\n\n public get path(): string {\n return this.data?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n if (!this.data) {\n return Number.MAX_SAFE_INTEGER;\n }\n const [start, end] = this.data.points;\n return Point.getDistance(pos, projectPointOnLine(pos, start, end));\n }\n\n public get bounds(): Rectangle {\n if (!this.data) {\n return new Rectangle();\n }\n return this.data.bbox;\n }\n\n get center() {\n return this.data?.center;\n }\n\n public update(params: { fromPos: LinePoint; toPos: LinePoint }): void {\n const { fromPos, toPos } = params;\n const shrink = this.entity.uiState.shrink;\n\n // 根据方向预先计算源点和目标点的偏移\n const sourceOffset = {\n x: fromPos.location === 'bottom' ? 0 : shrink,\n y: fromPos.location === 'bottom' ? shrink : 0,\n };\n const targetOffset = {\n x: toPos.location === 'top' ? 0 : -shrink,\n y: toPos.location === 'top' ? -shrink : 0,\n };\n\n const points = [\n {\n x: fromPos.x + sourceOffset.x,\n y: fromPos.y + sourceOffset.y,\n },\n {\n x: toPos.x + targetOffset.x,\n y: toPos.y + targetOffset.y,\n },\n ];\n\n const bbox = Rectangle.createRectangleWithTwoPoints(points[0], points[1]);\n\n // 调整所有点到 SVG 视口坐标系\n const adjustedPoints = points.map((p) => ({\n x: p.x - bbox.x + LINE_PADDING,\n y: p.y - bbox.y + LINE_PADDING,\n }));\n\n // 生成直线路径\n const path = `M ${adjustedPoints[0].x} ${adjustedPoints[0].y} L ${adjustedPoints[1].x} ${adjustedPoints[1].y}`;\n\n this.data = {\n points,\n path,\n bbox,\n center: getLineCenter(fromPos, toPos, bbox, LINE_PADDING),\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';\n\nexport interface StraightData {\n points: IPoint[];\n path: string;\n bbox: Rectangle;\n}\n\n/**\n * 计算点到直线的投影点\n */\nexport function projectPointOnLine(point: IPoint, lineStart: IPoint, lineEnd: IPoint): IPoint {\n const dx = lineEnd.x - lineStart.x;\n const dy = lineEnd.y - lineStart.y;\n\n // 如果是垂直线\n if (dx === 0) {\n return { x: lineStart.x, y: point.y };\n }\n // 如果是水平线\n if (dy === 0) {\n return { x: point.x, y: lineStart.y };\n }\n\n const t = ((point.x - lineStart.x) * dx + (point.y - lineStart.y) * dy) / (dx * dx + dy * dy);\n const clampedT = Math.max(0, Math.min(1, t));\n\n return {\n x: lineStart.x + clampedT * dx,\n y: lineStart.y + clampedT * dy,\n };\n}\n"],"mappings":"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","names":["React","React","WorkflowLinesManager","ReactDOM","React","useState","WorkflowHoverService","WorkflowLineRenderData","React","styled","React","React","toRelative","React","useState","WorkflowLineRenderData","React","ReactDOM","WorkflowHoverService","Rectangle","LineType","Point","Rectangle","FoldLine","xDir","yDir","Rectangle","LineType","Point","Rectangle","LineType","Point","Rectangle","LineType","WorkflowLinesManager"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { ReactNode, FC } from 'react';
|
|
2
|
-
import { WorkflowPortEntity, WorkflowLineEntity, LineRenderType, WorkflowLineRenderContributionFactory, WorkflowHoverService, WorkflowSelectService, WorkflowDocument, WorkflowLineRenderContribution, LineType, LinePoint } from '@flowgram.ai/free-layout-core';
|
|
2
|
+
import { WorkflowPortEntity, WorkflowLineEntity, LineRenderType, WorkflowLineRenderContributionFactory, WorkflowHoverService, WorkflowSelectService, WorkflowDocument, LineCenterPoint, WorkflowLineRenderContribution, LineType, LinePoint } from '@flowgram.ai/free-layout-core';
|
|
3
3
|
import * as _flowgram_ai_core from '@flowgram.ai/core';
|
|
4
4
|
import { Layer, TransformData } from '@flowgram.ai/core';
|
|
5
5
|
import { FlowRendererRegistry } from '@flowgram.ai/renderer';
|
|
@@ -137,6 +137,7 @@ interface BezierData {
|
|
|
137
137
|
controls: IPoint[];
|
|
138
138
|
bezier: Bezier;
|
|
139
139
|
path: string;
|
|
140
|
+
center: LineCenterPoint;
|
|
140
141
|
}
|
|
141
142
|
declare class WorkflowBezierLineContribution implements WorkflowLineRenderContribution {
|
|
142
143
|
static type: LineType;
|
|
@@ -146,6 +147,7 @@ declare class WorkflowBezierLineContribution implements WorkflowLineRenderContri
|
|
|
146
147
|
get path(): string;
|
|
147
148
|
calcDistance(pos: IPoint): number;
|
|
148
149
|
get bounds(): Rectangle;
|
|
150
|
+
get center(): LineCenterPoint | undefined;
|
|
149
151
|
update(params: {
|
|
150
152
|
fromPos: LinePoint;
|
|
151
153
|
toPos: LinePoint;
|
|
@@ -163,6 +165,7 @@ interface FoldData {
|
|
|
163
165
|
points: IPoint[];
|
|
164
166
|
path: string;
|
|
165
167
|
bbox: Rectangle;
|
|
168
|
+
center: LineCenterPoint;
|
|
166
169
|
}
|
|
167
170
|
declare class WorkflowFoldLineContribution implements WorkflowLineRenderContribution {
|
|
168
171
|
static type: LineType;
|
|
@@ -172,6 +175,7 @@ declare class WorkflowFoldLineContribution implements WorkflowLineRenderContribu
|
|
|
172
175
|
get path(): string;
|
|
173
176
|
calcDistance(pos: IPoint): number;
|
|
174
177
|
get bounds(): Rectangle;
|
|
178
|
+
get center(): LineCenterPoint | undefined;
|
|
175
179
|
update(params: {
|
|
176
180
|
fromPos: LinePoint;
|
|
177
181
|
toPos: LinePoint;
|
|
@@ -187,46 +191,21 @@ interface StraightData {
|
|
|
187
191
|
points: IPoint[];
|
|
188
192
|
path: string;
|
|
189
193
|
bbox: Rectangle;
|
|
194
|
+
center: LineCenterPoint;
|
|
190
195
|
}
|
|
191
196
|
declare class WorkflowStraightLineContribution implements WorkflowLineRenderContribution {
|
|
192
|
-
static type:
|
|
197
|
+
static type: LineType;
|
|
193
198
|
entity: WorkflowLineEntity;
|
|
194
199
|
constructor(entity: WorkflowLineEntity);
|
|
195
200
|
private data?;
|
|
196
201
|
get path(): string;
|
|
197
202
|
calcDistance(pos: IPoint): number;
|
|
198
203
|
get bounds(): Rectangle;
|
|
204
|
+
get center(): LineCenterPoint | undefined;
|
|
199
205
|
update(params: {
|
|
200
206
|
fromPos: LinePoint;
|
|
201
207
|
toPos: LinePoint;
|
|
202
208
|
}): void;
|
|
203
209
|
}
|
|
204
210
|
|
|
205
|
-
|
|
206
|
-
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
207
|
-
* SPDX-License-Identifier: MIT
|
|
208
|
-
*/
|
|
209
|
-
|
|
210
|
-
interface ArcData {
|
|
211
|
-
fromPos: IPoint;
|
|
212
|
-
toPos: IPoint;
|
|
213
|
-
path: string;
|
|
214
|
-
bbox: Rectangle;
|
|
215
|
-
}
|
|
216
|
-
declare class WorkflowArkLineContribution implements WorkflowLineRenderContribution {
|
|
217
|
-
static type: string;
|
|
218
|
-
entity: WorkflowLineEntity;
|
|
219
|
-
constructor(entity: WorkflowLineEntity);
|
|
220
|
-
private data?;
|
|
221
|
-
get path(): string;
|
|
222
|
-
calcDistance(pos: IPoint): number;
|
|
223
|
-
get bounds(): Rectangle;
|
|
224
|
-
update(params: {
|
|
225
|
-
fromPos: IPoint;
|
|
226
|
-
toPos: IPoint;
|
|
227
|
-
}): void;
|
|
228
|
-
private calculateArcBBox;
|
|
229
|
-
private getArcPath;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
export { type ArcData, type ArrowRendererComponent, type ArrowRendererProps, type BezierData, type FoldData, type FreeLinesPluginOptions, LINE_OFFSET, LINE_PADDING, type LineRenderProps, WorkflowLinesLayer as LinesLayer, type LinesLayerOptions, type StraightData, WorkflowArkLineContribution, WorkflowBezierLineContribution, WorkflowFoldLineContribution, WorkflowLinesLayer, WorkflowPortRender, type WorkflowPortRenderProps, WorkflowStraightLineContribution, createFreeLinesPlugin };
|
|
211
|
+
export { type ArrowRendererComponent, type ArrowRendererProps, type BezierData, type FoldData, type FreeLinesPluginOptions, LINE_OFFSET, LINE_PADDING, type LineRenderProps, WorkflowLinesLayer as LinesLayer, type LinesLayerOptions, type StraightData, WorkflowBezierLineContribution, WorkflowFoldLineContribution, WorkflowLinesLayer, WorkflowPortRender, type WorkflowPortRenderProps, WorkflowStraightLineContribution, createFreeLinesPlugin };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { ReactNode, FC } from 'react';
|
|
2
|
-
import { WorkflowPortEntity, WorkflowLineEntity, LineRenderType, WorkflowLineRenderContributionFactory, WorkflowHoverService, WorkflowSelectService, WorkflowDocument, WorkflowLineRenderContribution, LineType, LinePoint } from '@flowgram.ai/free-layout-core';
|
|
2
|
+
import { WorkflowPortEntity, WorkflowLineEntity, LineRenderType, WorkflowLineRenderContributionFactory, WorkflowHoverService, WorkflowSelectService, WorkflowDocument, LineCenterPoint, WorkflowLineRenderContribution, LineType, LinePoint } from '@flowgram.ai/free-layout-core';
|
|
3
3
|
import * as _flowgram_ai_core from '@flowgram.ai/core';
|
|
4
4
|
import { Layer, TransformData } from '@flowgram.ai/core';
|
|
5
5
|
import { FlowRendererRegistry } from '@flowgram.ai/renderer';
|
|
@@ -137,6 +137,7 @@ interface BezierData {
|
|
|
137
137
|
controls: IPoint[];
|
|
138
138
|
bezier: Bezier;
|
|
139
139
|
path: string;
|
|
140
|
+
center: LineCenterPoint;
|
|
140
141
|
}
|
|
141
142
|
declare class WorkflowBezierLineContribution implements WorkflowLineRenderContribution {
|
|
142
143
|
static type: LineType;
|
|
@@ -146,6 +147,7 @@ declare class WorkflowBezierLineContribution implements WorkflowLineRenderContri
|
|
|
146
147
|
get path(): string;
|
|
147
148
|
calcDistance(pos: IPoint): number;
|
|
148
149
|
get bounds(): Rectangle;
|
|
150
|
+
get center(): LineCenterPoint | undefined;
|
|
149
151
|
update(params: {
|
|
150
152
|
fromPos: LinePoint;
|
|
151
153
|
toPos: LinePoint;
|
|
@@ -163,6 +165,7 @@ interface FoldData {
|
|
|
163
165
|
points: IPoint[];
|
|
164
166
|
path: string;
|
|
165
167
|
bbox: Rectangle;
|
|
168
|
+
center: LineCenterPoint;
|
|
166
169
|
}
|
|
167
170
|
declare class WorkflowFoldLineContribution implements WorkflowLineRenderContribution {
|
|
168
171
|
static type: LineType;
|
|
@@ -172,6 +175,7 @@ declare class WorkflowFoldLineContribution implements WorkflowLineRenderContribu
|
|
|
172
175
|
get path(): string;
|
|
173
176
|
calcDistance(pos: IPoint): number;
|
|
174
177
|
get bounds(): Rectangle;
|
|
178
|
+
get center(): LineCenterPoint | undefined;
|
|
175
179
|
update(params: {
|
|
176
180
|
fromPos: LinePoint;
|
|
177
181
|
toPos: LinePoint;
|
|
@@ -187,46 +191,21 @@ interface StraightData {
|
|
|
187
191
|
points: IPoint[];
|
|
188
192
|
path: string;
|
|
189
193
|
bbox: Rectangle;
|
|
194
|
+
center: LineCenterPoint;
|
|
190
195
|
}
|
|
191
196
|
declare class WorkflowStraightLineContribution implements WorkflowLineRenderContribution {
|
|
192
|
-
static type:
|
|
197
|
+
static type: LineType;
|
|
193
198
|
entity: WorkflowLineEntity;
|
|
194
199
|
constructor(entity: WorkflowLineEntity);
|
|
195
200
|
private data?;
|
|
196
201
|
get path(): string;
|
|
197
202
|
calcDistance(pos: IPoint): number;
|
|
198
203
|
get bounds(): Rectangle;
|
|
204
|
+
get center(): LineCenterPoint | undefined;
|
|
199
205
|
update(params: {
|
|
200
206
|
fromPos: LinePoint;
|
|
201
207
|
toPos: LinePoint;
|
|
202
208
|
}): void;
|
|
203
209
|
}
|
|
204
210
|
|
|
205
|
-
|
|
206
|
-
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
207
|
-
* SPDX-License-Identifier: MIT
|
|
208
|
-
*/
|
|
209
|
-
|
|
210
|
-
interface ArcData {
|
|
211
|
-
fromPos: IPoint;
|
|
212
|
-
toPos: IPoint;
|
|
213
|
-
path: string;
|
|
214
|
-
bbox: Rectangle;
|
|
215
|
-
}
|
|
216
|
-
declare class WorkflowArkLineContribution implements WorkflowLineRenderContribution {
|
|
217
|
-
static type: string;
|
|
218
|
-
entity: WorkflowLineEntity;
|
|
219
|
-
constructor(entity: WorkflowLineEntity);
|
|
220
|
-
private data?;
|
|
221
|
-
get path(): string;
|
|
222
|
-
calcDistance(pos: IPoint): number;
|
|
223
|
-
get bounds(): Rectangle;
|
|
224
|
-
update(params: {
|
|
225
|
-
fromPos: IPoint;
|
|
226
|
-
toPos: IPoint;
|
|
227
|
-
}): void;
|
|
228
|
-
private calculateArcBBox;
|
|
229
|
-
private getArcPath;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
export { type ArcData, type ArrowRendererComponent, type ArrowRendererProps, type BezierData, type FoldData, type FreeLinesPluginOptions, LINE_OFFSET, LINE_PADDING, type LineRenderProps, WorkflowLinesLayer as LinesLayer, type LinesLayerOptions, type StraightData, WorkflowArkLineContribution, WorkflowBezierLineContribution, WorkflowFoldLineContribution, WorkflowLinesLayer, WorkflowPortRender, type WorkflowPortRenderProps, WorkflowStraightLineContribution, createFreeLinesPlugin };
|
|
211
|
+
export { type ArrowRendererComponent, type ArrowRendererProps, type BezierData, type FoldData, type FreeLinesPluginOptions, LINE_OFFSET, LINE_PADDING, type LineRenderProps, WorkflowLinesLayer as LinesLayer, type LinesLayerOptions, type StraightData, WorkflowBezierLineContribution, WorkflowFoldLineContribution, WorkflowLinesLayer, WorkflowPortRender, type WorkflowPortRenderProps, WorkflowStraightLineContribution, createFreeLinesPlugin };
|