@yh-ui/flow 0.1.21

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.
Files changed (354) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +234 -0
  3. package/dist/Flow.d.vue.ts +306 -0
  4. package/dist/Flow.vue +959 -0
  5. package/dist/Flow.vue.d.ts +306 -0
  6. package/dist/__tests__/ai-workflow.ssr.test.cjs +352 -0
  7. package/dist/__tests__/ai-workflow.ssr.test.d.ts +1 -0
  8. package/dist/__tests__/ai-workflow.ssr.test.mjs +283 -0
  9. package/dist/__tests__/ai-workflow.test.cjs +109 -0
  10. package/dist/__tests__/ai-workflow.test.d.ts +1 -0
  11. package/dist/__tests__/ai-workflow.test.mjs +112 -0
  12. package/dist/__tests__/bpmn.ssr.test.cjs +278 -0
  13. package/dist/__tests__/bpmn.ssr.test.d.ts +1 -0
  14. package/dist/__tests__/bpmn.ssr.test.mjs +237 -0
  15. package/dist/__tests__/bpmn.test.cjs +103 -0
  16. package/dist/__tests__/bpmn.test.d.ts +1 -0
  17. package/dist/__tests__/bpmn.test.mjs +106 -0
  18. package/dist/__tests__/custom-types.test.cjs +300 -0
  19. package/dist/__tests__/custom-types.test.d.ts +1 -0
  20. package/dist/__tests__/custom-types.test.mjs +248 -0
  21. package/dist/__tests__/edge.test.cjs +56 -0
  22. package/dist/__tests__/edge.test.d.ts +1 -0
  23. package/dist/__tests__/edge.test.mjs +69 -0
  24. package/dist/__tests__/event-bus.test.cjs +80 -0
  25. package/dist/__tests__/event-bus.test.d.ts +1 -0
  26. package/dist/__tests__/event-bus.test.mjs +51 -0
  27. package/dist/__tests__/flow.ssr.test.cjs +156 -0
  28. package/dist/__tests__/flow.ssr.test.d.ts +1 -0
  29. package/dist/__tests__/flow.ssr.test.mjs +112 -0
  30. package/dist/__tests__/geometry.test.cjs +191 -0
  31. package/dist/__tests__/geometry.test.d.ts +1 -0
  32. package/dist/__tests__/geometry.test.mjs +105 -0
  33. package/dist/__tests__/graph.test.cjs +115 -0
  34. package/dist/__tests__/graph.test.d.ts +1 -0
  35. package/dist/__tests__/graph.test.mjs +85 -0
  36. package/dist/__tests__/history-plugin.test.cjs +191 -0
  37. package/dist/__tests__/history-plugin.test.d.ts +1 -0
  38. package/dist/__tests__/history-plugin.test.mjs +161 -0
  39. package/dist/__tests__/history.test.cjs +81 -0
  40. package/dist/__tests__/history.test.d.ts +1 -0
  41. package/dist/__tests__/history.test.mjs +43 -0
  42. package/dist/__tests__/layout.test.cjs +213 -0
  43. package/dist/__tests__/layout.test.d.ts +1 -0
  44. package/dist/__tests__/layout.test.mjs +170 -0
  45. package/dist/__tests__/node-edit-panel.ssr.test.cjs +168 -0
  46. package/dist/__tests__/node-edit-panel.ssr.test.d.ts +1 -0
  47. package/dist/__tests__/node-edit-panel.ssr.test.mjs +118 -0
  48. package/dist/__tests__/node-group-plugin.test.cjs +235 -0
  49. package/dist/__tests__/node-group-plugin.test.d.ts +1 -0
  50. package/dist/__tests__/node-group-plugin.test.mjs +187 -0
  51. package/dist/__tests__/node-handles.test.cjs +340 -0
  52. package/dist/__tests__/node-handles.test.d.ts +1 -0
  53. package/dist/__tests__/node-handles.test.mjs +230 -0
  54. package/dist/__tests__/plugin.test.cjs +151 -0
  55. package/dist/__tests__/plugin.test.d.ts +1 -0
  56. package/dist/__tests__/plugin.test.mjs +116 -0
  57. package/dist/__tests__/transform.test.cjs +58 -0
  58. package/dist/__tests__/transform.test.d.ts +1 -0
  59. package/dist/__tests__/transform.test.mjs +38 -0
  60. package/dist/__tests__/useAlignment.test.cjs +91 -0
  61. package/dist/__tests__/useAlignment.test.d.ts +1 -0
  62. package/dist/__tests__/useAlignment.test.mjs +52 -0
  63. package/dist/__tests__/useEdges.test.cjs +117 -0
  64. package/dist/__tests__/useEdges.test.d.ts +1 -0
  65. package/dist/__tests__/useEdges.test.mjs +80 -0
  66. package/dist/__tests__/useKeyboard.test.cjs +88 -0
  67. package/dist/__tests__/useKeyboard.test.d.ts +1 -0
  68. package/dist/__tests__/useKeyboard.test.mjs +56 -0
  69. package/dist/__tests__/useNodes.test.cjs +150 -0
  70. package/dist/__tests__/useNodes.test.d.ts +1 -0
  71. package/dist/__tests__/useNodes.test.mjs +80 -0
  72. package/dist/__tests__/useSelection.test.cjs +112 -0
  73. package/dist/__tests__/useSelection.test.d.ts +1 -0
  74. package/dist/__tests__/useSelection.test.mjs +76 -0
  75. package/dist/__tests__/useViewport.test.cjs +171 -0
  76. package/dist/__tests__/useViewport.test.d.ts +1 -0
  77. package/dist/__tests__/useViewport.test.mjs +82 -0
  78. package/dist/__tests__/utils/ssr.cjs +124 -0
  79. package/dist/__tests__/utils/ssr.d.ts +33 -0
  80. package/dist/__tests__/utils/ssr.mjs +129 -0
  81. package/dist/__tests__/validation.test.cjs +95 -0
  82. package/dist/__tests__/validation.test.d.ts +1 -0
  83. package/dist/__tests__/validation.test.mjs +36 -0
  84. package/dist/components/AiNodeEditPanel.d.vue.ts +13 -0
  85. package/dist/components/AiNodeEditPanel.vue +413 -0
  86. package/dist/components/AiNodeEditPanel.vue.d.ts +13 -0
  87. package/dist/components/EdgeEditPanel.d.vue.ts +14 -0
  88. package/dist/components/EdgeEditPanel.vue +205 -0
  89. package/dist/components/EdgeEditPanel.vue.d.ts +14 -0
  90. package/dist/components/NodeEditPanel.d.vue.ts +13 -0
  91. package/dist/components/NodeEditPanel.vue +214 -0
  92. package/dist/components/NodeEditPanel.vue.d.ts +13 -0
  93. package/dist/components/edges/BaseEdge.d.vue.ts +23 -0
  94. package/dist/components/edges/BaseEdge.vue +55 -0
  95. package/dist/components/edges/BaseEdge.vue.d.ts +23 -0
  96. package/dist/components/edges/BezierEdge.d.vue.ts +22 -0
  97. package/dist/components/edges/BezierEdge.vue +57 -0
  98. package/dist/components/edges/BezierEdge.vue.d.ts +22 -0
  99. package/dist/components/edges/DataFlowEdge.d.vue.ts +41 -0
  100. package/dist/components/edges/DataFlowEdge.vue +211 -0
  101. package/dist/components/edges/DataFlowEdge.vue.d.ts +41 -0
  102. package/dist/components/edges/SmoothEdge.d.vue.ts +22 -0
  103. package/dist/components/edges/SmoothEdge.vue +53 -0
  104. package/dist/components/edges/SmoothEdge.vue.d.ts +22 -0
  105. package/dist/components/edges/StepEdge.d.vue.ts +22 -0
  106. package/dist/components/edges/StepEdge.vue +42 -0
  107. package/dist/components/edges/StepEdge.vue.d.ts +22 -0
  108. package/dist/components/edges/index.cjs +41 -0
  109. package/dist/components/edges/index.d.ts +5 -0
  110. package/dist/components/edges/index.mjs +5 -0
  111. package/dist/components/nodes/BaseNode.d.vue.ts +25 -0
  112. package/dist/components/nodes/BaseNode.vue +93 -0
  113. package/dist/components/nodes/BaseNode.vue.d.ts +25 -0
  114. package/dist/components/nodes/CustomNode.d.vue.ts +36 -0
  115. package/dist/components/nodes/CustomNode.vue +44 -0
  116. package/dist/components/nodes/CustomNode.vue.d.ts +36 -0
  117. package/dist/components/nodes/DatabaseNode.d.vue.ts +19 -0
  118. package/dist/components/nodes/DatabaseNode.vue +62 -0
  119. package/dist/components/nodes/DatabaseNode.vue.d.ts +19 -0
  120. package/dist/components/nodes/DiamondNode.d.vue.ts +19 -0
  121. package/dist/components/nodes/DiamondNode.vue +62 -0
  122. package/dist/components/nodes/DiamondNode.vue.d.ts +19 -0
  123. package/dist/components/nodes/GroupNode.d.vue.ts +31 -0
  124. package/dist/components/nodes/GroupNode.vue +48 -0
  125. package/dist/components/nodes/GroupNode.vue.d.ts +31 -0
  126. package/dist/components/nodes/InputNode.d.vue.ts +23 -0
  127. package/dist/components/nodes/InputNode.vue +63 -0
  128. package/dist/components/nodes/InputNode.vue.d.ts +23 -0
  129. package/dist/components/nodes/NodeResizer.d.vue.ts +27 -0
  130. package/dist/components/nodes/NodeResizer.vue +89 -0
  131. package/dist/components/nodes/NodeResizer.vue.d.ts +27 -0
  132. package/dist/components/nodes/NodeToolbar.d.vue.ts +32 -0
  133. package/dist/components/nodes/NodeToolbar.vue +101 -0
  134. package/dist/components/nodes/NodeToolbar.vue.d.ts +32 -0
  135. package/dist/components/nodes/OutputNode.d.vue.ts +21 -0
  136. package/dist/components/nodes/OutputNode.vue +53 -0
  137. package/dist/components/nodes/OutputNode.vue.d.ts +21 -0
  138. package/dist/components/nodes/ai-workflow/AiAgentNode.d.vue.ts +20 -0
  139. package/dist/components/nodes/ai-workflow/AiAgentNode.vue +59 -0
  140. package/dist/components/nodes/ai-workflow/AiAgentNode.vue.d.ts +20 -0
  141. package/dist/components/nodes/ai-workflow/AiConditionNode.d.vue.ts +19 -0
  142. package/dist/components/nodes/ai-workflow/AiConditionNode.vue +65 -0
  143. package/dist/components/nodes/ai-workflow/AiConditionNode.vue.d.ts +19 -0
  144. package/dist/components/nodes/ai-workflow/AiEndNode.d.vue.ts +19 -0
  145. package/dist/components/nodes/ai-workflow/AiEndNode.vue +47 -0
  146. package/dist/components/nodes/ai-workflow/AiEndNode.vue.d.ts +19 -0
  147. package/dist/components/nodes/ai-workflow/AiLlmNode.d.vue.ts +19 -0
  148. package/dist/components/nodes/ai-workflow/AiLlmNode.vue +64 -0
  149. package/dist/components/nodes/ai-workflow/AiLlmNode.vue.d.ts +19 -0
  150. package/dist/components/nodes/ai-workflow/AiMemoryNode.d.vue.ts +19 -0
  151. package/dist/components/nodes/ai-workflow/AiMemoryNode.vue +59 -0
  152. package/dist/components/nodes/ai-workflow/AiMemoryNode.vue.d.ts +19 -0
  153. package/dist/components/nodes/ai-workflow/AiPromptNode.d.vue.ts +19 -0
  154. package/dist/components/nodes/ai-workflow/AiPromptNode.vue +61 -0
  155. package/dist/components/nodes/ai-workflow/AiPromptNode.vue.d.ts +19 -0
  156. package/dist/components/nodes/ai-workflow/AiStartNode.d.vue.ts +19 -0
  157. package/dist/components/nodes/ai-workflow/AiStartNode.vue +47 -0
  158. package/dist/components/nodes/ai-workflow/AiStartNode.vue.d.ts +19 -0
  159. package/dist/components/nodes/ai-workflow/AiToolNode.d.vue.ts +19 -0
  160. package/dist/components/nodes/ai-workflow/AiToolNode.vue +59 -0
  161. package/dist/components/nodes/ai-workflow/AiToolNode.vue.d.ts +19 -0
  162. package/dist/components/nodes/ai-workflow/index.cjs +109 -0
  163. package/dist/components/nodes/ai-workflow/index.d.ts +23 -0
  164. package/dist/components/nodes/ai-workflow/index.mjs +37 -0
  165. package/dist/components/nodes/bpmn/BpmnEndEvent.d.vue.ts +19 -0
  166. package/dist/components/nodes/bpmn/BpmnEndEvent.vue +50 -0
  167. package/dist/components/nodes/bpmn/BpmnEndEvent.vue.d.ts +19 -0
  168. package/dist/components/nodes/bpmn/BpmnExclusiveGateway.d.vue.ts +19 -0
  169. package/dist/components/nodes/bpmn/BpmnExclusiveGateway.vue +60 -0
  170. package/dist/components/nodes/bpmn/BpmnExclusiveGateway.vue.d.ts +19 -0
  171. package/dist/components/nodes/bpmn/BpmnInclusiveGateway.d.vue.ts +19 -0
  172. package/dist/components/nodes/bpmn/BpmnInclusiveGateway.vue +60 -0
  173. package/dist/components/nodes/bpmn/BpmnInclusiveGateway.vue.d.ts +19 -0
  174. package/dist/components/nodes/bpmn/BpmnParallelGateway.d.vue.ts +19 -0
  175. package/dist/components/nodes/bpmn/BpmnParallelGateway.vue +60 -0
  176. package/dist/components/nodes/bpmn/BpmnParallelGateway.vue.d.ts +19 -0
  177. package/dist/components/nodes/bpmn/BpmnServiceTask.d.vue.ts +19 -0
  178. package/dist/components/nodes/bpmn/BpmnServiceTask.vue +55 -0
  179. package/dist/components/nodes/bpmn/BpmnServiceTask.vue.d.ts +19 -0
  180. package/dist/components/nodes/bpmn/BpmnStartEvent.d.vue.ts +19 -0
  181. package/dist/components/nodes/bpmn/BpmnStartEvent.vue +50 -0
  182. package/dist/components/nodes/bpmn/BpmnStartEvent.vue.d.ts +19 -0
  183. package/dist/components/nodes/bpmn/BpmnTask.d.vue.ts +19 -0
  184. package/dist/components/nodes/bpmn/BpmnTask.vue +54 -0
  185. package/dist/components/nodes/bpmn/BpmnTask.vue.d.ts +19 -0
  186. package/dist/components/nodes/bpmn/BpmnUserTask.d.vue.ts +19 -0
  187. package/dist/components/nodes/bpmn/BpmnUserTask.vue +55 -0
  188. package/dist/components/nodes/bpmn/BpmnUserTask.vue.d.ts +19 -0
  189. package/dist/components/nodes/bpmn/index.cjs +109 -0
  190. package/dist/components/nodes/bpmn/index.d.ts +23 -0
  191. package/dist/components/nodes/bpmn/index.mjs +37 -0
  192. package/dist/components/nodes/index.cjs +246 -0
  193. package/dist/components/nodes/index.d.ts +13 -0
  194. package/dist/components/nodes/index.mjs +44 -0
  195. package/dist/core/FlowContext.cjs +21 -0
  196. package/dist/core/FlowContext.d.ts +10 -0
  197. package/dist/core/FlowContext.mjs +13 -0
  198. package/dist/core/index.cjs +104 -0
  199. package/dist/core/index.d.ts +9 -0
  200. package/dist/core/index.mjs +9 -0
  201. package/dist/core/useAlignment.cjs +81 -0
  202. package/dist/core/useAlignment.d.ts +33 -0
  203. package/dist/core/useAlignment.mjs +71 -0
  204. package/dist/core/useEdges.cjs +132 -0
  205. package/dist/core/useEdges.d.ts +29 -0
  206. package/dist/core/useEdges.mjs +89 -0
  207. package/dist/core/useFlow.cjs +40 -0
  208. package/dist/core/useFlow.d.ts +31 -0
  209. package/dist/core/useFlow.mjs +32 -0
  210. package/dist/core/useHistory.cjs +63 -0
  211. package/dist/core/useHistory.d.ts +15 -0
  212. package/dist/core/useHistory.mjs +54 -0
  213. package/dist/core/useKeyboard.cjs +54 -0
  214. package/dist/core/useKeyboard.d.ts +18 -0
  215. package/dist/core/useKeyboard.mjs +45 -0
  216. package/dist/core/useNodeDistribution.cjs +171 -0
  217. package/dist/core/useNodeDistribution.d.ts +12 -0
  218. package/dist/core/useNodeDistribution.mjs +145 -0
  219. package/dist/core/useNodes.cjs +146 -0
  220. package/dist/core/useNodes.d.ts +26 -0
  221. package/dist/core/useNodes.mjs +101 -0
  222. package/dist/core/useSelection.cjs +83 -0
  223. package/dist/core/useSelection.d.ts +18 -0
  224. package/dist/core/useSelection.mjs +53 -0
  225. package/dist/core/useViewport.cjs +157 -0
  226. package/dist/core/useViewport.d.ts +65 -0
  227. package/dist/core/useViewport.mjs +125 -0
  228. package/dist/flow.cjs +240 -0
  229. package/dist/flow.d.ts +276 -0
  230. package/dist/flow.mjs +230 -0
  231. package/dist/index.cjs +378 -0
  232. package/dist/index.d.ts +28 -0
  233. package/dist/index.mjs +50 -0
  234. package/dist/plugins/index.cjs +96 -0
  235. package/dist/plugins/index.d.ts +34 -0
  236. package/dist/plugins/index.mjs +47 -0
  237. package/dist/plugins/plugin.cjs +117 -0
  238. package/dist/plugins/plugin.d.ts +72 -0
  239. package/dist/plugins/plugin.mjs +110 -0
  240. package/dist/plugins/plugins/controls.cjs +38 -0
  241. package/dist/plugins/plugins/controls.d.ts +12 -0
  242. package/dist/plugins/plugins/controls.mjs +28 -0
  243. package/dist/plugins/plugins/export.cjs +102 -0
  244. package/dist/plugins/plugins/export.d.ts +12 -0
  245. package/dist/plugins/plugins/export.mjs +89 -0
  246. package/dist/plugins/plugins/grid.cjs +36 -0
  247. package/dist/plugins/plugins/grid.d.ts +11 -0
  248. package/dist/plugins/plugins/grid.mjs +26 -0
  249. package/dist/plugins/plugins/history.cjs +140 -0
  250. package/dist/plugins/plugins/history.d.ts +53 -0
  251. package/dist/plugins/plugins/history.mjs +132 -0
  252. package/dist/plugins/plugins/index.cjs +104 -0
  253. package/dist/plugins/plugins/index.d.ts +9 -0
  254. package/dist/plugins/plugins/index.mjs +9 -0
  255. package/dist/plugins/plugins/keyboard.cjs +27 -0
  256. package/dist/plugins/plugins/keyboard.d.ts +10 -0
  257. package/dist/plugins/plugins/keyboard.mjs +18 -0
  258. package/dist/plugins/plugins/layout.cjs +275 -0
  259. package/dist/plugins/plugins/layout.d.ts +34 -0
  260. package/dist/plugins/plugins/layout.mjs +246 -0
  261. package/dist/plugins/plugins/minimap.cjs +60 -0
  262. package/dist/plugins/plugins/minimap.d.ts +25 -0
  263. package/dist/plugins/plugins/minimap.mjs +50 -0
  264. package/dist/plugins/plugins/node-group.cjs +209 -0
  265. package/dist/plugins/plugins/node-group.d.ts +26 -0
  266. package/dist/plugins/plugins/node-group.mjs +178 -0
  267. package/dist/plugins/plugins/snap.cjs +36 -0
  268. package/dist/plugins/plugins/snap.d.ts +12 -0
  269. package/dist/plugins/plugins/snap.mjs +26 -0
  270. package/dist/renderer/AlignmentLines.d.vue.ts +5 -0
  271. package/dist/renderer/AlignmentLines.vue +113 -0
  272. package/dist/renderer/AlignmentLines.vue.d.ts +5 -0
  273. package/dist/renderer/Background.d.vue.ts +7 -0
  274. package/dist/renderer/Background.vue +86 -0
  275. package/dist/renderer/Background.vue.d.ts +7 -0
  276. package/dist/renderer/Controls.d.vue.ts +13 -0
  277. package/dist/renderer/Controls.vue +82 -0
  278. package/dist/renderer/Controls.vue.d.ts +13 -0
  279. package/dist/renderer/EdgeHandlesRenderer.d.vue.ts +11 -0
  280. package/dist/renderer/EdgeHandlesRenderer.vue +75 -0
  281. package/dist/renderer/EdgeHandlesRenderer.vue.d.ts +11 -0
  282. package/dist/renderer/EdgeRenderer.d.vue.ts +39 -0
  283. package/dist/renderer/EdgeRenderer.vue +204 -0
  284. package/dist/renderer/EdgeRenderer.vue.d.ts +39 -0
  285. package/dist/renderer/FlowBackground.d.vue.ts +11 -0
  286. package/dist/renderer/FlowBackground.vue +82 -0
  287. package/dist/renderer/FlowBackground.vue.d.ts +11 -0
  288. package/dist/renderer/Minimap.d.vue.ts +30 -0
  289. package/dist/renderer/Minimap.vue +290 -0
  290. package/dist/renderer/Minimap.vue.d.ts +30 -0
  291. package/dist/renderer/NodeRenderer.d.vue.ts +56 -0
  292. package/dist/renderer/NodeRenderer.vue +328 -0
  293. package/dist/renderer/NodeRenderer.vue.d.ts +56 -0
  294. package/dist/renderer/SelectionBox.d.vue.ts +11 -0
  295. package/dist/renderer/SelectionBox.vue +28 -0
  296. package/dist/renderer/SelectionBox.vue.d.ts +11 -0
  297. package/dist/types/edge.cjs +13 -0
  298. package/dist/types/edge.d.ts +65 -0
  299. package/dist/types/edge.mjs +6 -0
  300. package/dist/types/events.cjs +1 -0
  301. package/dist/types/events.d.ts +115 -0
  302. package/dist/types/events.mjs +0 -0
  303. package/dist/types/index.cjs +1 -0
  304. package/dist/types/index.d.ts +366 -0
  305. package/dist/types/index.mjs +0 -0
  306. package/dist/types/node.cjs +9 -0
  307. package/dist/types/node.d.ts +90 -0
  308. package/dist/types/node.mjs +3 -0
  309. package/dist/types/viewport.cjs +42 -0
  310. package/dist/types/viewport.d.ts +62 -0
  311. package/dist/types/viewport.mjs +36 -0
  312. package/dist/utils/bpmn-engine.cjs +390 -0
  313. package/dist/utils/bpmn-engine.d.ts +164 -0
  314. package/dist/utils/bpmn-engine.mjs +378 -0
  315. package/dist/utils/bpmn.cjs +492 -0
  316. package/dist/utils/bpmn.d.ts +53 -0
  317. package/dist/utils/bpmn.mjs +430 -0
  318. package/dist/utils/collaboration.cjs +537 -0
  319. package/dist/utils/collaboration.d.ts +189 -0
  320. package/dist/utils/collaboration.mjs +521 -0
  321. package/dist/utils/custom-types.cjs +138 -0
  322. package/dist/utils/custom-types.d.ts +78 -0
  323. package/dist/utils/custom-types.mjs +108 -0
  324. package/dist/utils/edge.cjs +235 -0
  325. package/dist/utils/edge.d.ts +79 -0
  326. package/dist/utils/edge.mjs +172 -0
  327. package/dist/utils/event-bus.cjs +91 -0
  328. package/dist/utils/event-bus.d.ts +39 -0
  329. package/dist/utils/event-bus.mjs +82 -0
  330. package/dist/utils/geometry.cjs +178 -0
  331. package/dist/utils/geometry.d.ts +186 -0
  332. package/dist/utils/geometry.mjs +144 -0
  333. package/dist/utils/graph.cjs +158 -0
  334. package/dist/utils/graph.d.ts +40 -0
  335. package/dist/utils/graph.mjs +147 -0
  336. package/dist/utils/index.cjs +137 -0
  337. package/dist/utils/index.d.ts +12 -0
  338. package/dist/utils/index.mjs +12 -0
  339. package/dist/utils/performance.cjs +94 -0
  340. package/dist/utils/performance.d.ts +18 -0
  341. package/dist/utils/performance.mjs +82 -0
  342. package/dist/utils/screenshot.cjs +87 -0
  343. package/dist/utils/screenshot.d.ts +22 -0
  344. package/dist/utils/screenshot.mjs +66 -0
  345. package/dist/utils/theme.cjs +228 -0
  346. package/dist/utils/theme.d.ts +92 -0
  347. package/dist/utils/theme.mjs +217 -0
  348. package/dist/utils/transform.cjs +76 -0
  349. package/dist/utils/transform.d.ts +45 -0
  350. package/dist/utils/transform.mjs +57 -0
  351. package/dist/utils/validation.cjs +107 -0
  352. package/dist/utils/validation.d.ts +29 -0
  353. package/dist/utils/validation.mjs +85 -0
  354. package/package.json +61 -0
package/dist/Flow.vue ADDED
@@ -0,0 +1,959 @@
1
+ <template>
2
+ <div
3
+ ref="containerRef"
4
+ class="yh-flow"
5
+ :class="{
6
+ 'is-readonly': readonly,
7
+ 'is-panning': isPanning
8
+ }"
9
+ tabindex="0"
10
+ @wheel.prevent="handleWheel"
11
+ @mousedown="handlePaneMouseDown"
12
+ >
13
+ <!-- Plugin Components (Background, etc.) -->
14
+ <template v-for="plugin in uiPlugins" :key="plugin.id">
15
+ <component v-if="plugin.component" :is="plugin.component" v-bind="plugin.componentProps" />
16
+ </template>
17
+
18
+ <!-- Main Content -->
19
+ <div class="yh-flow__content" :style="contentStyle">
20
+ <!-- Edges -->
21
+ <EdgeRenderer
22
+ :edges="edgesRef || []"
23
+ :nodes="nodesRef || []"
24
+ :edge-types="edgeTypes"
25
+ :transform="viewportRef"
26
+ :connecting-edge="connectingEdge"
27
+ @edge-click="handleEdgeClick"
28
+ @edge-dblclick="handleEdgeDblClick"
29
+ @edge-contextmenu="handleEdgeContextMenu"
30
+ @edge-update-start="handleEdgeUpdateStart"
31
+ :updating-edge-id="updatingEdge?.edge.id"
32
+ >
33
+ <template #edge="edgeProps">
34
+ <slot name="edge" v-bind="edgeProps" />
35
+ </template>
36
+ </EdgeRenderer>
37
+
38
+ <!-- Edge Handles (for updating/reconnecting edges) -->
39
+ <EdgeHandlesRenderer
40
+ :edges="edgesRef || []"
41
+ :nodes="nodesRef || []"
42
+ @edge-update-start="handleEdgeUpdateStart"
43
+ />
44
+
45
+ <!-- Nodes -->
46
+ <NodeRenderer
47
+ :nodes="visibleNodes || []"
48
+ :node-types="nodeTypes"
49
+ :transform="viewportRef"
50
+ :draggable="nodesDraggable && !readonly"
51
+ :readonly="readonly"
52
+ @node-click="handleNodeClick"
53
+ @node-dblclick="handleNodeDblClick"
54
+ @node-contextmenu="handleNodeContextMenu"
55
+ @node-drag-start="handleNodeDragStart"
56
+ @node-drag="handleNodeDrag"
57
+ @node-drag-end="handleNodeDragEnd"
58
+ @connect-start="handleConnectStart"
59
+ @node-select-toggle="handleNodeSelectToggle"
60
+ >
61
+ <template #node="nodeProps">
62
+ <slot name="node" v-bind="nodeProps" />
63
+ </template>
64
+ </NodeRenderer>
65
+
66
+ <!-- Selection Box -->
67
+ <SelectionBox
68
+ :selection-rect="selectionManager.selectionRect.value"
69
+ :transform="viewportRef"
70
+ />
71
+ </div>
72
+
73
+ <!-- UI Overlay Plugin Components (Controls, Minimap, etc.) -->
74
+ <template v-for="plugin in overlayPlugins" :key="plugin.id">
75
+ <component v-if="plugin.component" :is="plugin.component" v-bind="plugin.componentProps" />
76
+ </template>
77
+
78
+ <!-- Connection Line (dragging) -->
79
+ <svg v-if="isConnecting" class="yh-flow__connection-line">
80
+ <path
81
+ :d="connectionLinePath"
82
+ stroke="var(--flow-edge-animated-stroke, #409eff)"
83
+ stroke-width="2"
84
+ fill="none"
85
+ stroke-dasharray="5,5"
86
+ />
87
+ </svg>
88
+
89
+ <!-- Node Edit Panel -->
90
+ <!-- AI 工作流节点使用 AI 配置面板 -->
91
+ <AiNodeEditPanel
92
+ v-if="editingNode?.type?.startsWith('ai-')"
93
+ :node="editingNode"
94
+ :visible="showNodeEditPanel"
95
+ @update="handleNodeEditUpdate"
96
+ @close="closeNodeEditPanel"
97
+ />
98
+ <!-- 普通节点使用基础编辑面板 -->
99
+ <NodeEditPanel
100
+ v-else
101
+ :node="editingNode"
102
+ :visible="showNodeEditPanel"
103
+ @update="handleNodeEditUpdate"
104
+ @close="closeNodeEditPanel"
105
+ />
106
+
107
+ <!-- Edge Edit Panel -->
108
+ <EdgeEditPanel
109
+ :edge="editingEdge"
110
+ :visible="showEdgeEditPanel"
111
+ :edge-types="edgeTypes"
112
+ @update="handleEdgeEditUpdate"
113
+ @close="closeEdgeEditPanel"
114
+ />
115
+ </div>
116
+ </template>
117
+
118
+ <script setup>
119
+ import { ref, computed, watch, onMounted, onBeforeUnmount, shallowRef } from "vue";
120
+ if (typeof window !== "undefined") window.__YH_FLOW_VERSION__ = "1.0.1";
121
+ import EdgeRenderer from "./renderer/EdgeRenderer.vue";
122
+ import EdgeHandlesRenderer from "./renderer/EdgeHandlesRenderer.vue";
123
+ import NodeRenderer from "./renderer/NodeRenderer.vue";
124
+ import SelectionBox from "./renderer/SelectionBox.vue";
125
+ import NodeEditPanel from "./components/NodeEditPanel.vue";
126
+ import AiNodeEditPanel from "./components/AiNodeEditPanel.vue";
127
+ import EdgeEditPanel from "./components/EdgeEditPanel.vue";
128
+ import {
129
+ createGridPlugin,
130
+ createMiniMapPlugin,
131
+ createControlsPlugin,
132
+ createSnapPlugin,
133
+ createExportPlugin,
134
+ createLayoutPlugin
135
+ } from "./plugins/plugins";
136
+ import { useViewport } from "./core/useViewport";
137
+ import { useNodes } from "./core/useNodes";
138
+ import { useEdges } from "./core/useEdges";
139
+ import { useSelection } from "./core/useSelection";
140
+ import { useHistory } from "./core/useHistory";
141
+ import { useKeyboard } from "./core/useKeyboard";
142
+ import { useAlignment } from "./core/useAlignment";
143
+ import { getEdgePath, getHandlePosition } from "./utils/edge";
144
+ import { screenToCanvas, canvasToScreen } from "./utils/transform";
145
+ import { isValidConnection, detectCycles } from "./utils/validation";
146
+ import {
147
+ createNodeFromTemplate,
148
+ isNestedNode,
149
+ getNodeChildren,
150
+ getNodeParent,
151
+ exportFlowData,
152
+ importFlowData
153
+ } from "./utils/custom-types";
154
+ import { provideFlowContext } from "./core/FlowContext";
155
+ import { createEventBus } from "./utils/event-bus";
156
+ import { PluginManager } from "./plugins/plugin";
157
+ const validateConnection = (sourceNode, targetNode, connection) => {
158
+ const basicResult = isValidConnection(sourceNode, targetNode, connection);
159
+ if (!basicResult.isValid) {
160
+ return basicResult;
161
+ }
162
+ if (props.connectionValidator && !props.connectionValidator(connection)) {
163
+ return { isValid: false, message: "Connection not allowed by custom validator" };
164
+ }
165
+ if (!props.noCycleValidation) {
166
+ const wouldCreateCycle = detectCycles(edgesRef.value, {
167
+ source: connection.source,
168
+ target: connection.target
169
+ });
170
+ if (wouldCreateCycle) {
171
+ return { isValid: false, message: "Connection would create a cycle" };
172
+ }
173
+ }
174
+ return { isValid: true };
175
+ };
176
+ const props = defineProps({
177
+ nodes: { type: Array, required: false, default: () => [] },
178
+ edges: { type: Array, required: false, default: () => [] },
179
+ modelValue: { type: Object, required: false, default: () => ({ x: 0, y: 0, zoom: 1 }) },
180
+ minZoom: { type: Number, required: false, default: 0.1 },
181
+ maxZoom: { type: Number, required: false, default: 2 },
182
+ zoomStep: { type: Number, required: false, default: 0.1 },
183
+ nodesDraggable: { type: Boolean, required: false, default: true },
184
+ edgesConnectable: { type: Boolean, required: false, default: true },
185
+ selectable: { type: Boolean, required: false, default: true },
186
+ background: { type: String, required: false, default: "none" },
187
+ backgroundColor: { type: String, required: false, default: "transparent" },
188
+ gridSize: { type: Number, required: false, default: 20 },
189
+ snapToGrid: { type: Boolean, required: false, default: false },
190
+ snapGrid: { type: Array, required: false, default: () => [20, 20] },
191
+ readonly: { type: Boolean, required: false, default: false },
192
+ showControls: { type: Boolean, required: false, default: false },
193
+ showMinimap: { type: Boolean, required: false, default: false },
194
+ minimapNodeColor: { type: String, required: false, default: "#cbd5e1" },
195
+ history: { type: Boolean, required: false, default: false },
196
+ maxHistory: { type: Number, required: false, default: 50 },
197
+ keyboardShortcuts: { type: Boolean, required: false, default: true },
198
+ connectionValidator: { type: Function, required: false, default: void 0 },
199
+ noCycleValidation: { type: Boolean, required: false, default: false },
200
+ showAlignmentLines: { type: Boolean, required: false, default: false },
201
+ snapThreshold: { type: Number, required: false, default: 5 },
202
+ customNodeTemplates: { type: Object, required: false, default: () => ({}) },
203
+ nodeTypes: { type: Object, required: false, default: () => ({}) },
204
+ edgeTypes: { type: Object, required: false, default: () => ({}) },
205
+ interactiveMinimap: { type: Boolean, required: false, default: false },
206
+ showLayoutControls: { type: Boolean, required: false, default: false },
207
+ layoutType: { type: String, required: false, default: "none" },
208
+ layoutDirection: { type: String, required: false, default: "TB" },
209
+ enableExport: { type: Boolean, required: false, default: false },
210
+ exportFileName: { type: String, required: false, default: "flow-chart" }
211
+ });
212
+ const emit = defineEmits(["update:modelValue", "update:nodes", "update:edges", "nodeClick", "nodeDblClick", "nodeDragStart", "nodeDrag", "nodeDragEnd", "nodeContextMenu", "edgeClick", "edgeDblClick", "edgeContextMenu", "edgeConnect", "selectionChange", "historyChange", "viewportChange", "edgeUpdate"]);
213
+ const containerRef = ref();
214
+ const containerWidth = ref(800);
215
+ const containerHeight = ref(600);
216
+ const nodesRef = ref(props.nodes || []);
217
+ const edgesRef = ref(props.edges || []);
218
+ const viewportRef = shallowRef(props.modelValue || { x: 0, y: 0, zoom: 1 });
219
+ const readonly = ref(props.readonly || false);
220
+ const eventBus = createEventBus();
221
+ const pluginManager = new PluginManager();
222
+ const snapThreshold = ref(props.snapThreshold ?? 10);
223
+ const viewport = useViewport(viewportRef, {
224
+ minZoom: props.minZoom || 0.1,
225
+ maxZoom: props.maxZoom || 5,
226
+ zoomStep: props.zoomStep || 0.1
227
+ });
228
+ const registeredPlugins = ref([]);
229
+ const uiPlugins = computed(
230
+ () => registeredPlugins.value.filter((p) => !p.id.includes("minimap") && !p.id.includes("controls"))
231
+ );
232
+ const overlayPlugins = computed(
233
+ () => registeredPlugins.value.filter((p) => p.id.includes("minimap") || p.id.includes("controls"))
234
+ );
235
+ const usePlugin = (plugin) => {
236
+ pluginManager.register(plugin);
237
+ registeredPlugins.value = pluginManager.getPlugins();
238
+ };
239
+ const removePlugin = (pluginId) => {
240
+ pluginManager.unregister(pluginId);
241
+ registeredPlugins.value = pluginManager.getPlugins();
242
+ };
243
+ const nodesManager = useNodes(viewportRef, {
244
+ nodes: nodesRef,
245
+ snapToGrid: props.snapToGrid || false,
246
+ snapGrid: props.snapGrid || [15, 15]
247
+ });
248
+ const edgesManager = useEdges({
249
+ edges: edgesRef,
250
+ nodes: nodesRef
251
+ });
252
+ const selectionManager = useSelection({
253
+ nodes: nodesRef,
254
+ edges: edgesRef
255
+ });
256
+ const historyManager = useHistory(nodesRef, edgesRef, {
257
+ maxHistory: props.maxHistory || 50,
258
+ onHistoryChange: (canUndo, canRedo) => {
259
+ emit("historyChange", { canUndo, canRedo });
260
+ }
261
+ });
262
+ const alignmentManager = useAlignment({
263
+ nodes: nodesRef,
264
+ snapThreshold: snapThreshold.value
265
+ });
266
+ const visibleNodes = computed(() => {
267
+ if (!containerRef.value) return nodesRef.value;
268
+ const padding = 100;
269
+ const visibleBounds = {
270
+ x: -viewportRef.value.x / viewportRef.value.zoom - padding,
271
+ y: -viewportRef.value.y / viewportRef.value.zoom - padding,
272
+ width: containerWidth.value / viewportRef.value.zoom + padding * 2,
273
+ height: containerHeight.value / viewportRef.value.zoom + padding * 2
274
+ };
275
+ return nodesRef.value.filter((node) => {
276
+ const width = node.width || 200;
277
+ const height = node.height || 50;
278
+ return !(node.position.x + width < visibleBounds.x || node.position.x > visibleBounds.x + visibleBounds.width || node.position.y + height < visibleBounds.y || node.position.y > visibleBounds.y + visibleBounds.height);
279
+ });
280
+ });
281
+ const contentStyle = computed(() => ({
282
+ transform: `translate(${viewportRef.value.x}px, ${viewportRef.value.y}px) scale(${viewportRef.value.zoom})`,
283
+ transformOrigin: "0 0"
284
+ }));
285
+ const isPanning = ref(false);
286
+ const panStart = ref({ x: 0, y: 0 });
287
+ const isSelecting = ref(false);
288
+ const draggingNodeId = ref(null);
289
+ const draggingPosition = ref(null);
290
+ const isConnecting = ref(false);
291
+ const connectionStart = ref(null);
292
+ const connectionEnd = ref({ x: 0, y: 0 });
293
+ const updatingEdge = ref(null);
294
+ const showNodeEditPanel = ref(false);
295
+ const editingNode = ref(null);
296
+ const showEdgeEditPanel = ref(false);
297
+ const editingEdge = ref(null);
298
+ const connectingEdge = computed(() => {
299
+ if (!isConnecting.value || !connectionStart.value) return null;
300
+ return {
301
+ path: connectionLinePath.value,
302
+ tx: connectionEnd.value.x,
303
+ ty: connectionEnd.value.y
304
+ };
305
+ });
306
+ const connectionLinePath = computed(() => {
307
+ if (!connectionStart.value) return "";
308
+ return getEdgePath("bezier", {
309
+ sourceX: connectionStart.value.x * viewportRef.value.zoom + viewportRef.value.x,
310
+ sourceY: connectionStart.value.y * viewportRef.value.zoom + viewportRef.value.y,
311
+ targetX: connectionEnd.value.x,
312
+ targetY: connectionEnd.value.y,
313
+ sourcePosition: connectionStart.value.position,
314
+ targetPosition: "left"
315
+ });
316
+ });
317
+ const handleWheel = (event) => {
318
+ event.preventDefault();
319
+ const delta = event.deltaY > 0 ? 0.9 : 1.1;
320
+ const rect = containerRef.value?.getBoundingClientRect();
321
+ if (rect) {
322
+ viewport.zoomTo(viewportRef.value.zoom * delta, {
323
+ x: event.clientX - rect.left,
324
+ y: event.clientY - rect.top
325
+ });
326
+ }
327
+ };
328
+ const handlePaneMouseDown = (event) => {
329
+ const target = event.target;
330
+ if (!containerRef.value?.contains(target)) return;
331
+ if (target.closest(".yh-flow-node")) return;
332
+ if (target.closest(".yh-flow-handle")) return;
333
+ if (target.closest(".yh-flow-edge-group")) return;
334
+ if (target.closest(".yh-flow__connection-line")) return;
335
+ if (target.closest(".yh-flow-controls")) return;
336
+ if (target.closest(".yh-flow-minimap")) return;
337
+ const rect = containerRef.value?.getBoundingClientRect();
338
+ if (!rect) return;
339
+ const mouseX = event.clientX - rect.left;
340
+ const mouseY = event.clientY - rect.top;
341
+ if (event.altKey && props.selectable && !readonly.value) {
342
+ const canvasPos = {
343
+ x: (mouseX - viewportRef.value.x) / viewportRef.value.zoom,
344
+ y: (mouseY - viewportRef.value.y) / viewportRef.value.zoom
345
+ };
346
+ isSelecting.value = true;
347
+ selectionManager.startSelection(canvasPos.x, canvasPos.y);
348
+ selectionManager.clearSelection();
349
+ } else if (!readonly.value) {
350
+ isPanning.value = true;
351
+ panStart.value = { x: event.clientX, y: event.clientY };
352
+ }
353
+ };
354
+ const handleMouseMove = (event) => {
355
+ if (isPanning.value) {
356
+ const dx = event.clientX - panStart.value.x;
357
+ const dy = event.clientY - panStart.value.y;
358
+ viewport.pan(dx, dy);
359
+ panStart.value = { x: event.clientX, y: event.clientY };
360
+ }
361
+ if (isSelecting.value) {
362
+ const rect = containerRef.value?.getBoundingClientRect();
363
+ if (rect) {
364
+ const mouseX = event.clientX - rect.left;
365
+ const mouseY = event.clientY - rect.top;
366
+ const canvasPos = {
367
+ x: (mouseX - viewportRef.value.x) / viewportRef.value.zoom,
368
+ y: (mouseY - viewportRef.value.y) / viewportRef.value.zoom
369
+ };
370
+ selectionManager.updateSelection(canvasPos.x, canvasPos.y);
371
+ }
372
+ }
373
+ if (isConnecting.value) {
374
+ const rect = containerRef.value?.getBoundingClientRect();
375
+ if (rect) {
376
+ connectionEnd.value = {
377
+ x: event.clientX - rect.left,
378
+ y: event.clientY - rect.top
379
+ };
380
+ }
381
+ }
382
+ };
383
+ const handleMouseUp = (event) => {
384
+ isPanning.value = false;
385
+ if (isSelecting.value) {
386
+ isSelecting.value = false;
387
+ selectionManager.endSelection();
388
+ }
389
+ if (isConnecting.value && connectionStart.value) {
390
+ const rect = containerRef.value?.getBoundingClientRect();
391
+ if (rect) {
392
+ const mouseX = event.clientX - rect.left;
393
+ const mouseY = event.clientY - rect.top;
394
+ const canvasPos = {
395
+ x: (mouseX - viewportRef.value.x) / viewportRef.value.zoom,
396
+ y: (mouseY - viewportRef.value.y) / viewportRef.value.zoom
397
+ };
398
+ const targetNode = findTargetNode(canvasPos);
399
+ if (targetNode) {
400
+ const sourceNodeId = updatingEdge.value ? updatingEdge.value.handleType === "source" ? targetNode.id : updatingEdge.value.edge.source : connectionStart.value.nodeId;
401
+ const targetNodeId = updatingEdge.value ? updatingEdge.value.handleType === "target" ? targetNode.id : updatingEdge.value.edge.target : targetNode.id;
402
+ const sourceNode = nodesRef.value.find((n) => n.id === sourceNodeId);
403
+ const validationResult = validateConnection(
404
+ sourceNode,
405
+ nodesRef.value.find((n) => n.id === targetNodeId),
406
+ {
407
+ source: sourceNodeId,
408
+ target: targetNodeId,
409
+ sourceHandle: updatingEdge.value && updatingEdge.value.handleType === "source" ? void 0 : updatingEdge.value?.edge.sourceHandle || connectionStart.value?.handleId,
410
+ targetHandle: updatingEdge.value && updatingEdge.value.handleType === "target" ? void 0 : updatingEdge.value?.edge.targetHandle
411
+ }
412
+ );
413
+ if (!validationResult.isValid) {
414
+ console.warn("Invalid connection:", validationResult.message);
415
+ isConnecting.value = false;
416
+ connectionStart.value = null;
417
+ updatingEdge.value = null;
418
+ return;
419
+ }
420
+ if (updatingEdge.value) {
421
+ const { edge, handleType } = updatingEdge.value;
422
+ const connection = {
423
+ source: handleType === "source" ? targetNode.id : edge.source,
424
+ target: handleType === "target" ? targetNode.id : edge.target,
425
+ sourceHandle: handleType === "source" ? void 0 : edge.sourceHandle,
426
+ targetHandle: handleType === "target" ? void 0 : edge.targetHandle
427
+ };
428
+ edgesManager.updateEdge(edge.id, connection);
429
+ emit("edgeUpdate", { edge, connection });
430
+ eventBus.emit("edge:update", { edge, connection });
431
+ } else {
432
+ const newEdge = {
433
+ id: `edge-${Date.now()}`,
434
+ source: connectionStart.value.nodeId,
435
+ target: targetNode.id,
436
+ sourceHandle: connectionStart.value.handleId || void 0,
437
+ targetHandle: void 0,
438
+ type: "bezier"
439
+ };
440
+ edgesManager.addEdge(newEdge);
441
+ emit("edgeConnect", {
442
+ source: newEdge.source,
443
+ target: newEdge.target,
444
+ sourceHandle: newEdge.sourceHandle,
445
+ targetHandle: newEdge.targetHandle
446
+ });
447
+ eventBus.emit("edge:connect", {
448
+ connection: {
449
+ source: newEdge.source,
450
+ target: newEdge.target,
451
+ sourceHandle: newEdge.sourceHandle,
452
+ targetHandle: newEdge.targetHandle
453
+ }
454
+ });
455
+ }
456
+ }
457
+ }
458
+ isConnecting.value = false;
459
+ connectionStart.value = null;
460
+ updatingEdge.value = null;
461
+ }
462
+ };
463
+ const findTargetNode = (canvasPos) => {
464
+ for (const node of nodesRef.value) {
465
+ const width = node.width || 200;
466
+ const height = node.height || 50;
467
+ if (canvasPos.x >= node.position.x && canvasPos.x <= node.position.x + width && canvasPos.y >= node.position.y && canvasPos.y <= node.position.y + height) {
468
+ if (connectionStart.value && node.id !== connectionStart.value.nodeId) {
469
+ return node;
470
+ }
471
+ }
472
+ }
473
+ return null;
474
+ };
475
+ const handleNodeClick = (event, node) => {
476
+ const multi = event.shiftKey || event.metaKey || event.ctrlKey;
477
+ if (!multi) edgesManager.clearSelection();
478
+ nodesManager.selectNode(node.id, true, multi);
479
+ emit("nodeClick", { node, nativeEvent: event });
480
+ eventBus.emit("node:click", { node, nativeEvent: event });
481
+ };
482
+ const handleNodeSelectToggle = (nodeId) => {
483
+ const node = nodesRef.value.find((n) => n.id === nodeId);
484
+ if (node) {
485
+ node.selected = !node.selected;
486
+ }
487
+ };
488
+ const handleNodeDblClick = (event, node) => {
489
+ emit("nodeDblClick", { node, nativeEvent: event });
490
+ eventBus.emit("node:dblclick", { node, nativeEvent: event });
491
+ if (!readonly.value) {
492
+ showEdgeEditPanel.value = false;
493
+ editingNode.value = node;
494
+ showNodeEditPanel.value = true;
495
+ }
496
+ };
497
+ const handleNodeContextMenu = (event, node) => {
498
+ emit("nodeContextMenu", { node, nativeEvent: event });
499
+ eventBus.emit("node:contextmenu", { node, nativeEvent: event });
500
+ };
501
+ const handleNodeDragStart = (event, node) => {
502
+ historyManager.push({ nodes: nodesRef.value, edges: edgesRef.value });
503
+ draggingNodeId.value = node.id;
504
+ draggingPosition.value = { ...node.position };
505
+ emit("nodeDragStart", { node, nativeEvent: event });
506
+ eventBus.emit("node:dragstart", { node, nativeEvent: event });
507
+ };
508
+ const handleNodeDrag = (event, node, position) => {
509
+ const snappedPosition = alignmentManager.getAlignmentSnap(node.id, position);
510
+ nodesManager.updateNodePosition(node.id, snappedPosition, { dragging: true });
511
+ draggingPosition.value = snappedPosition;
512
+ emit("nodeDrag", { node, nativeEvent: event, position: snappedPosition });
513
+ eventBus.emit("node:drag", { node, nativeEvent: event, position: snappedPosition });
514
+ emit("update:nodes", nodesRef.value);
515
+ };
516
+ const handleNodeDragEnd = (event, node) => {
517
+ nodesManager.updateNodePosition(node.id, node.position, { dragging: false });
518
+ draggingNodeId.value = null;
519
+ draggingPosition.value = null;
520
+ emit("nodeDragEnd", { node, nativeEvent: event });
521
+ eventBus.emit("node:dragend", { node, nativeEvent: event });
522
+ emit("update:nodes", nodesRef.value);
523
+ emit("update:edges", edgesRef.value);
524
+ };
525
+ const handleEdgeClick = (event, edge) => {
526
+ console.log("Edge click:", edge.id);
527
+ event.stopPropagation();
528
+ if (!event.ctrlKey && !event.metaKey && !event.shiftKey) {
529
+ edgesRef.value.forEach((e) => {
530
+ if (e.id !== edge.id) e.selected = false;
531
+ });
532
+ }
533
+ edge.selected = !edge.selected;
534
+ emit("edgeClick", { edge, nativeEvent: event });
535
+ if (!readonly.value) {
536
+ showNodeEditPanel.value = false;
537
+ editingEdge.value = edge;
538
+ showEdgeEditPanel.value = true;
539
+ }
540
+ eventBus.emit("edge:click", { edge, nativeEvent: event });
541
+ };
542
+ const handleEdgeDblClick = (event, edge) => {
543
+ console.log("Edge dblclick:", edge.id);
544
+ emit("edgeDblClick", { edge, nativeEvent: event });
545
+ eventBus.emit("edge:dblclick", { edge, nativeEvent: event });
546
+ if (!readonly.value) {
547
+ showNodeEditPanel.value = false;
548
+ editingEdge.value = edge;
549
+ showEdgeEditPanel.value = true;
550
+ }
551
+ };
552
+ const handleEdgeContextMenu = (event, edge) => {
553
+ emit("edgeContextMenu", { edge, nativeEvent: event });
554
+ eventBus.emit("edge:contextmenu", { edge, nativeEvent: event });
555
+ };
556
+ const handleEdgeUpdateStart = (event, edge, handleType) => {
557
+ if (readonly.value) return;
558
+ const rect = containerRef.value?.getBoundingClientRect();
559
+ if (!rect) return;
560
+ updatingEdge.value = { edge, handleType };
561
+ const anchorNodeId = handleType === "source" ? edge.target : edge.source;
562
+ const anchorHandleId = handleType === "source" ? edge.targetHandle : edge.sourceHandle;
563
+ const node = nodesRef.value.find((n) => n.id === anchorNodeId);
564
+ if (!node) return;
565
+ const position = handleType === "source" ? anchorHandleId ?? "left" : anchorHandleId ?? "right";
566
+ const startPos = getHandlePosition(node, position, anchorHandleId);
567
+ isConnecting.value = true;
568
+ connectionStart.value = {
569
+ nodeId: anchorNodeId,
570
+ handleId: anchorHandleId || "",
571
+ handleType: handleType === "source" ? "target" : "source",
572
+ // 反转类型
573
+ position,
574
+ x: startPos.x,
575
+ y: startPos.y
576
+ };
577
+ connectionEnd.value = {
578
+ x: event.clientX - rect.left,
579
+ y: event.clientY - rect.top
580
+ };
581
+ };
582
+ const handleConnectStart = (event, nodeId, handleId, handleType) => {
583
+ const node = nodesRef.value.find((n) => n.id === nodeId);
584
+ if (!node) return;
585
+ const rect = containerRef.value?.getBoundingClientRect();
586
+ if (!rect) return;
587
+ const position = handleId || (handleType === "source" ? "right" : "left");
588
+ const startPos = getHandlePosition(node, position, handleId);
589
+ isConnecting.value = true;
590
+ connectionStart.value = {
591
+ nodeId,
592
+ handleId,
593
+ handleType,
594
+ position,
595
+ x: startPos.x,
596
+ y: startPos.y
597
+ };
598
+ connectionEnd.value = {
599
+ x: event.clientX - rect.left,
600
+ y: event.clientY - rect.top
601
+ };
602
+ };
603
+ const handleNodeEditUpdate = (updates) => {
604
+ if (editingNode.value) {
605
+ historyManager.push({ nodes: nodesRef.value, edges: edgesRef.value });
606
+ nodesManager.updateNode(editingNode.value.id, updates);
607
+ editingNode.value = nodesRef.value.find((n) => n.id === editingNode.value?.id) || null;
608
+ emit("update:nodes", nodesRef.value);
609
+ }
610
+ };
611
+ const closeNodeEditPanel = () => {
612
+ showNodeEditPanel.value = false;
613
+ editingNode.value = null;
614
+ };
615
+ const handleEdgeEditUpdate = (updates) => {
616
+ if (editingEdge.value) {
617
+ historyManager.push({ nodes: nodesRef.value, edges: edgesRef.value });
618
+ edgesManager.updateEdge(editingEdge.value.id, updates);
619
+ editingEdge.value = edgesRef.value.find((e) => e.id === editingEdge.value?.id) || null;
620
+ emit("update:edges", edgesRef.value);
621
+ }
622
+ };
623
+ const closeEdgeEditPanel = () => {
624
+ showEdgeEditPanel.value = false;
625
+ editingEdge.value = null;
626
+ };
627
+ const getNodes = () => nodesRef.value;
628
+ const getEdges = () => edgesRef.value;
629
+ const onEvent = (event, handler) => {
630
+ eventBus.on(event, handler);
631
+ };
632
+ const offEvent = (event, handler) => {
633
+ eventBus.off(event, handler);
634
+ };
635
+ const emitEvent = (event, payload) => {
636
+ eventBus.emit(event, payload);
637
+ };
638
+ const flowInstance = {
639
+ nodes: nodesRef,
640
+ edges: edgesRef,
641
+ viewport: viewportRef,
642
+ addNode: nodesManager.addNode,
643
+ removeNode: nodesManager.removeNode,
644
+ updateNode: nodesManager.updateNode,
645
+ getNode: nodesManager.getNode,
646
+ addEdge: edgesManager.addEdge,
647
+ removeEdge: edgesManager.removeEdge,
648
+ updateEdge: edgesManager.updateEdge,
649
+ getEdge: edgesManager.getEdge,
650
+ setViewport: (transform) => viewport.setViewport(transform.x, transform.y, transform.zoom),
651
+ fitView: (options) => viewport.fitView(
652
+ { width: containerWidth.value, height: containerHeight.value },
653
+ nodesRef.value,
654
+ options
655
+ ),
656
+ zoomIn: viewport.zoomIn,
657
+ zoomOut: viewport.zoomOut,
658
+ centerView: viewport.center,
659
+ selectNode: nodesManager.selectNode,
660
+ selectEdge: edgesManager.selectEdge,
661
+ clearSelection: selectionManager.clearSelection,
662
+ on: onEvent,
663
+ off: offEvent,
664
+ emit: emitEvent,
665
+ isValidConnection: (connection) => isValidConnection(
666
+ nodesRef.value.find((n) => n.id === connection.source),
667
+ nodesRef.value.find((n) => n.id === connection.target),
668
+ connection
669
+ ).isValid,
670
+ getNodes,
671
+ getEdges,
672
+ getViewport: () => viewportRef.value,
673
+ screenToCanvas: (x, y) => screenToCanvas(x, y, viewportRef.value),
674
+ canvasToScreen: (x, y) => canvasToScreen(x, y, viewportRef.value),
675
+ // ============================================
676
+ // New 5-star feature methods
677
+ // ============================================
678
+ createNodeFromTemplate: (type, id, position, overrides) => createNodeFromTemplate(type, id, position, overrides),
679
+ exportFlowData: (viewport2) => exportFlowData(nodesRef.value, edgesRef.value, viewport2),
680
+ importFlowData: (json) => importFlowData(json),
681
+ isNestedNode: (node) => isNestedNode(node),
682
+ getNodeChildren: (node) => getNodeChildren(node, nodesRef.value),
683
+ getNodeParent: (node) => getNodeParent(node, nodesRef.value),
684
+ get $el() {
685
+ return containerRef.value;
686
+ },
687
+ draggingNodeId,
688
+ draggingPosition,
689
+ isLocked: readonly,
690
+ setInteractive: (interactive) => {
691
+ readonly.value = !interactive;
692
+ },
693
+ usePlugin,
694
+ removePlugin,
695
+ // Placeholders for plugin methods to be exposed via defineExpose
696
+ exportJson: void 0,
697
+ exportImage: void 0,
698
+ applyLayout: void 0
699
+ };
700
+ provideFlowContext(flowInstance);
701
+ pluginManager.init(flowInstance);
702
+ defineExpose(flowInstance);
703
+ watch(
704
+ () => props.nodes,
705
+ (newNodes) => {
706
+ if (draggingNodeId.value) return;
707
+ nodesRef.value = newNodes || [];
708
+ },
709
+ { deep: true }
710
+ );
711
+ watch(
712
+ () => props.edges,
713
+ (newEdges) => {
714
+ edgesRef.value = newEdges || [];
715
+ },
716
+ { deep: true }
717
+ );
718
+ const prevSelectedNodeIds = ref(/* @__PURE__ */ new Set());
719
+ const prevSelectedEdgeIds = ref(/* @__PURE__ */ new Set());
720
+ watch(
721
+ [nodesRef, edgesRef],
722
+ ([nodes, edges]) => {
723
+ const selectedNodes = nodes.filter((n) => n.selected);
724
+ const selectedEdges = edges.filter((e) => e.selected);
725
+ const nextNodeIds = new Set(selectedNodes.map((n) => n.id));
726
+ const nextEdgeIds = new Set(selectedEdges.map((e) => e.id));
727
+ for (const id of nextNodeIds) {
728
+ if (!prevSelectedNodeIds.value.has(id)) {
729
+ const node = nodes.find((n) => n.id === id);
730
+ if (node) eventBus.emit("node:selected", { node });
731
+ }
732
+ }
733
+ for (const id of prevSelectedNodeIds.value) {
734
+ if (!nextNodeIds.has(id)) {
735
+ const node = nodes.find((n) => n.id === id);
736
+ if (node) eventBus.emit("node:unselected", { node });
737
+ }
738
+ }
739
+ for (const id of nextEdgeIds) {
740
+ if (!prevSelectedEdgeIds.value.has(id)) {
741
+ const edge = edges.find((e) => e.id === id);
742
+ if (edge) eventBus.emit("edge:selected", { edge });
743
+ }
744
+ }
745
+ for (const id of prevSelectedEdgeIds.value) {
746
+ if (!nextEdgeIds.has(id)) {
747
+ const edge = edges.find((e) => e.id === id);
748
+ if (edge) eventBus.emit("edge:unselected", { edge });
749
+ }
750
+ }
751
+ eventBus.emit("selection:change", { selectedNodes, selectedEdges });
752
+ emit("selectionChange", { selectedNodes, selectedEdges });
753
+ emit("update:nodes", nodes);
754
+ emit("update:edges", edges);
755
+ prevSelectedNodeIds.value = nextNodeIds;
756
+ prevSelectedEdgeIds.value = nextEdgeIds;
757
+ },
758
+ { deep: true }
759
+ );
760
+ watch(
761
+ viewportRef,
762
+ (newViewport) => {
763
+ emit("update:modelValue", newViewport);
764
+ emit("viewportChange", newViewport);
765
+ eventBus.emit("viewport:change", { transform: newViewport });
766
+ },
767
+ { deep: true }
768
+ );
769
+ let handleKeyDown;
770
+ onMounted(() => {
771
+ document.addEventListener("mousemove", handleMouseMove);
772
+ document.addEventListener("mouseup", handleMouseUp);
773
+ if (containerRef.value) {
774
+ containerWidth.value = containerRef.value.clientWidth;
775
+ containerHeight.value = containerRef.value.clientHeight;
776
+ const resizeObserver = new ResizeObserver((entries) => {
777
+ for (const entry of entries) {
778
+ containerWidth.value = entry.contentRect.width;
779
+ containerHeight.value = entry.contentRect.height;
780
+ }
781
+ });
782
+ resizeObserver.observe(containerRef.value);
783
+ }
784
+ if (props.background && props.background !== "none") {
785
+ usePlugin(
786
+ createGridPlugin({
787
+ type: props.background === "dots" ? "dots" : "grid",
788
+ color: props.backgroundColor,
789
+ gap: props.gridSize
790
+ })
791
+ );
792
+ }
793
+ if (props.showControls) {
794
+ usePlugin(createControlsPlugin({}));
795
+ }
796
+ if (props.showMinimap) {
797
+ usePlugin(
798
+ createMiniMapPlugin({
799
+ nodeColor: props.minimapNodeColor ? () => props.minimapNodeColor : void 0,
800
+ interactive: props.interactiveMinimap,
801
+ showLayoutControls: props.showLayoutControls,
802
+ layoutType: props.layoutType,
803
+ layoutDirection: props.layoutDirection
804
+ })
805
+ );
806
+ }
807
+ if (props.showAlignmentLines) {
808
+ usePlugin(
809
+ createSnapPlugin({
810
+ showAlignmentLines: true,
811
+ snapThreshold: props.snapThreshold
812
+ })
813
+ );
814
+ }
815
+ if (props.enableExport) {
816
+ usePlugin(
817
+ createExportPlugin({
818
+ fileName: props.exportFileName,
819
+ enabled: true
820
+ })
821
+ );
822
+ }
823
+ if (props.layoutType && props.layoutType !== "none") {
824
+ usePlugin(
825
+ createLayoutPlugin({
826
+ type: props.layoutType,
827
+ direction: props.layoutDirection
828
+ })
829
+ );
830
+ }
831
+ watch(
832
+ () => [props.background, props.backgroundColor, props.gridSize],
833
+ ([bg, color, gap]) => {
834
+ removePlugin("grid");
835
+ if (bg && bg !== "none") {
836
+ usePlugin(
837
+ createGridPlugin({
838
+ type: bg === "dots" ? "dots" : "grid",
839
+ color,
840
+ gap: gap || 20
841
+ })
842
+ );
843
+ }
844
+ }
845
+ );
846
+ watch(
847
+ () => props.showControls,
848
+ (val) => {
849
+ removePlugin("controls");
850
+ if (val) usePlugin(createControlsPlugin({}));
851
+ }
852
+ );
853
+ watch(
854
+ () => [
855
+ props.showMinimap,
856
+ props.minimapNodeColor,
857
+ props.interactiveMinimap,
858
+ props.showLayoutControls,
859
+ props.layoutType,
860
+ props.layoutDirection
861
+ ],
862
+ ([show, color, interactive, showLayout, type, dir]) => {
863
+ removePlugin("minimap");
864
+ if (show) {
865
+ usePlugin(
866
+ createMiniMapPlugin({
867
+ nodeColor: color ? () => color : void 0,
868
+ interactive,
869
+ showLayoutControls: showLayout,
870
+ layoutType: type,
871
+ layoutDirection: dir
872
+ })
873
+ );
874
+ }
875
+ }
876
+ );
877
+ watch(
878
+ () => [props.showAlignmentLines, props.snapThreshold],
879
+ ([show, threshold]) => {
880
+ removePlugin("snap");
881
+ if (show) {
882
+ usePlugin(
883
+ createSnapPlugin({
884
+ showAlignmentLines: true,
885
+ snapThreshold: threshold || 10
886
+ })
887
+ );
888
+ }
889
+ }
890
+ );
891
+ watch(
892
+ () => [props.enableExport, props.exportFileName],
893
+ ([enable, fileName]) => {
894
+ removePlugin("export");
895
+ if (enable) {
896
+ usePlugin(
897
+ createExportPlugin({
898
+ fileName,
899
+ enabled: true
900
+ })
901
+ );
902
+ }
903
+ }
904
+ );
905
+ watch(
906
+ () => [props.layoutType, props.layoutDirection],
907
+ ([type, dir]) => {
908
+ removePlugin("layout");
909
+ if (type && type !== "none") {
910
+ usePlugin(
911
+ createLayoutPlugin({
912
+ type,
913
+ direction: dir
914
+ })
915
+ );
916
+ }
917
+ }
918
+ );
919
+ if (props.keyboardShortcuts) {
920
+ const keyboard = useKeyboard({
921
+ enabled: true,
922
+ onDelete: () => {
923
+ const selectedNodes = nodesRef.value.filter((n) => n.selected);
924
+ const selectedEdges = edgesRef.value.filter((e) => e.selected);
925
+ selectedNodes.forEach((node) => nodesManager.removeNode(node.id));
926
+ selectedEdges.forEach((edge) => edgesManager.removeEdge(edge.id));
927
+ emit("update:nodes", nodesRef.value);
928
+ emit("update:edges", edgesRef.value);
929
+ },
930
+ onUndo: () => historyManager.undo(),
931
+ onRedo: () => historyManager.redo(),
932
+ onSelectAll: () => {
933
+ nodesRef.value.forEach((n) => {
934
+ n.selected = true;
935
+ });
936
+ edgesRef.value.forEach((e) => {
937
+ e.selected = true;
938
+ });
939
+ },
940
+ onEscape: () => selectionManager.clearSelection()
941
+ });
942
+ handleKeyDown = keyboard.handleKeyDown;
943
+ document.addEventListener("keydown", handleKeyDown);
944
+ }
945
+ });
946
+ onBeforeUnmount(() => {
947
+ if (props.keyboardShortcuts && handleKeyDown) {
948
+ document.removeEventListener("keydown", handleKeyDown);
949
+ }
950
+ document.removeEventListener("mousemove", handleMouseMove);
951
+ document.removeEventListener("mouseup", handleMouseUp);
952
+ pluginManager.destroyAll();
953
+ eventBus.clear();
954
+ });
955
+ </script>
956
+
957
+ <style scoped>
958
+ .yh-flow{background:var(--flow-background-color,#f8f9fa);cursor:grab;height:100%;overflow:hidden;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.yh-flow.is-panning{cursor:grabbing}.yh-flow.is-readonly{cursor:default}.yh-flow__content{height:100%;left:0;pointer-events:none;position:absolute;top:0;width:100%}.yh-flow__content>*{pointer-events:auto}.yh-flow__connection-line{height:100%;left:0;overflow:visible;pointer-events:none;position:absolute;top:0;width:100%;z-index:1000}
959
+ </style>