@logicflow/core 2.2.0 → 2.2.2

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 (361) hide show
  1. package/dist/docs/api/logicflow-constructor/index.en.md +106 -0
  2. package/dist/docs/api/logicflow-constructor/index.zh.md +106 -0
  3. package/dist/docs/api/logicflow-constructor/use.en.md +61 -0
  4. package/dist/docs/api/logicflow-constructor/use.zh.md +61 -0
  5. package/dist/docs/api/logicflow-instance/canvas.en.md +197 -0
  6. package/dist/docs/api/logicflow-instance/canvas.zh.md +199 -0
  7. package/dist/docs/api/logicflow-instance/edge.en.md +273 -0
  8. package/dist/docs/api/logicflow-instance/edge.zh.md +273 -0
  9. package/dist/docs/api/logicflow-instance/edit-config.en.md +59 -0
  10. package/dist/docs/api/logicflow-instance/edit-config.zh.md +59 -0
  11. package/dist/docs/api/logicflow-instance/element.en.md +375 -0
  12. package/dist/docs/api/logicflow-instance/element.zh.md +379 -0
  13. package/dist/docs/api/logicflow-instance/event.en.md +326 -0
  14. package/dist/docs/api/logicflow-instance/event.zh.md +406 -0
  15. package/dist/docs/api/logicflow-instance/history.en.md +38 -0
  16. package/dist/docs/api/logicflow-instance/history.zh.md +38 -0
  17. package/dist/docs/api/logicflow-instance/index.en.md +41 -0
  18. package/dist/docs/api/logicflow-instance/index.zh.md +41 -0
  19. package/dist/docs/api/logicflow-instance/node.en.md +308 -0
  20. package/dist/docs/api/logicflow-instance/node.zh.md +308 -0
  21. package/dist/docs/api/logicflow-instance/register.en.md +76 -0
  22. package/dist/docs/api/logicflow-instance/register.zh.md +76 -0
  23. package/dist/docs/api/logicflow-instance/render-and-data.en.md +179 -0
  24. package/dist/docs/api/logicflow-instance/render-and-data.zh.md +181 -0
  25. package/dist/docs/api/logicflow-instance/text.en.md +60 -0
  26. package/dist/docs/api/logicflow-instance/text.zh.md +60 -0
  27. package/dist/docs/api/logicflow-instance/theme.en.md +179 -0
  28. package/dist/docs/api/logicflow-instance/theme.zh.md +179 -0
  29. package/dist/docs/api/runtime-model/edgeModel.en.md +29 -0
  30. package/dist/docs/api/runtime-model/edgeModel.zh.md +325 -0
  31. package/dist/docs/api/runtime-model/graphModel.en.md +275 -0
  32. package/dist/docs/api/runtime-model/graphModel.zh.md +1153 -0
  33. package/dist/docs/api/runtime-model/nodeModel.en.md +37 -0
  34. package/dist/docs/api/runtime-model/nodeModel.zh.md +644 -0
  35. package/dist/docs/api/type/MainTypes.en.md +598 -0
  36. package/dist/docs/api/type/MainTypes.zh.md +867 -0
  37. package/dist/docs/api/type/Theme.en.md +187 -0
  38. package/dist/docs/api/type/Theme.zh.md +187 -0
  39. package/dist/docs/api/type/canvas-types.en.md +25 -0
  40. package/dist/docs/api/type/canvas-types.zh.md +25 -0
  41. package/dist/docs/api/type/index.en.md +96 -0
  42. package/dist/docs/api/type/index.zh.md +99 -0
  43. package/dist/docs/api/type/node-types.en.md +21 -0
  44. package/dist/docs/api/type/node-types.zh.md +21 -0
  45. package/dist/docs/api/type/plugin-types.en.md +24 -0
  46. package/dist/docs/api/type/plugin-types.zh.md +24 -0
  47. package/dist/docs/index.md +11 -0
  48. package/dist/docs/tutorial/about.en.md +38 -0
  49. package/dist/docs/tutorial/about.zh.md +65 -0
  50. package/dist/docs/tutorial/advanced/dnd.en.md +62 -0
  51. package/dist/docs/tutorial/advanced/dnd.zh.md +52 -0
  52. package/dist/docs/tutorial/advanced/edge.en.md +64 -0
  53. package/dist/docs/tutorial/advanced/edge.zh.md +66 -0
  54. package/dist/docs/tutorial/advanced/keyboard.en.md +70 -0
  55. package/dist/docs/tutorial/advanced/keyboard.zh.md +67 -0
  56. package/dist/docs/tutorial/advanced/node.en.md +338 -0
  57. package/dist/docs/tutorial/advanced/node.zh.md +338 -0
  58. package/dist/docs/tutorial/advanced/react.en.md +106 -0
  59. package/dist/docs/tutorial/advanced/react.zh.md +114 -0
  60. package/dist/docs/tutorial/advanced/silent-mode.en.md +75 -0
  61. package/dist/docs/tutorial/advanced/silent-mode.zh.md +71 -0
  62. package/dist/docs/tutorial/advanced/snapline.en.md +54 -0
  63. package/dist/docs/tutorial/advanced/vue.en.md +249 -0
  64. package/dist/docs/tutorial/advanced/vue.zh.md +248 -0
  65. package/dist/docs/tutorial/ai.en.md +64 -0
  66. package/dist/docs/tutorial/ai.zh.md +64 -0
  67. package/dist/docs/tutorial/basic/background.en.md +50 -0
  68. package/dist/docs/tutorial/basic/canvas.en.md +164 -0
  69. package/dist/docs/tutorial/basic/canvas.zh.md +183 -0
  70. package/dist/docs/tutorial/basic/class.en.md +106 -0
  71. package/dist/docs/tutorial/basic/class.zh.md +103 -0
  72. package/dist/docs/tutorial/basic/edge.en.md +151 -0
  73. package/dist/docs/tutorial/basic/edge.zh.md +152 -0
  74. package/dist/docs/tutorial/basic/event.en.md +70 -0
  75. package/dist/docs/tutorial/basic/event.zh.md +66 -0
  76. package/dist/docs/tutorial/basic/grid.en.md +77 -0
  77. package/dist/docs/tutorial/basic/node.en.md +358 -0
  78. package/dist/docs/tutorial/basic/node.zh.md +318 -0
  79. package/dist/docs/tutorial/basic/theme.en.md +154 -0
  80. package/dist/docs/tutorial/basic/theme.zh.md +157 -0
  81. package/dist/docs/tutorial/extension/adapter.en.md +446 -0
  82. package/dist/docs/tutorial/extension/adapter.zh.md +429 -0
  83. package/dist/docs/tutorial/extension/bpmn-element.en.md +1427 -0
  84. package/dist/docs/tutorial/extension/bpmn-element.zh.md +1472 -0
  85. package/dist/docs/tutorial/extension/control.en.md +117 -0
  86. package/dist/docs/tutorial/extension/control.zh.md +118 -0
  87. package/dist/docs/tutorial/extension/curved-edge.en.md +46 -0
  88. package/dist/docs/tutorial/extension/curved-edge.zh.md +46 -0
  89. package/dist/docs/tutorial/extension/custom.en.md +142 -0
  90. package/dist/docs/tutorial/extension/custom.zh.md +138 -0
  91. package/dist/docs/tutorial/extension/dnd-panel.en.md +109 -0
  92. package/dist/docs/tutorial/extension/dnd-panel.zh.md +109 -0
  93. package/dist/docs/tutorial/extension/dynamic-group.en.md +606 -0
  94. package/dist/docs/tutorial/extension/dynamic-group.zh.md +606 -0
  95. package/dist/docs/tutorial/extension/group.en.md +217 -0
  96. package/dist/docs/tutorial/extension/group.zh.md +209 -0
  97. package/dist/docs/tutorial/extension/highlight.en.md +50 -0
  98. package/dist/docs/tutorial/extension/highlight.zh.md +50 -0
  99. package/dist/docs/tutorial/extension/insert-node-in-polyline.en.md +52 -0
  100. package/dist/docs/tutorial/extension/insert-node-in-polyline.zh.md +47 -0
  101. package/dist/docs/tutorial/extension/intro.en.md +72 -0
  102. package/dist/docs/tutorial/extension/intro.zh.md +95 -0
  103. package/dist/docs/tutorial/extension/label.en.md +136 -0
  104. package/dist/docs/tutorial/extension/label.zh.md +135 -0
  105. package/dist/docs/tutorial/extension/layout.en.md +156 -0
  106. package/dist/docs/tutorial/extension/layout.zh.md +156 -0
  107. package/dist/docs/tutorial/extension/menu.en.md +319 -0
  108. package/dist/docs/tutorial/extension/menu.zh.md +377 -0
  109. package/dist/docs/tutorial/extension/minimap.en.md +164 -0
  110. package/dist/docs/tutorial/extension/minimap.zh.md +180 -0
  111. package/dist/docs/tutorial/extension/node-resize.en.md +199 -0
  112. package/dist/docs/tutorial/extension/node-resize.zh.md +221 -0
  113. package/dist/docs/tutorial/extension/pool.en.md +227 -0
  114. package/dist/docs/tutorial/extension/pool.zh.md +227 -0
  115. package/dist/docs/tutorial/extension/proximity-connect.en.md +104 -0
  116. package/dist/docs/tutorial/extension/proximity-connect.zh.md +107 -0
  117. package/dist/docs/tutorial/extension/selection.en.md +166 -0
  118. package/dist/docs/tutorial/extension/selection.zh.md +150 -0
  119. package/dist/docs/tutorial/extension/snapshot.en.md +276 -0
  120. package/dist/docs/tutorial/extension/snapshot.zh.md +276 -0
  121. package/dist/docs/tutorial/get-started.en.md +501 -0
  122. package/dist/docs/tutorial/get-started.zh.md +139 -0
  123. package/dist/docs/tutorial/update.en.md +213 -0
  124. package/dist/docs/tutorial/update.zh.md +212 -0
  125. package/dist/index.css +3 -2
  126. package/dist/index.min.js +1 -1
  127. package/dist/index.min.js.map +1 -1
  128. package/es/LogicFlow.d.ts +9 -0
  129. package/es/LogicFlow.js +0 -1
  130. package/es/constant/index.d.ts +1 -1
  131. package/es/constant/index.js +1 -1
  132. package/es/constant/theme.d.ts +136 -0
  133. package/es/constant/theme.js +680 -0
  134. package/es/index.css +3 -2
  135. package/es/model/GraphModel.d.ts +10 -2
  136. package/es/model/GraphModel.js +48 -14
  137. package/es/model/TransformModel.js +9 -9
  138. package/es/model/edge/BaseEdgeModel.js +7 -2
  139. package/es/model/edge/PolylineEdgeModel.d.ts +7 -0
  140. package/es/model/edge/PolylineEdgeModel.js +136 -7
  141. package/es/model/node/BaseNodeModel.d.ts +12 -1
  142. package/es/model/node/BaseNodeModel.js +9 -2
  143. package/es/model/node/HtmlNodeModel.d.ts +12 -0
  144. package/es/model/node/HtmlNodeModel.js +19 -0
  145. package/es/model/node/PolygonNodeModel.js +3 -3
  146. package/es/options.d.ts +4 -2
  147. package/es/style/index.css +3 -2
  148. package/es/style/index.less +3 -2
  149. package/es/style/raw.d.ts +1 -1
  150. package/es/style/raw.js +1 -1
  151. package/es/tool/MultipleSelectTool.js +10 -5
  152. package/es/util/drag.js +0 -1
  153. package/es/util/edge.d.ts +40 -1
  154. package/es/util/edge.js +43 -9
  155. package/es/util/geometry.d.ts +8 -0
  156. package/es/util/geometry.js +79 -0
  157. package/es/util/theme.d.ts +2 -65
  158. package/es/util/theme.js +4 -281
  159. package/es/view/Anchor.d.ts +1 -0
  160. package/es/view/Anchor.js +24 -21
  161. package/es/view/Control.d.ts +5 -0
  162. package/es/view/Control.js +44 -57
  163. package/es/view/edge/BaseEdge.js +9 -0
  164. package/es/view/edge/PolylineEdge.js +13 -2
  165. package/es/view/node/BaseNode.d.ts +1 -0
  166. package/es/view/node/BaseNode.js +23 -11
  167. package/es/view/node/HtmlNode.js +2 -4
  168. package/es/view/overlay/CanvasOverlay.js +5 -2
  169. package/es/view/overlay/Grid.d.ts +12 -1
  170. package/es/view/overlay/Grid.js +85 -23
  171. package/es/view/overlay/OutlineOverlay.d.ts +1 -0
  172. package/es/view/overlay/OutlineOverlay.js +18 -17
  173. package/es/view/overlay/gridConfig.d.ts +46 -0
  174. package/es/view/overlay/gridConfig.js +99 -0
  175. package/es/view/shape/Polygon.d.ts +0 -7
  176. package/es/view/shape/Polygon.js +12 -43
  177. package/lib/LogicFlow.d.ts +9 -0
  178. package/lib/LogicFlow.js +0 -1
  179. package/lib/constant/index.d.ts +1 -1
  180. package/lib/constant/index.js +16 -2
  181. package/lib/constant/theme.d.ts +136 -0
  182. package/lib/constant/theme.js +683 -0
  183. package/lib/index.css +3 -2
  184. package/lib/model/GraphModel.d.ts +10 -2
  185. package/lib/model/GraphModel.js +49 -15
  186. package/lib/model/TransformModel.js +9 -9
  187. package/lib/model/edge/BaseEdgeModel.js +7 -2
  188. package/lib/model/edge/PolylineEdgeModel.d.ts +7 -0
  189. package/lib/model/edge/PolylineEdgeModel.js +136 -7
  190. package/lib/model/node/BaseNodeModel.d.ts +12 -1
  191. package/lib/model/node/BaseNodeModel.js +9 -2
  192. package/lib/model/node/HtmlNodeModel.d.ts +12 -0
  193. package/lib/model/node/HtmlNodeModel.js +19 -0
  194. package/lib/model/node/PolygonNodeModel.js +3 -3
  195. package/lib/options.d.ts +4 -2
  196. package/lib/style/index.css +3 -2
  197. package/lib/style/index.less +3 -2
  198. package/lib/style/raw.d.ts +1 -1
  199. package/lib/style/raw.js +1 -1
  200. package/lib/tool/MultipleSelectTool.js +10 -5
  201. package/lib/util/drag.js +0 -1
  202. package/lib/util/edge.d.ts +40 -1
  203. package/lib/util/edge.js +43 -9
  204. package/lib/util/geometry.d.ts +8 -0
  205. package/lib/util/geometry.js +81 -1
  206. package/lib/util/theme.d.ts +2 -65
  207. package/lib/util/theme.js +15 -292
  208. package/lib/view/Anchor.d.ts +1 -0
  209. package/lib/view/Anchor.js +24 -21
  210. package/lib/view/Control.d.ts +5 -0
  211. package/lib/view/Control.js +44 -57
  212. package/lib/view/edge/BaseEdge.js +9 -0
  213. package/lib/view/edge/PolylineEdge.js +13 -2
  214. package/lib/view/node/BaseNode.d.ts +1 -0
  215. package/lib/view/node/BaseNode.js +22 -10
  216. package/lib/view/node/HtmlNode.js +1 -3
  217. package/lib/view/overlay/CanvasOverlay.js +5 -2
  218. package/lib/view/overlay/Grid.d.ts +12 -1
  219. package/lib/view/overlay/Grid.js +83 -21
  220. package/lib/view/overlay/OutlineOverlay.d.ts +1 -0
  221. package/lib/view/overlay/OutlineOverlay.js +18 -17
  222. package/lib/view/overlay/gridConfig.d.ts +46 -0
  223. package/lib/view/overlay/gridConfig.js +104 -0
  224. package/lib/view/shape/Polygon.d.ts +0 -7
  225. package/lib/view/shape/Polygon.js +13 -45
  226. package/package.json +9 -2
  227. package/scripts/postinstall-ai-prompt.js +67 -0
  228. package/.turbo/turbo-build$colon$dev.log +0 -10
  229. package/.turbo/turbo-build.log +0 -33
  230. package/CHANGELOG.md +0 -1849
  231. package/__tests__/algorithm/egde.test.ts +0 -131
  232. package/__tests__/algorithm/index.test.ts +0 -74
  233. package/__tests__/algorithm/outline.test.ts +0 -43
  234. package/__tests__/bugs/1545-spec.test.ts +0 -42
  235. package/__tests__/event/event.test.ts +0 -22
  236. package/__tests__/history/history.test.ts +0 -28
  237. package/__tests__/logicflow.test.ts +0 -575
  238. package/__tests__/model/graphmodel.test.ts +0 -87
  239. package/__tests__/util/compatible.test.ts +0 -48
  240. package/__tests__/util/edge.test.ts +0 -224
  241. package/__tests__/util/geometry.test.ts +0 -14
  242. package/__tests__/util/graph.test.ts +0 -16
  243. package/__tests__/util/matrix.test.ts +0 -41
  244. package/__tests__/util/node.test.ts +0 -68
  245. package/__tests__/util/sampling.test.ts +0 -12
  246. package/__tests__/util/vector.test.ts +0 -50
  247. package/__tests__/util/zIndex.test.ts +0 -10
  248. package/src/LogicFlow.tsx +0 -2008
  249. package/src/algorithm/edge.ts +0 -67
  250. package/src/algorithm/index.ts +0 -70
  251. package/src/algorithm/outline.ts +0 -77
  252. package/src/algorithm/rotate.ts +0 -55
  253. package/src/common/drag.ts +0 -219
  254. package/src/common/history.ts +0 -108
  255. package/src/common/index.ts +0 -6
  256. package/src/common/keyboard.ts +0 -108
  257. package/src/common/matrix.ts +0 -122
  258. package/src/common/vector.ts +0 -93
  259. package/src/constant/index.ts +0 -179
  260. package/src/event/event.md +0 -66
  261. package/src/event/eventArgs.ts +0 -643
  262. package/src/event/eventEmitter.ts +0 -156
  263. package/src/history/index.ts +0 -119
  264. package/src/index.less +0 -1
  265. package/src/index.ts +0 -26
  266. package/src/keyboard/index.ts +0 -112
  267. package/src/keyboard/shortcut.ts +0 -200
  268. package/src/model/BaseModel.ts +0 -250
  269. package/src/model/EditConfigModel.ts +0 -334
  270. package/src/model/GraphModel.ts +0 -1788
  271. package/src/model/NestedTransformModel.ts +0 -121
  272. package/src/model/SnaplineModel.ts +0 -256
  273. package/src/model/TransformModel.ts +0 -258
  274. package/src/model/edge/BaseEdgeModel.ts +0 -777
  275. package/src/model/edge/BezierEdgeModel.ts +0 -197
  276. package/src/model/edge/LineEdgeModel.ts +0 -36
  277. package/src/model/edge/PolylineEdgeModel.ts +0 -672
  278. package/src/model/edge/index.ts +0 -4
  279. package/src/model/index.ts +0 -9
  280. package/src/model/node/BaseNodeModel.ts +0 -949
  281. package/src/model/node/CircleNodeModel.ts +0 -91
  282. package/src/model/node/DiamondNodeModel.ts +0 -132
  283. package/src/model/node/EllipseNodeModel.ts +0 -98
  284. package/src/model/node/HtmlNodeModel.ts +0 -50
  285. package/src/model/node/PolygonNodeModel.ts +0 -150
  286. package/src/model/node/RectNodeModel.ts +0 -69
  287. package/src/model/node/TextNodeModel.ts +0 -54
  288. package/src/model/node/index.ts +0 -8
  289. package/src/options.ts +0 -145
  290. package/src/style/index.less +0 -261
  291. package/src/style/raw.ts +0 -220
  292. package/src/tool/MultipleSelectTool.tsx +0 -132
  293. package/src/tool/TextEditTool.tsx +0 -193
  294. package/src/tool/index.ts +0 -101
  295. package/src/typings.d.ts +0 -5
  296. package/src/util/animation.ts +0 -29
  297. package/src/util/browser.ts +0 -4
  298. package/src/util/compatible.ts +0 -15
  299. package/src/util/drag.ts +0 -220
  300. package/src/util/edge.ts +0 -1060
  301. package/src/util/geometry.ts +0 -55
  302. package/src/util/graph.ts +0 -46
  303. package/src/util/index.ts +0 -17
  304. package/src/util/matrix.ts +0 -129
  305. package/src/util/mobx.ts +0 -23
  306. package/src/util/node.ts +0 -543
  307. package/src/util/raf.ts +0 -28
  308. package/src/util/resize.ts +0 -606
  309. package/src/util/sampling.ts +0 -85
  310. package/src/util/theme.ts +0 -375
  311. package/src/util/uuid.ts +0 -26
  312. package/src/util/vector.ts +0 -93
  313. package/src/util/zIndex.ts +0 -6
  314. package/src/view/Anchor.tsx +0 -445
  315. package/src/view/Control.tsx +0 -512
  316. package/src/view/Graph.tsx +0 -141
  317. package/src/view/Rotate.tsx +0 -113
  318. package/src/view/behavior/dnd.ts +0 -162
  319. package/src/view/behavior/index.ts +0 -2
  320. package/src/view/behavior/snapline.ts +0 -16
  321. package/src/view/edge/AdjustPoint.tsx +0 -425
  322. package/src/view/edge/Arrow.tsx +0 -54
  323. package/src/view/edge/BaseEdge.tsx +0 -650
  324. package/src/view/edge/BezierEdge.tsx +0 -101
  325. package/src/view/edge/LineEdge.tsx +0 -81
  326. package/src/view/edge/PolylineEdge.tsx +0 -299
  327. package/src/view/edge/index.ts +0 -6
  328. package/src/view/index.ts +0 -8
  329. package/src/view/node/BaseNode.tsx +0 -571
  330. package/src/view/node/CircleNode.tsx +0 -21
  331. package/src/view/node/DiamondNode.tsx +0 -24
  332. package/src/view/node/EllipseNode.tsx +0 -22
  333. package/src/view/node/HtmlNode.tsx +0 -95
  334. package/src/view/node/PolygonNode.tsx +0 -28
  335. package/src/view/node/RectNode.tsx +0 -30
  336. package/src/view/node/TextNode.tsx +0 -39
  337. package/src/view/node/index.ts +0 -8
  338. package/src/view/overlay/BackgroundOverlay.tsx +0 -34
  339. package/src/view/overlay/BezierAdjustOverlay.tsx +0 -150
  340. package/src/view/overlay/CanvasOverlay.tsx +0 -288
  341. package/src/view/overlay/Grid.tsx +0 -162
  342. package/src/view/overlay/ModificationOverlay.tsx +0 -31
  343. package/src/view/overlay/OutlineOverlay.tsx +0 -170
  344. package/src/view/overlay/SnaplineOverlay.tsx +0 -44
  345. package/src/view/overlay/ToolOverlay.tsx +0 -65
  346. package/src/view/overlay/getTransformHoc.tsx +0 -50
  347. package/src/view/overlay/index.ts +0 -8
  348. package/src/view/shape/Circle.tsx +0 -41
  349. package/src/view/shape/Ellipse.tsx +0 -42
  350. package/src/view/shape/Line.tsx +0 -39
  351. package/src/view/shape/Path.tsx +0 -22
  352. package/src/view/shape/Polygon.tsx +0 -91
  353. package/src/view/shape/Polyline.tsx +0 -31
  354. package/src/view/shape/Rect.tsx +0 -44
  355. package/src/view/shape/Text.tsx +0 -169
  356. package/src/view/shape/index.ts +0 -8
  357. package/src/view/text/BaseText.tsx +0 -134
  358. package/src/view/text/LineText.tsx +0 -168
  359. package/src/view/text/index.ts +0 -2
  360. package/stats.html +0 -4842
  361. package/tsconfig.json +0 -18
@@ -0,0 +1,1427 @@
1
+ ---
2
+ nav: Guide
3
+ group:
4
+ title: Plug-in functionality
5
+ order: 3
6
+ title: BpmnElement
7
+ order: 11
8
+ toc: content
9
+ ---
10
+
11
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder;">
12
+ BPMN (Business Process Model and Notation) is a specification defined by OMG, widely used for enterprise-level process modeling, that describes business process execution logic in a standardized way.
13
+ </p>
14
+
15
+ ## Introduction
16
+ LogicFlow provides a BPMN plugin to build a BPMN-compliant modeling experience on the canvas. With this plugin, users can:
17
+ - Visually design process diagrams compliant with the BPMN specification
18
+ - Export to BPMN 2.0-compliant XML
19
+ - Run or further configure them in BPMN engines such as Activiti, Flowable, and Camunda
20
+
21
+ LogicFlow currently provides two versions of the BPMN plugin to meet scenarios with varying complexity and customization needs:
22
+ | Version | Target scenarios | Corresponding plugins and feature descriptions |
23
+ | -------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
24
+ | Basic | Quick delivery of simple flows | `bpmnElement`: Registers basic BPMN nodes for drawing simple flows;<br/>`bpmnAdapter`: Provides basic BPMN data import/export, supporting fundamental mapping and conversion between LogicFlow data and BPMN XML |
25
+ | Extended | Customization for complex flows | `BPMNElements`: Adds 6 node types, further extending BPMN element support;<br/>`bpmnElementsAdapter`: Offers more configurable options for finer-grained customization during import, export, and data mapping to meet different engine or business requirements |
26
+
27
+ :::info{title=Tip}
28
+ The built-in BPMN plugin in LogicFlow is mainly for basic capability demonstration and quick start. It covers only a small set of commonly used BPMN elements and does not support complex BPMN extension elements or custom attribute configuration.
29
+
30
+ In production projects, we recommend defining the node types and data structures required by your business, and implementing the corresponding data import, export, and transformation logic, rather than directly and fully adopting the built-in bpmnElement and bpmnAdapter plugins.
31
+
32
+ For scenarios with higher process complexity or customized BPMN semantics or XML structure, use the official bpmnElement and bpmnAdapter as references and re-implement, locally, a set of node systems and data format conversion plugins that better fit your product needs.
33
+
34
+ One of LogicFlow’s original intentions is to enable the frontend to express business logic completely and clearly in code, rather than encapsulating critical business rules in uncontrollable third-party implementations. This brings frontend development closer to the business itself while leaving sufficient room for flexible extension in complex scenarios.
35
+ :::
36
+
37
+ ## bpmnElement Plugin
38
+
39
+ The bpmnElement plugin provides basic BPMN element registration for drawing BPMN-compliant nodes on the LogicFlow canvas.
40
+
41
+ ### Node Description
42
+ During mounting, the bpmnElement plugin registers the following six BPMN elements:
43
+
44
+ <div style="height: 40px;">
45
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 24px;">
46
+ <span style="font-size: 14px;">Start Event (bpmn:startEvent)</span>
47
+ </p>
48
+ </div>
49
+
50
+ **Visual Style**
51
+
52
+ <div style="width: 100%; display: flex; justify-content: center;">
53
+ <img src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/article/extension/bpmn/startEvent.png" style="height: 120px; border-radius: 10px; box-shadow: 0 0 20px #dfecf9ff" alt="Start Event" />
54
+ </div>
55
+
56
+ - Inherits the circle from the built-in CircleNode
57
+ - Text: when initialized with `text`, defaults to 40px below the node
58
+ - Overrides setAttributes to fix the radius at 18
59
+
60
+ **Other Details**
61
+
62
+ - Default ID generation rule: Event_${random}
63
+ - Overrides getConnectedTargetRules: cannot be a connection target, only a source
64
+ - Implementation: [StartEvent](https://github.com/didi/LogicFlow/blob/master/packages/extension/src/bpmn/events/StartEvent.ts)
65
+
66
+ <div style="height: 40px;">
67
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 24px;">
68
+ <span style="font-size: 14px;">End Event (bpmn:endEvent)</span>
69
+ </p>
70
+ </div>
71
+
72
+ **Visual Style**
73
+
74
+ <div style="width: 100%; display: flex; justify-content: center;">
75
+ <img src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/article/extension/bpmn/endEvent.png" style="height: 100px; border-radius: 10px; box-shadow: 0 0 20px #dfecf9" alt="End Event" />
76
+ </div>
77
+
78
+ - Inherits the circle from the built-in CircleNode
79
+ - Text: when initialized with `text`, defaults to 40px below the node
80
+ - Overrides setAttributes to fix the radius at 18
81
+
82
+ **Other Details**
83
+
84
+ - Default ID generation rule: Event_${random}
85
+ - Overrides getConnectedSourceRules: cannot be a connection source
86
+ - Overrides getShape to draw concentric double circles
87
+ - Implementation: [EndEvent](https://github.com/didi/LogicFlow/blob/master/packages/extension/src/bpmn/events/EndEvent.ts)
88
+
89
+ <div style="height: 40px;">
90
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 24px;">
91
+ <span style="font-size: 14px;">User Task (bpmn:userTask)</span>
92
+ </p>
93
+ </div>
94
+
95
+ **Visual Style**
96
+
97
+ <div style="width: 100%; display: flex; justify-content: center;">
98
+ <img src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/article/extension/bpmn/userTask.png" style="height: 100px; border-radius: 10px; box-shadow: 0 0 20px #dfecf9ff" alt="User Task Node" />
99
+ </div>
100
+
101
+ - Inherits the rounded rectangle from the built-in RectNode
102
+ - Overrides getShape to overlay a user icon drawn with an SVG path
103
+ - Icon is positioned with a 5px inner offset from the top-left corner
104
+ - Icon color follows the node’s `stroke` style
105
+
106
+ **Other Details**
107
+
108
+ - Default ID generation rule: Activity_${random}
109
+ - Implementation: [UserTask](https://github.com/didi/LogicFlow/blob/master/packages/extension/src/bpmn/tasks/UserTask.ts)
110
+
111
+ <div style="height: 40px;">
112
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 24px;">
113
+ <span style="font-size: 14px;">Service Task (bpmn:serviceTask)</span>
114
+ </p>
115
+ </div>
116
+
117
+ **Visual Style**
118
+
119
+ <div style="width: 100%; display: flex; justify-content: center;">
120
+ <img src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/article/extension/bpmn/serviceTask.png" style="height: 100px; border-radius: 10px; box-shadow: 0 0 20px #dfecf9" alt="Service Task Node" />
121
+ </div>
122
+
123
+ - Inherits the rounded rectangle from the built-in RectNode
124
+ - Overrides getShape to overlay a service icon drawn with an SVG path
125
+ - Icon is positioned with a 5px inner offset from the top-left corner
126
+ - Icon color follows the node’s `stroke` style
127
+
128
+ **Other Details**
129
+
130
+ - Default ID generation rule: Activity_${random}
131
+ - Implementation: [ServiceTask](https://github.com/didi/LogicFlow/blob/master/packages/extension/src/bpmn/tasks/ServiceTask.ts)
132
+
133
+ <div style="height: 40px;">
134
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 24px;">
135
+ <span style="font-size: 14px;">Exclusive Gateway (bpmn:exclusiveGateway)</span>
136
+ </p>
137
+ </div>
138
+
139
+ **Visual Style**
140
+
141
+ <div style="width: 100%; display: flex; justify-content: center;">
142
+ <img src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/article/extension/bpmn/exclusiveGateway.png" style="height: 100px; border-radius: 10px; box-shadow: 0 0 20px #dfecf9" alt="Exclusive Gateway Node" />
143
+ </div>
144
+
145
+ - Inherits the diamond from the built-in PolygonNode
146
+ - When initialized with `text`, the label defaults to 40px below the node
147
+ - Default points are set to `[25,0] [50,25] [25,50] [0,25]`
148
+ - Overrides `getShape` to draw the internal exclusive routing marker
149
+
150
+ **Other Details**
151
+
152
+ - Default ID generation rule: Gateway_${random}
153
+ - Implementation: [ExclusiveGateway](https://github.com/didi/LogicFlow/blob/master/packages/extension/src/bpmn/gateways/ExclusiveGateway.ts)
154
+
155
+ <div style="height: 40px;">
156
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 24px;">
157
+ <span style="font-size: 14px;">Sequence Flow (bpmn:sequenceFlow)</span>
158
+ </p>
159
+ </div>
160
+
161
+ **Visual Style**
162
+
163
+ <div style="width: 100%; display: flex; justify-content: center;">
164
+ <img src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/article/extension/bpmn/sequenceFlow.png" style="height: 70px; border-radius: 10px; box-shadow: 0 0 20px #dfecf9" alt="Sequence Flow" />
165
+ </div>
166
+
167
+ - Inherits the polyline from the built-in PolylineEdge
168
+
169
+ **Other Details**
170
+
171
+ - Default ID generation rule: Flow_${random}
172
+ - After the plugin is introduced, it is set as the default edge type. You can disable this by passing `customBpmnEdge: true` when initializing the LogicFlow instance.
173
+ - Implementation: [SequenceFlow](https://github.com/didi/LogicFlow/blob/master/packages/extension/src/bpmn/flow/SequenceFlow.ts)
174
+
175
+ ### Usage Guide
176
+ 1. Import the plugin
177
+
178
+ :::code-group
179
+
180
+ ```tsx [npm]
181
+ import { BpmnElement } from '@logicflow/extension'
182
+ // Global usage
183
+ LogicFlow.use(BpmnElement)
184
+ // Per-instance usage
185
+ const lf = new LogicFlow({
186
+ // ... // other options
187
+ plugins: [BpmnElement],
188
+ })
189
+ ```
190
+ ```html [CDN]
191
+ <!-- Include plugin bundle -->
192
+ <script src="https://cdn.jsdelivr.net/npm/@logicflow/extension/dist/index.min.js"></script>
193
+ <!-- Include plugin styles -->
194
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@logicflow/extension/lib/style/index.min.css" />
195
+ <div id="container"></div>
196
+ <script>
197
+ const { BpmnElement } = Extension
198
+ // Global usage
199
+ Core.default.use(BpmnElement);
200
+ // Per-instance usage
201
+ const lf = new Core.default({
202
+ ..., // Other options
203
+ plugins: [BpmnElement],
204
+ })
205
+ </script>
206
+ ```
207
+ :::
208
+ 2. Render BPMN elements
209
+
210
+ ```js
211
+ // ... plugin import logic
212
+
213
+ lf.render({
214
+ nodes: [
215
+ { id: 'Event_1234567', type: 'bpmn:startEvent', x: 100, y: 100, },
216
+ { id: 'Task_123ac56', type: 'bpmn:userTask', x: 300, y: 100, },
217
+ { id: 'Event_fa4c699', type: 'bpmn:endEvent', x: 500, y: 100, },
218
+ ],
219
+ edges: [
220
+ { id: 'Flow_12ac567', sourceNodeId: 'Event_1234567', targetNodeId: 'Task_123ac56', type: 'bpmn:sequenceFlow', },
221
+ { id: 'Flow_fa4c689', sourceNodeId: 'Task_123ac56', targetNodeId: 'Event_fa4c699', type: 'bpmn:sequenceFlow', },
222
+ ],
223
+ })
224
+ ```
225
+
226
+ Simply include this plugin in a LogicFlow instance to use its built-in BPMN elements.
227
+ During mounting, the plugin automatically calls `register` to add BPMN elements to LogicFlow and sets `bpmn:sequenceFlow` as the default edge type on the canvas.
228
+
229
+ Whether to use `bpmn:sequenceFlow` as the default edge type can be controlled by configuration. If you do not want BPMN edges as the default, set `customBpmnEdge: true` when instantiating LogicFlow to disable this behavior.
230
+
231
+
232
+
233
+
234
+ ## bpmnAdapter Plugin
235
+ This plugin provides conversion capabilities between BPMN data format and LogicFlow data format, including adapters for different scenarios: `BpmnAdapter`, `BpmnXmlAdapter`, and helper functions `toNormalJson` and `toXmlJson` to convert between standard JSON and XML-style JSON structures.
236
+
237
+ ### BpmnAdapter
238
+ Performs bidirectional conversion between LogicFlow graph data and BPMN graph data; includes `adapterIn` and `adapterOut` methods:
239
+
240
+ <div style="height: 60px;">
241
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 20px;">
242
+ <span style="font-size: 14px;">adapterIn(bpmnData)</span>
243
+ <br/>
244
+ <span style="font-size: 12px; color: #a4a4a4;">
245
+ Convert BPMN graph data to LogicFlow graph data.
246
+ </span>
247
+ </p>
248
+ </div>
249
+
250
+ **Parameters**<br/>
251
+ - bpmnData *(Object)*: BPMN data to convert
252
+
253
+ **Returns**<br/>
254
+ - data *([GraphConfigData](../../api/type/MainTypes.en.md#graphconfigdata))*: Converted LogicFlow graph data
255
+
256
+ **Data conversion example**
257
+ <iframe src="/bpmn2Lf.html" style="border: none; width: 100%; height: 260px; margin: auto;"></iframe>
258
+
259
+ <div style="height: 60px;">
260
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 20px;">
261
+ <span style="font-size: 14px;">adapterOut(data, retainedFields?)</span>
262
+ <br/>
263
+ <span style="font-size: 12px; color: #a4a4a4;">
264
+ Convert LogicFlow graph data to BPMN graph data.
265
+ </span>
266
+ </p>
267
+ </div>
268
+
269
+ **Parameters**<br/>
270
+ - data *([GraphConfigData](../../api/type/MainTypes.en.md#graphconfigdata))*: LogicFlow data to convert
271
+ - retainedFields *(string[])*: Optional; list of field names to retain and write as BPMN attributes during conversion. Effective only when the corresponding field in `node.properties` is of type `object`.
272
+
273
+ **Returns**<br/>
274
+ - bpmnData *(Object)*: Converted BPMN graph data
275
+
276
+ **Data conversion example**
277
+ <iframe src="/lf2Bpmn.html" style="border: none; width: 100%; height: 260px; margin: auto;"></iframe>
278
+
279
+ :::info{title=Differences}
280
+ As shown by the red box below, if an attribute is in `retainedFields`, it will have the `-` prefix and exist as a property of the startEvent; otherwise, it will exist as a child node.
281
+ <img src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/article/extension/bpmn/lf2bpmnDiff.png" style="border-radius: 10px;" alt="Differences between LogicFlow graph data and BPMN graph data conversion" />
282
+ :::
283
+
284
+ ### BpmnXmlAdapter
285
+ Extends BpmnAdapter and overrides `adapterIn` and `adapterOut` with the same overall logic. The difference is: `adapterOut` converts LogicFlow graph data to BPMN graph data in XML format; `adapterIn` converts BPMN XML JSON data to LogicFlow graph data.
286
+
287
+ <div style="height: 60px;">
288
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 20px;">
289
+ <span style="font-size: 14px;">adapterIn(bpmnData)</span>
290
+ <br/>
291
+ <span style="font-size: 12px; color: #a4a4a4;">
292
+ Convert BPMN graph data to LogicFlow graph data.
293
+ </span>
294
+ </p>
295
+ </div>
296
+
297
+ **Parameters**<br/>
298
+ - bpmnData *(Object)*: BPMN data to convert
299
+
300
+ **Returns**<br/>
301
+ - data *([GraphConfigData](../../api/type/MainTypes.en.md#graphconfigdata))*: Converted LogicFlow graph data
302
+
303
+ **Data conversion example**
304
+ <iframe src="/bpmnXml2Lf.html" style="border: none; width: 100%; height: 260px; margin: auto;"></iframe>
305
+
306
+ <div style="height: 60px;">
307
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 20px;">
308
+ <span style="font-size: 14px;">adapterOut(data)</span>
309
+ <br/>
310
+ <span style="font-size: 12px; color: #a4a4a4;">
311
+ Convert LogicFlow graph data to BPMN graph data.
312
+ </span>
313
+ </p>
314
+ </div>
315
+
316
+ **Parameters**<br/>
317
+ - data *([GraphConfigData](../../api/type/MainTypes.en.md#graphconfigdata))*: LogicFlow data to convert
318
+ - retainedFields *(string[])*: List of field names to retain and write as BPMN attributes during conversion. Effective only when the corresponding field in `node.properties` is of type `object`.
319
+
320
+ **Returns**<br/>
321
+ - bpmnData *(Object)*: Converted BPMN graph data
322
+
323
+ **Data conversion example**
324
+ <iframe src="/lf2BpmnXml.html" style="border: none; width: 100%; height: 260px; margin: auto;"></iframe>
325
+
326
+ :::info{title=Differences}
327
+ As shown by the red box below, if a field is in `retainedFields`, it will be rendered as a node attribute; otherwise, it will be rendered as node data.
328
+ <img src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/article/extension/bpmn/lf2BpmnXmlDiff.png" style="border-radius: 10px;" alt="Differences between LogicFlow graph data and BPMN XML graph data conversion" />
329
+ :::
330
+
331
+ ### Other Exports
332
+
333
+ `toNormalJson` and `toXmlJson` are the core conversion methods of bpmnAdapter, used by `adapterIn` and `adapterOut` respectively.
334
+ You can wrap customized conversion logic based on these methods as needed.
335
+
336
+
337
+ <div style="height: 60px;">
338
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 20px;">
339
+ <span style="font-size: 14px;">toNormalJson(xmlJson)</span>
340
+ <br/>
341
+ <span style="font-size: 12px; color: #a4a4a4;">
342
+ 将 XML 风格 JSON(属性键以 `-` 前缀)转换为普通 JSON;移除 `-` 前缀并递归处理对象/数组,保留文本与属性结构。
343
+ </span>
344
+ </p>
345
+ </div>
346
+
347
+ **Parameters**<br/>
348
+ - xmlJson *(Object)*: XML-style JSON data (attribute keys start with `-`)
349
+
350
+ **Returns**<br/>
351
+ - json *(Object)*: Converted normal JSON data
352
+
353
+
354
+ <div style="height: 80px; margin-top: 8px;">
355
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 20px;">
356
+ <span style="font-size: 14px;">toXmlJson(retainedFields?)</span>
357
+ <br/>
358
+ <span style="font-size: 12px; color: #a4a4a4;">
359
+ 将普通 JSON 转为 XML 风格 JSON;为属性键加 `-` 前缀;支持保留字段 `retainedFields` 与默认保留字段(如 `properties/startPoint/endPoint/pointsList`);处理数组与 `#text/#cdata-section/#comment`。
360
+ </span>
361
+ </p>
362
+ </div>
363
+
364
+ **Parameters**<br/>
365
+ - retainedFields *(string[])*: Optional; list of fields to retain and write as attributes during conversion (effective only when the corresponding field is of type `object`)
366
+
367
+ **Returns**<br/>
368
+ - convert *(Function)*: Returns a conversion function used as `convert(json)`, where `json` is normal JSON; the return value is XML-style JSON (attribute keys start with `-`)
369
+
370
+
371
+ ### Usage Guide
372
+
373
+ Similar to the bpmnElement plugin above, simply include this plugin in a LogicFlow instance to use its built-in BPMN data conversion capabilities. Without additional customization, this conversion process is transparent to users.
374
+ Just call `getGraphData` to obtain the BPMN data for the current canvas, and call `render` to render BPMN data onto the canvas.
375
+
376
+ :::warning{title=Note}
377
+ 1. To use the conversion capabilities provided by the bpmnAdapter plugin, ensure BPMN-related nodes have been registered within the LogicFlow instance (either via the bpmnElement plugin or custom BPMN nodes), otherwise a node type not found exception will be thrown.
378
+ 2. Both `BpmnAdapter` and `BpmnXmlAdapter` override `lf.adapterIn` and `lf.adapterOut`. When multiple adapters exist, the later one will override the earlier implementation and take effect. Therefore, if you need to customize `lf.adapterIn` or `lf.adapterOut`, assign them after introducing the Adapter to avoid your custom logic being overwritten.
379
+ :::
380
+
381
+ 1. Import the plugin
382
+
383
+ :::code-group
384
+
385
+ ```tsx [npm]
386
+ // Note: The following example assumes no custom BPMN nodes are registered;
387
+ // if custom BPMN nodes are already registered, you do not need to include the bpmnElement plugin
388
+ import { BpmnElement, BpmnAdapter, BpmnXmlAdapter, toNormalJson, toXmlJson } from '@logicflow/extension'
389
+ // Global usage
390
+ LogicFlow.use(BpmnElement)
391
+ // Include BpmnAdapter or BpmnXmlAdapter as needed
392
+ // LogicFlow.use(BpmnAdapter)
393
+ LogicFlow.use(BpmnXmlAdapter)
394
+ // Per-instance usage
395
+ const lf = new LogicFlow({
396
+ // ... // other options
397
+ plugins: [
398
+ BpmnElement,
399
+ // Include BpmnAdapter or BpmnXmlAdapter as needed
400
+ // BpmnAdapter,
401
+ BpmnXmlAdapter
402
+ ],
403
+ })
404
+ ```
405
+
406
+ ```html [CDN]
407
+ <!-- Note: The following example assumes no custom BPMN nodes are registered;
408
+ if custom BPMN nodes are already registered, you do not need to include the BpmnElement plugin -->
409
+
410
+ <!-- Include plugin bundle -->
411
+ <script src="https://cdn.jsdelivr.net/npm/@logicflow/extension/dist/index.min.js"></script>
412
+ <!-- Include plugin styles -->
413
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@logicflow/extension/lib/style/index.min.css" />
414
+ <div id="container"></div>
415
+ <script>
416
+ const { BpmnElement, BpmnAdapter, BpmnXmlAdapter, toNormalJson, toXmlJson } = Extension
417
+ // Global usage
418
+ // Include BpmnAdapter or BpmnXmlAdapter as needed
419
+ Core.default.use(BpmnElement);
420
+ // Core.default.use(BpmnAdapter);
421
+ Core.default.use(BpmnXmlAdapter);
422
+ // Per-instance usage
423
+ const lf = new Core.default({
424
+ ..., // Other options
425
+ plugins: [
426
+ BpmnElement,
427
+ // Include BpmnAdapter or BpmnXmlAdapter as needed
428
+ // BpmnAdapter,
429
+ BpmnXmlAdapter
430
+ ],
431
+ })
432
+ </script>
433
+ ```
434
+ :::
435
+
436
+ 2. Use the plugin for data conversion
437
+ ```js
438
+ // Render data
439
+ lf.render({
440
+ nodes: [
441
+ { id: 'Event_1234567', type: 'bpmn:startEvent', x: 100, y: 100, },
442
+ { id: 'Task_123ac56', type: 'bpmn:userTask', x: 300, y: 100, },
443
+ { id: 'Event_fa4c699', type: 'bpmn:endEvent', x: 500, y: 100, },
444
+ ],
445
+ edges: [
446
+ { id: 'Flow_12ac567', sourceNodeId: 'Event_1234567', targetNodeId: 'Task_123ac56', type: 'bpmn:sequenceFlow', },
447
+ { id: 'Flow_fa4c689', sourceNodeId: 'Task_123ac56', targetNodeId: 'Event_fa4c699', type: 'bpmn:sequenceFlow', },
448
+ ],
449
+ })
450
+ // Generate BPMN XML data and download locally
451
+ const handleDownloadData = () => {
452
+ const retainedFields = ['width', 'height']
453
+ const data = lfRef.current?.getGraphData(retainedFields)
454
+ download('logicflow.xml', data)
455
+ }
456
+ // Upload an XML file and render it into the LogicFlow instance
457
+ const handleUploadData = (e) => {
458
+ const file = e.target.files?.[0]
459
+ const reader = new FileReader()
460
+ reader.onload = (event) => {
461
+ const xml = event.target?.result
462
+ // Render XML data into the LogicFlow instance
463
+ lf.render(xml)
464
+ }
465
+ reader.onerror = (error) => console.log(error)
466
+ file && reader.readAsText(file)
467
+ }
468
+ ```
469
+ 3. Customize adapter logic
470
+ ``` js
471
+
472
+ // ... preceding plugin import logic
473
+
474
+ // Custom adapter logic
475
+ const customAdapterIn = (xmlJson) => {
476
+ // ... // preprocessing data construction logic
477
+ const json = toNormalJson(xmlJson)
478
+ // Apply custom processing to json
479
+ return json
480
+ }
481
+
482
+ const customAdapterOut = (json) => {
483
+ // ... // preprocessing data construction logic
484
+ const xmlJson = toXmlJson(json)
485
+ // Apply custom processing to xmlJson
486
+ return xmlJson
487
+ }
488
+ lf.adapterIn = customAdapterIn
489
+ lf.adapterOut = customAdapterOut
490
+
491
+ // ... subsequent data rendering and import/export logic
492
+
493
+ ```
494
+
495
+ ## Preview
496
+ <iframe src="/bpmn.html" style="border: none; width: 100%; height: 400px; margin: auto;"></iframe>
497
+
498
+
499
+
500
+ ## BPMNElements Plugin
501
+
502
+ :::
503
+
504
+ The BPMNElements plugin extends capabilities based on the bpmnElement plugin:
505
+
506
+ ### Event Definition Support
507
+ In BPMN, event nodes indicate changes in a moment or state during a process; event definitions describe the cause of the event.
508
+ In the extended BPMNElements plugin, all event nodes support event definitions. Users can add event definitions to nodes via `lf.useDefinition()`.
509
+ <div style="height: 60px; margin-top: 8px;">
510
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 20px;">
511
+ <span style="font-size: 14px;">lf.useDefinition()</span>
512
+ <br/>
513
+ <span style="font-size: 12px; color: #a4a4a4;">
514
+ Provides mapping and configuration between nodes and event definitions
515
+ </span>
516
+ </p>
517
+ </div>
518
+
519
+ **Returns**<br/>
520
+ - Returns a parameterless function whose result is a tuple `[definition, setDefinition]`.
521
+ - Where:
522
+ - definition: `Map<string, [DefinitionConfigType](../../api/type/MainTypes.en.md#definitionconfigtype)>`, an event definition mapping for storing node definition configurations
523
+ - setDefinition: `(config: [DefinitionConfigType](../../api/type/MainTypes.en.md#definitionconfigtype)[]) => void`, used to set node definition configurations
524
+
525
+ :::info{title=Default Event Definitions}
526
+ When initialized, the BPMNElements plugin calls `setDefinition(definitionConfig)` once to generate a default set of event definitions:
527
+
528
+ ```ts
529
+ // Add a timer event definition for the three nodes: startEvent, intermediateCatchEvent, boundaryEvent
530
+ const definitionConfig: DefinitionConfigType[] = [
531
+ {
532
+ nodes: ['startEvent', 'intermediateCatchEvent', 'boundaryEvent'],
533
+ definition: [
534
+ {
535
+ // The 'type' property of the definition corresponds to the XML node name
536
+ type: 'bpmn:timerEventDefinition',
537
+ // The icon can be an SVG path 'd', or an SVG generated via the 'h' function exported by @logicflow/core; here it's generated via 'h'
538
+ icon: timerIcon,
539
+ /**
540
+ * 'properties' are attributes required by the definition, e.g. timerType and timerValue here
541
+ * timerType can be "timeCycle", "timerDate", "timeDuration", distinguishing <bpmn:timeCycle/>, <bpmn:timeDate/>, <bpmn:timeDuration/>
542
+ * timerValue is the cron-like expression corresponding to timerType
543
+ * This ultimately generates `<bpmn:${timerType} xsi:type="bpmn:tFormalExpression">${timerValue}</bpmn:${timerType}>`
544
+ */
545
+ properties: {
546
+ definitionType: 'bpmn:timerEventDefinition',
547
+ timerType: 'timeDuration',
548
+ timerValue: 'PT5M',
549
+ },
550
+ },
551
+ ],
552
+ },
553
+ ]
554
+ ```
555
+ When using, simply include the plugin and set `definitionType` in the node `properties` when rendering:
556
+ ```ts
557
+ lf.render({
558
+ nodes: [
559
+ {
560
+ id: 1,
561
+ type: 'bpmn:startEvent',
562
+ text: '5 min timed start',
563
+ properties: {
564
+ definitionType: 'bpmn:timerEventDefinition',
565
+ },
566
+ }
567
+ ]
568
+ })
569
+ ```
570
+ This renders a start event with a clock icon <img src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/article/extension/bpmn/durationStart.png" style=" border-radius: 10px;" height="50" alt="Start Event" />, and the corresponding BPMN node structure is:
571
+ ```xml
572
+ <bpmn:startEvent id="Event_f035fe6" name="5 min timed start" width="36" height="36">
573
+ <bpmn:timerEventDefinition id="Definition_4e3d5ce">
574
+ <bpmn:timeDuration xsi:type="bpmn:tFormalExpression">PT5M</bpmn:timeDuration>
575
+ </bpmn:timerEventDefinition>
576
+ </bpmn:startEvent>
577
+ ```
578
+ :::
579
+
580
+
581
+ ### Node Type Expansion
582
+ Compared to bpmnElement, the BPMNElements plugin adds six node types:
583
+
584
+ First, three event nodes:
585
+ <div style="height: 94px;">
586
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 24px;">
587
+ <span style="font-size: 14px;">Boundary Event (bpmn:boundaryEvent)<br/>Intermediate Catch Event (bpmn:intermediateCatchEvent)<br/>Intermediate Throw Event (bpmn:intermediateThrowEvent)</span>
588
+ </p>
589
+ </div>
590
+
591
+ **Visual Style**
592
+
593
+ <div style="margin-bottom: 20px;width: 100%; display: flex; justify-content: center;">
594
+ <img src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/article/extension/bpmn/diffDoundary.png" style="width: 50%; border-radius: 10px; box-shadow: 0 0 20px #dfecf9" alt="Event node styles" />
595
+ </div>
596
+
597
+ - Shape: double concentric circles (outer radius 18 by default, inner radius 15, border width 1.5), render icon per definition configuration (supports a single `path d` or multiple child elements `g`)
598
+ - Text: when initialized with `text`, defaults to 40px below the node
599
+ - Specific to throw events: when the icon is a single `path`, use black fill (`style: 'fill: black'`) to indicate the “throw” semantics
600
+ - Specific to boundary events: set `autoToFront=false` and `zIndex=99999` in `initNodeData` so the node stays on top; when `properties.cancelActivity === false`, show a dashed border (`5,5`), interrupting type (`true`) uses a solid border
601
+ - Anchors: hide anchors (`getAnchorStyle` returns `visibility: hidden`) to avoid unnecessary anchor interactions
602
+
603
+ **Unique Attributes**
604
+
605
+ - `definitionType`: definition type identifier used to select specific icons and default attributes from the definition repository
606
+ - `definitionId`: when `definitionType` exists, generate `Definition_${random}` for subsequent association
607
+ - Boundary event-specific attributes: `attachedToRef` is the ID of the task node it attaches to (user/system task); `cancelActivity` determines whether the process is interrupted (default `true`), affecting border style (solid/dashed)
608
+ - Others: merge default attributes from the definition based on `properties.definitionType`
609
+
610
+ **Other Details**
611
+
612
+ - ID generation: defaults to `Event_${random}` when absent
613
+ - Grouping rules: call `groupRule.call(this)` during initialization to keep grouping interactions consistent
614
+
615
+ Next, two gateway nodes:
616
+
617
+ <div style="height: 60px;">
618
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 24px;">
619
+ <span style="font-size: 14px;">Parallel Gateway (bpmn:parallelGateway)<br/>Inclusive Gateway (bpmn:inclusiveGateway)</span>
620
+ </p>
621
+ </div>
622
+
623
+ In the BPMNElements plugin, gateway node implementations are unified: exclusive, parallel, and inclusive gateways are constructed via the same factory method. They differ only by node type and icon, so they are described together.
624
+
625
+ **Visual Style**
626
+ <div style="margin-bottom: 20px;width: 100%; display: flex; justify-content: center;">
627
+ <img src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/article/extension/bpmn/diffGateway.png" style="width: 50%; border-radius: 10px; box-shadow: 0 0 20px #dfecf9" alt="Gateway node styles" />
628
+ </div>
629
+
630
+ - Custom nodes inheriting the diamond shape, initializing the four vertices as: `[25,0] [50,25] [25,50] [0,25]`; override `getShape` to overlay the gateway icon at the diamond’s center
631
+ - Icons may be a single `path d` (default fill `rgb(34, 36, 42)`, `strokeWidth: 1`), or complex SVG generated via the h function
632
+ - When `text` is provided as a string, format it as `{ value, x, y }` and move it 40px downward
633
+
634
+ **Other Details**
635
+
636
+ - ID generation: defaults to `Gateway_${random}` when absent
637
+ - Grouping rules: call `groupRule.call(this)` during initialization to keep grouping interactions consistent
638
+
639
+ Finally, a process node:
640
+ <div style="height: 42px;">
641
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 20px;">
642
+ <span style="font-size: 14px;">SubProcess Node (bpmn:subProcess)</span>
643
+ </p>
644
+ </div>
645
+
646
+ **Visual Style**
647
+
648
+ <div style="margin-bottom: 20px;width: 100%; display: flex; justify-content: center;">
649
+ <img src="https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/article/extension/bpmn/subProcess.png" style="width: 50%; border-radius: 10px; box-shadow: 0 0 20px #dfecf9" alt="SubProcess node styles" />
650
+ </div>
651
+
652
+ - Custom rectangle inheriting the grouping node `GroupNode`; supports collapse/expand interaction: draw a collapse button at the top-left (gray small rectangle + plus sign horizontal/vertical lines) and toggle `properties.isFolded` on click
653
+ - Main render is a rectangular border (`stroke: black`, `strokeWidth: 2`, `strokeDasharray: '0 0'`)
654
+ - Hide anchor hover outlines (`getAnchorStyle`, `getOutlineStyle` set hover/outline to transparent)
655
+
656
+ **Unique Attributes and Behaviors**
657
+
658
+ - `foldable`: whether collapsible, default `true`; clicking the top-left collapse button triggers `foldGroup`
659
+ - `resizable`: whether resizable, default `true`
660
+ - `iniProp`: initialization properties to customize initial width/height (`iniProp.width/iniProp.height` override defaults)
661
+ - `isTaskNode`: marks the node as a task node to support attached boundary events (see boundary event description)
662
+ - `boundaryEvents`: records the list of attached boundary event IDs
663
+
664
+ **Methods**
665
+
666
+ - `setTouching(flag)`: set the proximity state when dragging a boundary event, used for highlight indication
667
+ - `addBoundaryEvent(nodeId)`: attach a boundary event (write `attachedToRef` and add to the list), and cancel the proximity highlight
668
+ - `deleteBoundaryEvent(nodeId)`: remove the record of an attached boundary event
669
+ - `addChild(id)`: set the child node’s `parent` attribute and add it to the group, aiding group management and collapse semantics
670
+
671
+ **Other Details**
672
+
673
+ - Default size: `width=400`, `height=200` (can be reset via `iniProp`)
674
+ - Interaction consistency: enable grouping rules during initialization (`groupRule.call(this)`) to keep grouping interactions consistent
675
+
676
+ ### Usage Guide
677
+ 1. Import the plugin
678
+
679
+ :::code-group
680
+
681
+ ```tsx [npm]
682
+ import { BPMNElements } from '@logicflow/extension'
683
+ // Global usage
684
+ LogicFlow.use(BPMNElements)
685
+ // Per-instance usage
686
+ const lf = new LogicFlow({
687
+ // ... // other options
688
+ plugins: [BPMNElements],
689
+ })
690
+ ```
691
+ ```html [CDN]
692
+ <!-- Include plugin bundle -->
693
+ <script src="https://cdn.jsdelivr.net/npm/@logicflow/extension/dist/index.min.js"></script>
694
+ <!-- Include plugin styles -->
695
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@logicflow/extension/lib/style/index.min.css" />
696
+ <div id="container"></div>
697
+ <script>
698
+ const { BPMNElements } = Extension
699
+ // Global usage
700
+ Core.default.use(BPMNElements);
701
+ // Per-instance usage
702
+ const lf = new Core.default({
703
+ ..., // Other options
704
+ plugins: [BPMNElements],
705
+ })
706
+ </script>
707
+ ```
708
+ :::
709
+ 2. Render BPMN elements
710
+
711
+ ```js
712
+ // ... plugin import logic
713
+
714
+ lf.render({
715
+ nodes: [
716
+ {
717
+ id: '1',
718
+ type: 'bpmn:userTask',
719
+ x: 531,
720
+ y: 199,
721
+ properties: {
722
+ isBoundaryEventTouchingTask: false,
723
+ width: 100,
724
+ height: 80,
725
+ },
726
+ },
727
+ {
728
+ id: 'Event_1230439',
729
+ type: 'bpmn:startEvent',
730
+ x: 369,
731
+ y: 199,
732
+ properties: {
733
+ definitionType: 'bpmn:timerEventDefinition',
734
+ timerValue: 'PT5M',
735
+ timerType: 'timeDuration',
736
+ definitionId: 'Definition_1ee1ad3',
737
+ width: 36,
738
+ height: 36,
739
+ },
740
+ text: '5 min timed start',
741
+ },
742
+ {
743
+ id: 'Event_551491b',
744
+ type: 'bpmn:boundaryEvent',
745
+ x: 575,
746
+ y: 235,
747
+ properties: {
748
+ attachedToRef: '1',
749
+ cancelActivity: true,
750
+ definitionType: 'bpmn:timerEventDefinition',
751
+ timerValue: 'boundaryEvent',
752
+ timerType: '222',
753
+ definitionId: 'Definition_7f7779a',
754
+ width: 36,
755
+ height: 36,
756
+ },
757
+ text: 'Boundary Event',
758
+ },
759
+ {
760
+ id: 'Gateway_3e3764d',
761
+ type: 'bpmn:parallelGateway',
762
+ x: 707,
763
+ y: 199,
764
+ properties: {
765
+ width: 50,
766
+ height: 50,
767
+ },
768
+ text: 'Parallel Gateway',
769
+ },
770
+ {
771
+ id: 'Activity_3d69f0c',
772
+ type: 'bpmn:serviceTask',
773
+ x: 880,
774
+ y: 144,
775
+ properties: {
776
+ width: 100,
777
+ height: 80,
778
+ },
779
+ text: 'Service Task',
780
+ },
781
+ {
782
+ id: 'Activity_6e5fe39',
783
+ type: 'bpmn:serviceTask',
784
+ x: 879,
785
+ y: 285,
786
+ properties: {
787
+ width: 100,
788
+ height: 80,
789
+ },
790
+ text: 'Service Task',
791
+ },
792
+ {
793
+ id: 'Event_be840c3',
794
+ type: 'bpmn:endEvent',
795
+ x: 1041,
796
+ y: 198,
797
+ properties: {
798
+ width: 36,
799
+ height: 36,
800
+ },
801
+ text: 'End',
802
+ },
803
+ ],
804
+ edges: [
805
+ {
806
+ id: 'Flow_059933a',
807
+ type: 'bpmn:sequenceFlow',
808
+ properties: {
809
+ isDefaultFlow: false,
810
+ },
811
+ sourceNodeId: 'Event_1230439',
812
+ targetNodeId: '1',
813
+ sourceAnchorId: 'Event_1230439_1',
814
+ targetAnchorId: '1_3',
815
+ },
816
+ ],
817
+ })
818
+ ```
819
+
820
+ Like BpmnElement, BPMNElements only needs to be included in a LogicFlow instance to use its built-in BPMN elements.
821
+ During mounting, the plugin automatically calls `register` to add relevant BPMN elements to LogicFlow and sets `bpmn:sequenceFlow` as the default edge type on the canvas.
822
+
823
+ Whether to use `bpmn:sequenceFlow` as the default edge type can be controlled via configuration. If you do not want BPMN edges as the default, set `customBpmnEdge: true` when instantiating LogicFlow to disable this behavior.
824
+
825
+ ## bpmnElementsAdapter Plugin
826
+
827
+ :::info{title=Tip}
828
+ Before reading this section, it is recommended to read the [BPMN adapter](adapter.en.md) section to understand the basic features and usage of the bpmnAdapter plugin.
829
+ :::
830
+
831
+ Similar to bpmnAdapter, bpmnElementsAdapter exposes two adapters: `BPMNBaseAdapter` and `BPMNAdapter`, and two data conversion helper functions: `convertNormalToXml` and `convertXmlToNormal`.
832
+
833
+ ### BPMNBaseAdapter
834
+ **Core Capabilities**
835
+
836
+ Performs bidirectional conversion between BPMN JSON and LogicFlow, supporting synchronization of graphical information (coordinates/size/text); controls field retention, field exclusion, type mapping, and semantic conversion via the `extraProps` parameter.
837
+
838
+ **Feature Comparison with BpmnAdapter**
839
+
840
+ | Dimension | BpmnAdapter (basic) | BPMNBaseAdapter (enhanced) | Notes |
841
+ | ----------- | ----------------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------ |
842
+ | I/O | adapterIn(bpmnJson), adapterOut(graphData, retainedFields?) | adapterIn(bpmnJson, extraProps?), adapterOut(graphData, extraProps?) | Adds extraProps for finer-grained conversion |
843
+ | Elements | Supports all nodes from the BpmnElement plugin | Supports all nodes from the BPMNElements plugin | More comprehensive shape mapping |
844
+ | Event Def. | No built-in handling | Built-in timerEventDefinition in/out hooks | Auto generate/parse via definitionType/timerType/value |
845
+ | Condition | No built-in handling | Built-in conditionExpression in/out hooks | Supports both cdata and plain text expressions |
846
+ | Params | Retained fields only on export | Provides extraProps: retain/exclude fields; custom node conversion | Finer customization capability |
847
+ | Field Excl. | None | excludeFields (in/out) | Path Set, recursively filter object levels |
848
+ | Type Map | None | mapping (in/out) | Rewrite key/type names, applied recursively |
849
+
850
+ **API Differences**
851
+ - BpmnAdapter
852
+ - adapterIn(bpmnJson)
853
+ - adapterOut(graphData, retainedFields?)
854
+ - BPMNBaseAdapter
855
+ - adapterIn(bpmnJson, extraProps?)
856
+ - adapterOut(graphData, extraProps?)
857
+ - setCustomShape(type, { width, height })
858
+
859
+ ### BPMNAdapter
860
+ **Core Capabilities**
861
+
862
+ Builds on BPMNBaseAdapter to provide bidirectional XML ↔ LogicFlow conversion, also controlled via `extraProps` for field retention/exclusion, type mapping, and semantic conversion.
863
+
864
+ **Feature Comparison with BpmnXmlAdapter**
865
+
866
+ | Dimension | BpmnXmlAdapter (basic XML) | BPMNAdapter (enhanced XML) | Notes |
867
+ | --------------------------- | -------------------------------- | ---------------------------------- | ------------------------------ |
868
+ | Inheritance | Extends BpmnAdapter (basic JSON) | Extends BPMNBaseAdapter (enhanced) | Different wrapper sources |
869
+ | Illegal char pre-processing | Yes (only escapes < > & in name) | No (direct parsing) | Basic XML is more conservative |
870
+
871
+ **API Differences**
872
+ - BpmnXmlAdapter
873
+ - adapterXmlIn(bpmnData)
874
+ - If input is a string, first escape illegal characters in the name attribute (handle only <, >, &; does not affect already valid entities)
875
+ - Use lfXml2Json to convert XML to BPMN JSON
876
+ - Call base adapterIn(json) to produce GraphData (does not support extraProps; retainedFields does not apply during import)
877
+ - adapterXmlOut(data, retainedFields?)
878
+ - Call base adapterOut(data, retainedFields) to produce BPMN JSON (supports retained fields strategy only)
879
+ - Use lfJson2Xml to output an XML string (includes attribute and text escaping)
880
+ - Does not support semantic/structural customization via transformer/mapping/excludeFields
881
+ - BPMNAdapter
882
+ - adapterXmlIn(bpmnData)
883
+ - Directly use lfXml2Json to convert XML to BPMN JSON (no name attribute pre-escaping)
884
+ - Call enhanced adapterIn(json, props) to produce GraphData
885
+ - Apply extraProps configuration for attribute retention, exclusion, and transformation
886
+ - adapterXmlOut(data)
887
+ - Call enhanced adapterOut(data, props) to produce BPMN JSON
888
+ - Use lfJson2Xml to output an XML string
889
+ - Apply extraProps configuration for attribute retention, exclusion, and transformation
890
+
891
+ ### extraProps
892
+
893
+ Compared to bpmnAdapter, bpmnElementsAdapter further enhances data conversion capabilities, primarily by supporting finer-grained control via `extraProps`, including:
894
+
895
+ **Enhanced attribute backfill**
896
+
897
+ When `retainedAttrsFields` is configured, during export and subsequent import, the specified fields’ data will be backfilled into node `properties`, preventing loss of key information across conversions.
898
+
899
+ **Configurable attribute ignore mechanism**
900
+
901
+ Supports customizing which attribute fields to ignore during import and export, reducing redundancy and avoiding unnecessary fields being converted.
902
+
903
+ **Multi-granularity conversion customization**
904
+
905
+ Allows customizing node data conversion rules at different levels, for example:
906
+ - Use `mapping` to customize mapping between BPMN element types and LogicFlow node types
907
+ - Use `transformer` to deeply customize structure/format conversion between BPMN and LogicFlow
908
+
909
+ #### Configuration
910
+
911
+ <div style="height: 40px;">
912
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 24px;">
913
+ <span style="font-size: 14px;">retainedAttrsFields</span>
914
+ </p>
915
+ </div>
916
+
917
+ - Type: `string[]`
918
+ - Required: No
919
+ - Default:
920
+ ```js
921
+ ["properties", "startPoint", "endPoint", "pointsList"]
922
+ ```
923
+ - Description: Specifies fields to retain as “attributes” during import/export. Even if the matched field value is an object or array, it will be retained as an attribute (key prefixed with `-`) rather than converted into child nodes.
924
+
925
+ <div style="height: 40px;">
926
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 24px;">
927
+ <span style="font-size: 14px;">excludeFields</span>
928
+ </p>
929
+ </div>
930
+
931
+ - Type: `{ in?: Set<string>; out?: Set<string> }`
932
+ - Required: No
933
+ - Default:
934
+ ```js
935
+ {
936
+ in: [],
937
+ out: [
938
+ 'properties.panels',
939
+ 'properties.nodeSize',
940
+ 'properties.definitionId',
941
+ 'properties.timerValue',
942
+ 'properties.timerType',
943
+ 'properties.definitionType',
944
+ 'properties.parent',
945
+ 'properties.isBoundaryEventTouchingTask',
946
+ ],
947
+ }
948
+ ```
949
+ - Description: Ignore fields by path during conversion
950
+ - `in`: Set of field paths to ignore on import (BPMN → LogicFlow)
951
+ - `out`: Set of field paths to ignore on export (LogicFlow → BPMN)
952
+ - Paths use dot notation (e.g., `properties.definitionId`) and match recursively through object levels
953
+
954
+ <div style="height: 40px;">
955
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 24px;">
956
+ <span style="font-size: 14px;">transformer</span>
957
+ </p>
958
+ </div>
959
+
960
+ - Type:
961
+ ```js
962
+ {
963
+ [type: string]: {
964
+ in?: (key: string, data: any) => any;
965
+ out?: (data: any) => any;
966
+ }
967
+ }
968
+ ```
969
+ - Required: No
970
+ - Built-in defaults: `bpmn:startEvent`, `bpmn:intermediateCatchEvent`, `bpmn:intermediateThrowEvent`, `bpmn:boundaryEvent`, `bpmn:sequenceFlow`, `bpmn:timerEventDefinition`, `bpmn:conditionExpression`
971
+ - Description: Define conversion hooks for child content by element type
972
+ - `in(key, data)`: Import (BPMN → LogicFlow) parses nested child elements into flattened attributes
973
+ - `out(data)`: Export (LogicFlow → BPMN) generates nested structures or serialized fragments
974
+ - Used for semantic conversion like `timerEventDefinition` and `conditionExpression`
975
+
976
+ <div style="height: 40px;">
977
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 24px;">
978
+ <span style="font-size: 14px;">mapping</span>
979
+ </p>
980
+ </div>
981
+
982
+ - Type: `{ in?: { [key: string]: string }; out?: { [key: string]: string } }`
983
+ - Required: No
984
+ - Description: Rewrite mappings for key/type names on both ends
985
+ - `in`: Type name mapping for import (BPMN → LogicFlow); `key` is the BPMN type name, `value` is the target LF type name
986
+ - `out`: Key name mapping for export (LogicFlow → BPMN); recursively rename keys in output JSON (including type names/field names, etc.)
987
+
988
+ Order of application:
989
+ Traverse all elements, retain/exclude attributes per retainedAttrsFields and excludeFields,
990
+ then apply transformer conversions, and finally rewrite keys via mapping.
991
+
992
+ #### Usage Guide
993
+ Simply pass the `extraProps` configuration when instantiating LogicFlow.
994
+ ``` js
995
+ const lf = new LogicFlow({
996
+ plugins: [BPMNAdapter],
997
+ pluginsOptions: {
998
+ BPMNAdapter: {
999
+ extraProps: {
1000
+ // Retain the customProps attribute inside properties
1001
+ retainedAttrsFields: ['customProps'],
1002
+ // Ignore properties.customId on import; ignore properties.definitionId on export
1003
+ excludeFields: {
1004
+ in: ['properties.customId'],
1005
+ out: [
1006
+ 'properties.definitionId',
1007
+ ],
1008
+ },
1009
+ // Conversion rules for bpmn:sequenceFlow
1010
+ transformer: {
1011
+ 'bpmn:sequenceFlow': {
1012
+ in: (key, data) => {
1013
+ if (key === 'conditionExpression') {
1014
+ return data.expression;
1015
+ }
1016
+ return data;
1017
+ },
1018
+ out: (data) => ({
1019
+ conditionExpression: {
1020
+ expression: data,
1021
+ },
1022
+ }),
1023
+ },
1024
+ },
1025
+ mapping: {
1026
+ // Import: map bpmn:startEvent to StartEvent
1027
+ in: {
1028
+ 'bpmn:startEvent': 'StartEvent',
1029
+ },
1030
+ // Export: map StartEvent to bpmn:startEvent
1031
+ out: {
1032
+ 'StartEvent': 'bpmn:startEvent',
1033
+ },
1034
+ },
1035
+ },
1036
+ },
1037
+ },
1038
+ })
1039
+ ```
1040
+ **A practical conversion example**
1041
+
1042
+ Suppose there is a sequence flow element (bpmn:sequenceFlow) on the canvas with a conditional expression:
1043
+ ```json
1044
+ {
1045
+ "id": "sequenceFlow_1",
1046
+ "type": "bpmn:sequenceFlow",
1047
+ "sourceRef": "task_1",
1048
+ "targetRef": "task_2",
1049
+ "properties": {
1050
+ "expressionType": "cdata",
1051
+ "condition": "foo &gt; bar" // pre-escape &gt; to ensure XML validity
1052
+ }
1053
+ }
1054
+ ```
1055
+ Now we want to configure extraProps so that on export to BPMN XML, the condition is emitted using cdata and wrapped in a bpmn:conditionExpression element, and on import it correctly parses back to expressionType and condition. How to achieve this?
1056
+
1057
+ This involves complex data conversion, so we implement custom logic in transformer.
1058
+ First, scaffold the structure. Because this conversion involves both bpmn:sequenceFlow and bpmn:conditionExpression, define conversion rules for these two types:
1059
+ ```js
1060
+ extraProps.transformer = {
1061
+ 'bpmn:sequenceFlow': {},
1062
+ 'bpmn:conditionExpression': {}
1063
+ }
1064
+ ```
1065
+
1066
+ On export, convert expressionType and condition into child content of a bpmn:conditionExpression element, which itself is a child of bpmn:sequenceFlow. Define the out method for bpmn:sequenceFlow as follows:
1067
+ ```js
1068
+ extraProps.transformer = {
1069
+ 'bpmn:sequenceFlow': {
1070
+ out(data) { // 'data' is the bpmn:sequenceFlow element data in LogicFlow
1071
+ const { properties: { expressionType, condition } } = data;
1072
+ // Check if 'condition' exists
1073
+ if (condition) {
1074
+ // Then check whether format is cdata
1075
+ if (expressionType === 'cdata') {
1076
+ // For cdata format, wrap with CDATA
1077
+ return {
1078
+ json:
1079
+ `<bpmn:conditionExpression xsi:type="bpmn2:tFormalExpression"><![CDATA[\${${
1080
+ condition
1081
+ }}]]></bpmn:conditionExpression>`,
1082
+ };
1083
+ }
1084
+ // Otherwise, wrap as plain string
1085
+ return {
1086
+ json: `<bpmn:conditionExpression xsi:type="bpmn2:tFormalExpression">${condition}</bpmn:conditionExpression>`,
1087
+ };
1088
+ }
1089
+ // If no 'condition', return empty string
1090
+ return {
1091
+ json: '',
1092
+ };
1093
+ },
1094
+ },
1095
+ 'bpmn:conditionExpression': {}
1096
+ }
1097
+ ```
1098
+
1099
+ Executing this conversion logic produces BPMN JSON like:
1100
+
1101
+ ```js
1102
+ {
1103
+ "-id": "sequenceFlow_1",
1104
+ "-sourceRef": "Event_5d74c17",
1105
+ "-targetRef": "task_2",
1106
+ "-json": "<bpmn:conditionExpression xsi:type=\"bpmn2:tFormalExpression\"><![CDATA[${foo &gt; bar}]]></bpmn:conditionExpression>",
1107
+ "-expressionType": "cdata",
1108
+ "-condition": "foo &gt; bar",
1109
+ "-isDefaultFlow": false
1110
+ }
1111
+ ```
1112
+
1113
+ Finally convert to XML:
1114
+
1115
+ ```xml
1116
+ <bpmn:sequenceFlow id="sequenceFlow_1" sourceRef="Event_5d74c17" targetRef="task_2" expressionType="cdata" condition="foo &gt; bar" isDefaultFlow="false">
1117
+ <bpmn:conditionExpression xsi:type="bpmn2:tFormalExpression"><![CDATA[${foo &gt; bar}]]></bpmn:conditionExpression>
1118
+ </bpmn:sequenceFlow>
1119
+ ```
1120
+
1121
+ On import, convert `bpmn:conditionExpression` into `condition` and `expressionType` and backfill into the `properties` of the `bpmn:sequenceFlow` element. Define the transformer in method for bpmn:conditionExpression as follows:
1122
+
1123
+ ```js
1124
+ extraProps.transformer = {
1125
+ // ... bpmn:sequenceFlow conversion rules
1126
+ 'bpmn:conditionExpression': {
1127
+ in(_key: string, data: any) {
1128
+ let condition = '';
1129
+ let expressionType = '';
1130
+ if (data['#cdata-section']) {
1131
+ expressionType = 'cdata';
1132
+ condition = /^\$\{(.*)\}$/g.exec(data['#cdata-section'])?.[1] || '';
1133
+ } else if (data['#text']) {
1134
+ expressionType = 'normal';
1135
+ condition = data['#text'];
1136
+ }
1137
+ return {
1138
+ '-condition': condition,
1139
+ '-expressionType': expressionType,
1140
+ };
1141
+ },
1142
+ },
1143
+ }
1144
+ ```
1145
+
1146
+ First, the Adapter converts XML to BPMN JSON like:
1147
+
1148
+ ```js
1149
+ {
1150
+ "bpmn:sequenceFlow": {
1151
+ "-id": "Flow_X",
1152
+ "-sourceRef": "Node_A",
1153
+ "-targetRef": "Node_B",
1154
+ "-expressionType": "cdata",
1155
+ "-condition": "foo &gt; bar",
1156
+ "-isDefaultFlow": false,
1157
+ "bpmn:conditionExpression": {
1158
+ "-xsi:type": "bpmn2:tFormalExpression",
1159
+ "#cdata-section": "${foo &gt; bar}"
1160
+ }
1161
+ }
1162
+ }
1163
+ ```
1164
+ Then the transformer in method for bpmn:conditionExpression parses expressionType and condition and injects them into the properties of the bpmn:sequenceFlow element:
1165
+ ```json
1166
+ {
1167
+ "id": "sequenceFlow_1",
1168
+ "type": "bpmn:sequenceFlow",
1169
+ "sourceRef": "task_1",
1170
+ "targetRef": "task_2",
1171
+ "properties": {
1172
+ "expressionType": "cdata",
1173
+ "condition": "foo &gt; bar" // pre-escape &gt; to ensure XML validity
1174
+ }
1175
+ }
1176
+ ```
1177
+
1178
+ :::warning{title=Note}
1179
+ The transformer in method is only invoked when the imported node has attributes containing bpmn:, so it currently applies only to scenarios of converting child nodes to attributes.
1180
+ :::
1181
+
1182
+ ### Other Exports
1183
+ <div style="height: 60px;">
1184
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 20px;">
1185
+ <span style="font-size: 14px;">convertNormalToXml(other?)</span>
1186
+ <br/>
1187
+ <span style="font-size: 12px; color: #a4a4a4;">
1188
+ Convert normal JSON (GraphData) to XML-style JSON; supports retained fields, ignored fields, type mapping, and semantic hooks; handles arrays and <code>#text/#cdata-section/#comment</code>.
1189
+ </span>
1190
+ </p>
1191
+ </div>
1192
+
1193
+ **Parameters**<br/>
1194
+ - other *(ExtraProps)*: Optional configuration object to extend conversion behavior
1195
+ - retainedAttrsFields *(string[])*: Merged with default retained fields (default <code>["properties","startPoint","endPoint","pointsList"]</code>); matched paths retained as attributes (prefix <code>-</code>)
1196
+ - excludeFields *({ in?: Set<string>; out?: Set<string> })*: Merged with default ignore sets; matched paths on export (out) are ignored
1197
+ - transformer *({ [type: string]: { in?: (key, data) => any; out?: (data) => any } })*: Define in/out hooks for child content by element type; keys returned by out hooks are merged into the current object
1198
+ - mapping *({ in?: { [key: string]: string }; out?: { [key: string]: string } })*: Rewrite key/type names (this function itself uses transformer; mapping is applied in adapterOut final rewrite)
1199
+
1200
+ **Returns**<br/>
1201
+ - convert *(Function)*: Returns a conversion function <code>convert(object)</code>, where <code>object</code> is normal JSON containing <code>nodes/edges</code>; the return value is XML-style JSON (attribute keys prefixed with <code>-</code>)
1202
+
1203
+ **Processing rules summary**<br/>
1204
+ - Scalars and text: convert normal keys to attribute keys (prefix <code>-</code>); preserve <code>#text/#cdata-section/#comment</code> as-is
1205
+ - Retained fields: paths matching <code>retainedAttrsFields</code> are retained as attributes even if values are objects/arrays (prefix <code>-</code>)
1206
+ - Ignored fields: paths matching <code>excludeFields.out</code> are skipped
1207
+ - Semantic hooks: if the current object's <code>type</code> matches <code>transformer[type].out</code>, returned keys (e.g., <code>json</code>) are merged as sibling attributes (later written as <code>-json</code> and serialized as embedded fragments)
1208
+ - children handling: replace <code>children</code> id list with actual child node objects (lookup in nodes/edges)
1209
+
1210
+ <div style="height: 60px;">
1211
+ <p style="padding: 8px; border-left: 4px solid #598df6; font-weight: bolder; line-height: 20px;">
1212
+ <span style="font-size: 14px;">convertXmlToNormal(xmlJson)</span>
1213
+ <br/>
1214
+ <span style="font-size: 12px; color: #a4a4a4;">
1215
+ Convert XML-style JSON to normal JSON; remove attribute prefix <code>-</code> and recursively process objects, arrays, and text nodes; used for flattening and backfilling attributes during import.
1216
+ </span>
1217
+ </p>
1218
+ </div>
1219
+
1220
+ **Parameters**<br/>
1221
+ - xmlJson *(Object)*: XML-style JSON data (attribute keys start with <code>-</code>; child elements are normal keys)
1222
+
1223
+ **Returns**<br/>
1224
+ - json *(Object)*: Converted normal JSON; attribute prefixes removed (applying <code>handleAttributes</code>), arrays/objects converted recursively
1225
+
1226
+ **Usage together**<br/>
1227
+ - The result of convertNormalToXml flows into <code>adapterOut</code>, then is serialized to XML by <code>lfJson2Xml</code>
1228
+ - convertXmlToNormal is used in <code>adapterIn</code>: parse XML to normal JSON, apply <code>transformer[type].in</code> flattening, and finally write into node/edge <code>properties</code>
1229
+
1230
+ ### Usage Guide
1231
+
1232
+ 1. Include BPMNAdapter / BPMNBaseAdapter
1233
+
1234
+ :::code-group
1235
+
1236
+ ```tsx [npm]
1237
+ // Note: The following example assumes no custom BPMN nodes are registered;
1238
+ // if custom BPMN nodes are already registered, you do not need to include the bpmnElement plugin.
1239
+ import { BPMNElements, BPMNBaseAdapter, BPMNAdapter } from '@logicflow/extension'
1240
+
1241
+ LogicFlow.use(BPMNElements)
1242
+ // Choose to include BPMNAdapter or BPMNBaseAdapter as needed
1243
+ // Global usage
1244
+ LogicFlow.use(BPMNAdapter)
1245
+ // LogicFlow.use(BPMNBaseAdapter)
1246
+
1247
+ // Per-instance usage
1248
+ const lf = new LogicFlow({
1249
+ // ... // other options
1250
+ plugins: [
1251
+ BPMNElements,
1252
+ // Choose to include BpmnAdapter or BpmnXmlAdapter as needed
1253
+ BPMNAdapter,
1254
+ // BPMNBaseAdapter
1255
+ ],
1256
+ })
1257
+ ```
1258
+
1259
+ ```html [CDN]
1260
+ <!-- Note: The following example assumes no custom BPMN nodes are registered;
1261
+ if custom BPMN nodes are already registered, you do not need to include the BpmnElement plugin. -->
1262
+
1263
+ <!-- Include plugin bundle -->
1264
+ <script src="https://cdn.jsdelivr.net/npm/@logicflow/extension/dist/index.min.js"></script>
1265
+ <!-- Include plugin styles -->
1266
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@logicflow/extension/lib/style/index.min.css" />
1267
+ <div id="container"></div>
1268
+ <script>
1269
+ const { BPMNElements, BPMNAdapter, BPMNBaseAdapter } = Extension
1270
+ // Global usage
1271
+ // Choose to include BpmnAdapter or BpmnXmlAdapter as needed
1272
+ Core.default.use(BPMNElements);
1273
+ Core.default.use(BPMNAdapter);
1274
+ // Core.default.use(BPMNBaseAdapter);
1275
+ // Per-instance usage
1276
+ const lf = new Core.default({
1277
+ ..., // Other options
1278
+ plugins: [
1279
+ BPMNElements,
1280
+ // Choose to include BpmnAdapter or BpmnXmlAdapter as needed
1281
+ // BPMNAdapter,
1282
+ BPMNBaseAdapter
1283
+ ],
1284
+ })
1285
+ </script>
1286
+ ```
1287
+ :::
1288
+
1289
+ 2. Use the plugin for data conversion
1290
+ ```js
1291
+ // Render data
1292
+ lf.render({
1293
+ nodes: [
1294
+ { id: 'Event_1234567', type: 'bpmn:startEvent', x: 100, y: 100, },
1295
+ { id: 'Task_123ac56', type: 'bpmn:userTask', x: 300, y: 100, },
1296
+ { id: 'Event_fa4c699', type: 'bpmn:endEvent', x: 500, y: 100, },
1297
+ ],
1298
+ edges: [
1299
+ { id: 'Flow_12ac567', sourceNodeId: 'Event_1234567', targetNodeId: 'Task_123ac56', type: 'bpmn:sequenceFlow', },
1300
+ { id: 'Flow_fa4c689', sourceNodeId: 'Task_123ac56', targetNodeId: 'Event_fa4c699', type: 'bpmn:sequenceFlow', },
1301
+ ],
1302
+ })
1303
+ // Generate BPMN XML data and download locally
1304
+ const handleDownloadData = () => {
1305
+ const retainedFields = ['width', 'height']
1306
+ const data = lfRef.current?.getGraphData(retainedFields)
1307
+ download('logicflow.xml', data)
1308
+ }
1309
+ // Upload an XML file and render it into the LogicFlow instance
1310
+ const handleUploadData = (e) => {
1311
+ const file = e.target.files?.[0]
1312
+ const reader = new FileReader()
1313
+ reader.onload = (event) => {
1314
+ const xml = event.target?.result
1315
+ // Render XML data into the LogicFlow instance
1316
+ lf.render(xml)
1317
+ }
1318
+ reader.onerror = (error) => console.log(error)
1319
+ file && reader.readAsText(file)
1320
+ }
1321
+ ```
1322
+
1323
+ 1. Add custom conversion rules
1324
+ :::code-group
1325
+
1326
+ ```tsx [npm]
1327
+ // Note: The following example assumes no custom BPMN nodes are registered;
1328
+ // if custom BPMN nodes are already registered, you do not need to include the bpmnElement plugin.
1329
+ import { BPMNElements, BPMNBaseAdapter, BPMNAdapter } from '@logicflow/extension'
1330
+
1331
+ const extraProps = {
1332
+ // ... custom conversion rules
1333
+ };
1334
+
1335
+ LogicFlow.use(BPMNElements)
1336
+ // Choose to include BPMNAdapter or BPMNBaseAdapter as needed
1337
+ // Global usage
1338
+ LogicFlow.use(BPMNAdapter, extraProps)
1339
+ // LogicFlow.use(BPMNBaseAdapter, extraProps)
1340
+
1341
+ // Per-instance usage
1342
+ const lf = new LogicFlow({
1343
+ // ... // other options
1344
+ plugins: [
1345
+ BPMNElements,
1346
+ // Choose to include BpmnAdapter or BpmnXmlAdapter as needed
1347
+ BPMNAdapter,
1348
+ // BPMNBaseAdapter
1349
+ ],
1350
+ pluginsOptions: {
1351
+ BPMNAdapter: extraProps,
1352
+ // BPMNBaseAdapter: extraProps,
1353
+ },
1354
+ })
1355
+ ```
1356
+
1357
+ ```html [CDN]
1358
+ <!-- Note: The following example assumes no custom BPMN nodes are registered;
1359
+ if custom BPMN nodes are already registered, you do not need to include the BpmnElement plugin. -->
1360
+
1361
+ <!-- Include plugin bundle -->
1362
+ <script src="https://cdn.jsdelivr.net/npm/@logicflow/extension/dist/index.min.js"></script>
1363
+ <!-- Include plugin styles -->
1364
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@logicflow/extension/lib/style/index.min.css" />
1365
+ <div id="container"></div>
1366
+ <script>
1367
+ const { BPMNElements, BPMNAdapter, BPMNBaseAdapter } = Extension
1368
+ const extraProps = {
1369
+ // ... custom conversion rules
1370
+ };
1371
+
1372
+ // Global usage
1373
+ // Choose to include BpmnAdapter or BpmnXmlAdapter as needed
1374
+ Core.default.use(BPMNElements);
1375
+ Core.default.use(BPMNAdapter, extraProps);
1376
+ // Core.default.use(BPMNBaseAdapter, extraProps);
1377
+ // Per-instance usage
1378
+ const lf = new Core.default({
1379
+ ..., // Other options
1380
+ plugins: [
1381
+ BPMNElements,
1382
+ // Choose to include BpmnAdapter or BpmnXmlAdapter as needed
1383
+ // BPMNAdapter,
1384
+ BPMNBaseAdapter
1385
+ ],
1386
+ pluginsOptions: {
1387
+ BPMNBaseAdapter: extraProps,
1388
+ // BPMNAdapter: extraProps,
1389
+ },
1390
+ })
1391
+ </script>
1392
+ ```
1393
+ :::
1394
+
1395
+ ### Migration Guide
1396
+ > Switch from BpmnAdapter / BpmnXmlAdapter to BPMNBaseAdapter / BPMNAdapter
1397
+
1398
+ 1. Dependency replacement
1399
+ - `BpmnAdapter` → `BPMNBaseAdapter`
1400
+ - `BpmnXmlAdapter` → `BPMNAdapter`
1401
+ 2. Extra parameter variable name and passing method changes
1402
+ - Variable name change: `retainedFields` → `retainedAttrsFields`
1403
+ - Passing method change
1404
+ - Old:
1405
+ ```js
1406
+ // Pass where conversion is needed
1407
+ const data = lfRef.current?.getGraphData(retainedFields)
1408
+ ```
1409
+ - New:
1410
+ ```js
1411
+ // Pass during plugin registration
1412
+ // Global inclusion
1413
+ LogicFlow.use(BPMNBaseAdapter, {
1414
+ retainedAttrsFields,
1415
+ // Other configuration; see extraProps details below
1416
+ })
1417
+ // Per-instance inclusion
1418
+ const lf = new LogicFlow({
1419
+ plugins: [BPMNBaseAdapter],
1420
+ pluginsOptions: {
1421
+ BPMNBaseAdapter: {
1422
+ retainedAttrsFields,
1423
+ // Other configuration; see extraProps details below
1424
+ },
1425
+ },
1426
+ })
1427
+ ```