@flowgram-vue/free-layout-core 0.2.0

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 (68) hide show
  1. package/LICENSE +22 -0
  2. package/dist/index.cjs +0 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +0 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/typings.cjs +46 -0
  8. package/dist/typings.cjs.map +1 -0
  9. package/dist/typings.d.ts +1 -0
  10. package/dist/typings.js +40 -0
  11. package/dist/typings.js.map +1 -0
  12. package/package.json +78 -0
  13. package/src/composables/index.ts +24 -0
  14. package/src/composables/typings.ts +97 -0
  15. package/src/composables/use-current-dom-node.ts +18 -0
  16. package/src/composables/use-current-entity.ts +15 -0
  17. package/src/composables/use-node-render-context.ts +18 -0
  18. package/src/composables/use-node-render.ts +192 -0
  19. package/src/composables/use-playground-readonly-state.ts +25 -0
  20. package/src/composables/use-workflow-document.ts +12 -0
  21. package/src/constants.ts +17 -0
  22. package/src/entities/index.ts +8 -0
  23. package/src/entities/workflow-line-entity.ts +640 -0
  24. package/src/entities/workflow-node-entity.ts +17 -0
  25. package/src/entities/workflow-port-entity.ts +340 -0
  26. package/src/entity-datas/index.ts +8 -0
  27. package/src/entity-datas/workflow-line-render-data.ts +136 -0
  28. package/src/entity-datas/workflow-node-lines-data.ts +166 -0
  29. package/src/entity-datas/workflow-node-ports-data.ts +253 -0
  30. package/src/env.d.ts +10 -0
  31. package/src/index.ts +18 -0
  32. package/src/layout/free-layout.ts +166 -0
  33. package/src/layout/index.ts +6 -0
  34. package/src/service/index.ts +10 -0
  35. package/src/service/workflow-drag-service.ts +969 -0
  36. package/src/service/workflow-hover-service.ts +106 -0
  37. package/src/service/workflow-operation-base-service.ts +118 -0
  38. package/src/service/workflow-reset-layout-service.ts +87 -0
  39. package/src/service/workflow-select-service.ts +128 -0
  40. package/src/typings/index.ts +19 -0
  41. package/src/typings/workflow-drag.ts +51 -0
  42. package/src/typings/workflow-edge.ts +15 -0
  43. package/src/typings/workflow-json.ts +64 -0
  44. package/src/typings/workflow-line.ts +71 -0
  45. package/src/typings/workflow-node.ts +52 -0
  46. package/src/typings/workflow-operation.ts +40 -0
  47. package/src/typings/workflow-registry.ts +34 -0
  48. package/src/typings/workflow-sub-canvas.ts +15 -0
  49. package/src/utils/build-group-json.ts +47 -0
  50. package/src/utils/compose.ts +6 -0
  51. package/src/utils/fit-view.ts +21 -0
  52. package/src/utils/flow-node-form-data.ts +45 -0
  53. package/src/utils/get-anti-overlap-position.ts +44 -0
  54. package/src/utils/get-line-center.ts +22 -0
  55. package/src/utils/get-url-params.ts +50 -0
  56. package/src/utils/index.ts +29 -0
  57. package/src/utils/layout-to-positions.ts +65 -0
  58. package/src/utils/location-config-to-point.ts +40 -0
  59. package/src/utils/nanoid.ts +10 -0
  60. package/src/utils/statics.ts +27 -0
  61. package/src/vue/index.ts +6 -0
  62. package/src/vue/node-render-provider.vue +16 -0
  63. package/src/workflow-commands.ts +14 -0
  64. package/src/workflow-document-container-module.ts +50 -0
  65. package/src/workflow-document-contribution.ts +31 -0
  66. package/src/workflow-document-option.ts +148 -0
  67. package/src/workflow-document.ts +873 -0
  68. package/src/workflow-lines-manager.ts +596 -0
@@ -0,0 +1,46 @@
1
+ 'use strict';
2
+
3
+ // src/typings/workflow-json.ts
4
+ var WorkflowContentChangeType = /* @__PURE__ */ ((WorkflowContentChangeType2) => {
5
+ WorkflowContentChangeType2["ADD_NODE"] = "ADD_NODE";
6
+ WorkflowContentChangeType2["DELETE_NODE"] = "DELETE_NODE";
7
+ WorkflowContentChangeType2["MOVE_NODE"] = "MOVE_NODE";
8
+ WorkflowContentChangeType2["NODE_DATA_CHANGE"] = "NODE_DATA_CHANGE";
9
+ WorkflowContentChangeType2["ADD_LINE"] = "ADD_LINE";
10
+ WorkflowContentChangeType2["DELETE_LINE"] = "DELETE_LINE";
11
+ WorkflowContentChangeType2["LINE_DATA_CHANGE"] = "LINE_DATA_CHANGE";
12
+ WorkflowContentChangeType2["META_CHANGE"] = "META_CHANGE";
13
+ return WorkflowContentChangeType2;
14
+ })(WorkflowContentChangeType || {});
15
+
16
+ // src/typings/workflow-line.ts
17
+ var LineType = /* @__PURE__ */ ((LineType2) => {
18
+ LineType2[LineType2["BEZIER"] = 0] = "BEZIER";
19
+ LineType2[LineType2["LINE_CHART"] = 1] = "LINE_CHART";
20
+ LineType2[LineType2["STRAIGHT"] = 2] = "STRAIGHT";
21
+ return LineType2;
22
+ })(LineType || {});
23
+ var LineColors = /* @__PURE__ */ ((LineColors2) => {
24
+ LineColors2["HIDDEN"] = "var(--g-workflow-line-color-hidden,transparent)";
25
+ LineColors2["DEFUALT"] = "var(--g-workflow-line-color-default,#4d53e8)";
26
+ LineColors2["DRAWING"] = "var(--g-workflow-line-color-drawing, #5DD6E3)";
27
+ LineColors2["HOVER"] = "var(--g-workflow-line-color-hover,#37d0ff)";
28
+ LineColors2["SELECTED"] = "var(--g-workflow-line-color-selected,#37d0ff)";
29
+ LineColors2["ERROR"] = "var(--g-workflow-line-color-error,red)";
30
+ LineColors2["FLOWING"] = "var(--g-workflow-line-color-flowing,#4d53e8)";
31
+ return LineColors2;
32
+ })(LineColors || {});
33
+
34
+ // src/typings/workflow-operation.ts
35
+ var WorkflowOperationBaseService = /* @__PURE__ */ Symbol("WorkflowOperationBaseService");
36
+
37
+ // src/typings/index.ts
38
+ var URLParams = /* @__PURE__ */ Symbol("");
39
+
40
+ exports.LineColors = LineColors;
41
+ exports.LineType = LineType;
42
+ exports.URLParams = URLParams;
43
+ exports.WorkflowContentChangeType = WorkflowContentChangeType;
44
+ exports.WorkflowOperationBaseService = WorkflowOperationBaseService;
45
+ //# sourceMappingURL=typings.cjs.map
46
+ //# sourceMappingURL=typings.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/typings/workflow-json.ts","../src/typings/workflow-line.ts","../src/typings/workflow-operation.ts","../src/typings/index.ts"],"names":["WorkflowContentChangeType","LineType","LineColors"],"mappings":";;;AAcO,IAAK,yBAAA,qBAAAA,0BAAAA,KAAL;AAIL,EAAAA,2BAAA,UAAA,CAAA,GAAW,UAAA;AAIX,EAAAA,2BAAA,aAAA,CAAA,GAAc,aAAA;AAId,EAAAA,2BAAA,WAAA,CAAA,GAAY,WAAA;AAIZ,EAAAA,2BAAA,kBAAA,CAAA,GAAmB,kBAAA;AAInB,EAAAA,2BAAA,UAAA,CAAA,GAAW,UAAA;AAIX,EAAAA,2BAAA,aAAA,CAAA,GAAc,aAAA;AAId,EAAAA,2BAAA,kBAAA,CAAA,GAAmB,kBAAA;AAInB,EAAAA,2BAAA,aAAA,CAAA,GAAc,aAAA;AAhCJ,EAAA,OAAAA,0BAAAA;AAAA,CAAA,EAAA,yBAAA,IAAA,EAAA;;;ACLL,IAAK,QAAA,qBAAAC,SAAAA,KAAL;AACL,EAAAA,SAAAA,CAAAA,SAAAA,CAAA,QAAA,CAAA,GAAA,CAAA,CAAA,GAAA,QAAA;AACA,EAAAA,SAAAA,CAAAA,SAAAA,CAAA,YAAA,CAAA,GAAA,CAAA,CAAA,GAAA,YAAA;AACA,EAAAA,SAAAA,CAAAA,SAAAA,CAAA,UAAA,CAAA,GAAA,CAAA,CAAA,GAAA,UAAA;AAHU,EAAA,OAAAA,SAAAA;AAAA,CAAA,EAAA,QAAA,IAAA,EAAA;AA+BL,IAAK,UAAA,qBAAAC,WAAAA,KAAL;AACL,EAAAA,YAAA,QAAA,CAAA,GAAS,iDAAA;AACT,EAAAA,YAAA,SAAA,CAAA,GAAU,8CAAA;AACV,EAAAA,YAAA,SAAA,CAAA,GAAU,+CAAA;AACV,EAAAA,YAAA,OAAA,CAAA,GAAQ,4CAAA;AACR,EAAAA,YAAA,UAAA,CAAA,GAAW,+CAAA;AACX,EAAAA,YAAA,OAAA,CAAA,GAAQ,wCAAA;AACR,EAAAA,YAAA,SAAA,CAAA,GAAU,8CAAA;AAPA,EAAA,OAAAA,WAAAA;AAAA,CAAA,EAAA,UAAA,IAAA,EAAA;;;ACDL,IAAM,4BAAA,0BAAsC,8BAA8B;;;ACzB1E,IAAM,SAAA,0BAAmB,EAAE","file":"typings.cjs","sourcesContent":["/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { type WorkflowLineEntity, type WorkflowNodeEntity } from '../entities';\nimport { type WorkflowNodeJSON } from './workflow-node';\nimport { type WorkflowEdgeJSON } from './workflow-edge';\n\nexport interface WorkflowJSON {\n nodes: WorkflowNodeJSON[];\n edges: WorkflowEdgeJSON[];\n}\n\nexport enum WorkflowContentChangeType {\n /**\n * 添加节点\n */\n ADD_NODE = 'ADD_NODE',\n /**\n * 删除节点\n */\n DELETE_NODE = 'DELETE_NODE',\n /**\n * 移动节点\n */\n MOVE_NODE = 'MOVE_NODE',\n /**\n * 节点数据更新 (表单引擎数据 或者 extInfo 数据)\n */\n NODE_DATA_CHANGE = 'NODE_DATA_CHANGE',\n /**\n * 添加线条\n */\n ADD_LINE = 'ADD_LINE',\n /**\n * 删除线条\n */\n DELETE_LINE = 'DELETE_LINE',\n /**\n * 线条数据修改\n */\n LINE_DATA_CHANGE = 'LINE_DATA_CHANGE',\n /**\n * 节点Meta信息变更\n */\n META_CHANGE = 'META_CHANGE',\n}\n\nexport interface WorkflowContentChangeEvent {\n type: WorkflowContentChangeType;\n /**\n * 当前触发的元素的json数据,toJSON 需要主动触发\n */\n toJSON: () => any;\n /**\n * oldValue\n */\n oldValue?: any;\n /*\n * 当前的事件的 entity\n */\n entity: WorkflowNodeEntity | WorkflowLineEntity;\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport type { Rectangle, IPoint } from '@flowgram-vue/utils';\n\nimport { type WorkflowLineEntity } from '../entities';\n\nexport enum LineType {\n BEZIER, // 贝塞尔曲线\n LINE_CHART, // 折叠线\n STRAIGHT, // 直线\n}\n\nexport type LineRenderType = LineType | string;\n\nexport type LinePointLocation = 'left' | 'top' | 'right' | 'bottom';\n\nexport interface LinePoint {\n x: number;\n y: number;\n location: LinePointLocation;\n}\n\nexport interface LinePosition {\n from: LinePoint;\n to: LinePoint;\n}\n\nexport interface LineColor {\n hidden: string;\n default: string;\n drawing: string;\n hovered: string;\n selected: string;\n error: string;\n flowing: string;\n}\n\nexport enum LineColors {\n HIDDEN = 'var(--g-workflow-line-color-hidden,transparent)', // 隐藏线条\n DEFUALT = 'var(--g-workflow-line-color-default,#4d53e8)',\n DRAWING = 'var(--g-workflow-line-color-drawing, #5DD6E3)', // '#b5bbf8', // '#9197F1',\n HOVER = 'var(--g-workflow-line-color-hover,#37d0ff)',\n SELECTED = 'var(--g-workflow-line-color-selected,#37d0ff)',\n ERROR = 'var(--g-workflow-line-color-error,red)',\n FLOWING = 'var(--g-workflow-line-color-flowing,#4d53e8)', // 流动线条,默认使用主题色\n}\n\nexport interface LineCenterPoint {\n x: number;\n y: number;\n labelX: number; // Relative to where the line begins\n labelY: number; // Relative to where the line begins\n}\n\nexport interface WorkflowLineRenderContribution {\n entity: WorkflowLineEntity;\n path: string;\n center?: LineCenterPoint;\n bounds: Rectangle;\n update: (params: { fromPos: LinePoint; toPos: LinePoint }) => void;\n calcDistance: (pos: IPoint) => number;\n}\n\nexport type WorkflowLineRenderContributionFactory = (new (\n entity: WorkflowLineEntity\n) => WorkflowLineRenderContribution) & {\n type: LineRenderType;\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { IPoint, Event } from '@flowgram-vue/utils';\nimport {\n FlowNodeEntity,\n FlowNodeEntityOrId,\n FlowOperationBaseService,\n} from '@flowgram-vue/document';\n\nimport { WorkflowJSON } from './workflow-json';\n\nexport interface NodePostionUpdateEvent {\n node: FlowNodeEntity;\n oldPosition: IPoint;\n newPosition: IPoint;\n}\n\nexport interface WorkflowOperationBaseService extends FlowOperationBaseService {\n /**\n * 节点位置更新事件\n */\n readonly onNodePostionUpdate: Event<NodePostionUpdateEvent>;\n /**\n * 更新节点位置\n * @param nodeOrId\n * @param position\n * @returns\n */\n updateNodePosition(nodeOrId: FlowNodeEntityOrId, position: IPoint): void;\n\n /**\n * 更新节点与线条\n */\n fromJSON(json: WorkflowJSON): void;\n}\n\nexport const WorkflowOperationBaseService = Symbol('WorkflowOperationBaseService');\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport * from './workflow-json';\nexport * from './workflow-edge';\nexport * from './workflow-node';\nexport * from './workflow-registry';\nexport * from './workflow-line';\nexport * from './workflow-sub-canvas';\nexport * from './workflow-operation';\nexport * from './workflow-drag';\n\nexport const URLParams = Symbol('');\n\nexport interface URLParams {\n [key: string]: string;\n}\n"]}
@@ -0,0 +1 @@
1
+ export * from '../src/typings/index';
@@ -0,0 +1,40 @@
1
+ // src/typings/workflow-json.ts
2
+ var WorkflowContentChangeType = /* @__PURE__ */ ((WorkflowContentChangeType2) => {
3
+ WorkflowContentChangeType2["ADD_NODE"] = "ADD_NODE";
4
+ WorkflowContentChangeType2["DELETE_NODE"] = "DELETE_NODE";
5
+ WorkflowContentChangeType2["MOVE_NODE"] = "MOVE_NODE";
6
+ WorkflowContentChangeType2["NODE_DATA_CHANGE"] = "NODE_DATA_CHANGE";
7
+ WorkflowContentChangeType2["ADD_LINE"] = "ADD_LINE";
8
+ WorkflowContentChangeType2["DELETE_LINE"] = "DELETE_LINE";
9
+ WorkflowContentChangeType2["LINE_DATA_CHANGE"] = "LINE_DATA_CHANGE";
10
+ WorkflowContentChangeType2["META_CHANGE"] = "META_CHANGE";
11
+ return WorkflowContentChangeType2;
12
+ })(WorkflowContentChangeType || {});
13
+
14
+ // src/typings/workflow-line.ts
15
+ var LineType = /* @__PURE__ */ ((LineType2) => {
16
+ LineType2[LineType2["BEZIER"] = 0] = "BEZIER";
17
+ LineType2[LineType2["LINE_CHART"] = 1] = "LINE_CHART";
18
+ LineType2[LineType2["STRAIGHT"] = 2] = "STRAIGHT";
19
+ return LineType2;
20
+ })(LineType || {});
21
+ var LineColors = /* @__PURE__ */ ((LineColors2) => {
22
+ LineColors2["HIDDEN"] = "var(--g-workflow-line-color-hidden,transparent)";
23
+ LineColors2["DEFUALT"] = "var(--g-workflow-line-color-default,#4d53e8)";
24
+ LineColors2["DRAWING"] = "var(--g-workflow-line-color-drawing, #5DD6E3)";
25
+ LineColors2["HOVER"] = "var(--g-workflow-line-color-hover,#37d0ff)";
26
+ LineColors2["SELECTED"] = "var(--g-workflow-line-color-selected,#37d0ff)";
27
+ LineColors2["ERROR"] = "var(--g-workflow-line-color-error,red)";
28
+ LineColors2["FLOWING"] = "var(--g-workflow-line-color-flowing,#4d53e8)";
29
+ return LineColors2;
30
+ })(LineColors || {});
31
+
32
+ // src/typings/workflow-operation.ts
33
+ var WorkflowOperationBaseService = /* @__PURE__ */ Symbol("WorkflowOperationBaseService");
34
+
35
+ // src/typings/index.ts
36
+ var URLParams = /* @__PURE__ */ Symbol("");
37
+
38
+ export { LineColors, LineType, URLParams, WorkflowContentChangeType, WorkflowOperationBaseService };
39
+ //# sourceMappingURL=typings.js.map
40
+ //# sourceMappingURL=typings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/typings/workflow-json.ts","../src/typings/workflow-line.ts","../src/typings/workflow-operation.ts","../src/typings/index.ts"],"names":["WorkflowContentChangeType","LineType","LineColors"],"mappings":";AAcO,IAAK,yBAAA,qBAAAA,0BAAAA,KAAL;AAIL,EAAAA,2BAAA,UAAA,CAAA,GAAW,UAAA;AAIX,EAAAA,2BAAA,aAAA,CAAA,GAAc,aAAA;AAId,EAAAA,2BAAA,WAAA,CAAA,GAAY,WAAA;AAIZ,EAAAA,2BAAA,kBAAA,CAAA,GAAmB,kBAAA;AAInB,EAAAA,2BAAA,UAAA,CAAA,GAAW,UAAA;AAIX,EAAAA,2BAAA,aAAA,CAAA,GAAc,aAAA;AAId,EAAAA,2BAAA,kBAAA,CAAA,GAAmB,kBAAA;AAInB,EAAAA,2BAAA,aAAA,CAAA,GAAc,aAAA;AAhCJ,EAAA,OAAAA,0BAAAA;AAAA,CAAA,EAAA,yBAAA,IAAA,EAAA;;;ACLL,IAAK,QAAA,qBAAAC,SAAAA,KAAL;AACL,EAAAA,SAAAA,CAAAA,SAAAA,CAAA,QAAA,CAAA,GAAA,CAAA,CAAA,GAAA,QAAA;AACA,EAAAA,SAAAA,CAAAA,SAAAA,CAAA,YAAA,CAAA,GAAA,CAAA,CAAA,GAAA,YAAA;AACA,EAAAA,SAAAA,CAAAA,SAAAA,CAAA,UAAA,CAAA,GAAA,CAAA,CAAA,GAAA,UAAA;AAHU,EAAA,OAAAA,SAAAA;AAAA,CAAA,EAAA,QAAA,IAAA,EAAA;AA+BL,IAAK,UAAA,qBAAAC,WAAAA,KAAL;AACL,EAAAA,YAAA,QAAA,CAAA,GAAS,iDAAA;AACT,EAAAA,YAAA,SAAA,CAAA,GAAU,8CAAA;AACV,EAAAA,YAAA,SAAA,CAAA,GAAU,+CAAA;AACV,EAAAA,YAAA,OAAA,CAAA,GAAQ,4CAAA;AACR,EAAAA,YAAA,UAAA,CAAA,GAAW,+CAAA;AACX,EAAAA,YAAA,OAAA,CAAA,GAAQ,wCAAA;AACR,EAAAA,YAAA,SAAA,CAAA,GAAU,8CAAA;AAPA,EAAA,OAAAA,WAAAA;AAAA,CAAA,EAAA,UAAA,IAAA,EAAA;;;ACDL,IAAM,4BAAA,0BAAsC,8BAA8B;;;ACzB1E,IAAM,SAAA,0BAAmB,EAAE","file":"typings.js","sourcesContent":["/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { type WorkflowLineEntity, type WorkflowNodeEntity } from '../entities';\nimport { type WorkflowNodeJSON } from './workflow-node';\nimport { type WorkflowEdgeJSON } from './workflow-edge';\n\nexport interface WorkflowJSON {\n nodes: WorkflowNodeJSON[];\n edges: WorkflowEdgeJSON[];\n}\n\nexport enum WorkflowContentChangeType {\n /**\n * 添加节点\n */\n ADD_NODE = 'ADD_NODE',\n /**\n * 删除节点\n */\n DELETE_NODE = 'DELETE_NODE',\n /**\n * 移动节点\n */\n MOVE_NODE = 'MOVE_NODE',\n /**\n * 节点数据更新 (表单引擎数据 或者 extInfo 数据)\n */\n NODE_DATA_CHANGE = 'NODE_DATA_CHANGE',\n /**\n * 添加线条\n */\n ADD_LINE = 'ADD_LINE',\n /**\n * 删除线条\n */\n DELETE_LINE = 'DELETE_LINE',\n /**\n * 线条数据修改\n */\n LINE_DATA_CHANGE = 'LINE_DATA_CHANGE',\n /**\n * 节点Meta信息变更\n */\n META_CHANGE = 'META_CHANGE',\n}\n\nexport interface WorkflowContentChangeEvent {\n type: WorkflowContentChangeType;\n /**\n * 当前触发的元素的json数据,toJSON 需要主动触发\n */\n toJSON: () => any;\n /**\n * oldValue\n */\n oldValue?: any;\n /*\n * 当前的事件的 entity\n */\n entity: WorkflowNodeEntity | WorkflowLineEntity;\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport type { Rectangle, IPoint } from '@flowgram-vue/utils';\n\nimport { type WorkflowLineEntity } from '../entities';\n\nexport enum LineType {\n BEZIER, // 贝塞尔曲线\n LINE_CHART, // 折叠线\n STRAIGHT, // 直线\n}\n\nexport type LineRenderType = LineType | string;\n\nexport type LinePointLocation = 'left' | 'top' | 'right' | 'bottom';\n\nexport interface LinePoint {\n x: number;\n y: number;\n location: LinePointLocation;\n}\n\nexport interface LinePosition {\n from: LinePoint;\n to: LinePoint;\n}\n\nexport interface LineColor {\n hidden: string;\n default: string;\n drawing: string;\n hovered: string;\n selected: string;\n error: string;\n flowing: string;\n}\n\nexport enum LineColors {\n HIDDEN = 'var(--g-workflow-line-color-hidden,transparent)', // 隐藏线条\n DEFUALT = 'var(--g-workflow-line-color-default,#4d53e8)',\n DRAWING = 'var(--g-workflow-line-color-drawing, #5DD6E3)', // '#b5bbf8', // '#9197F1',\n HOVER = 'var(--g-workflow-line-color-hover,#37d0ff)',\n SELECTED = 'var(--g-workflow-line-color-selected,#37d0ff)',\n ERROR = 'var(--g-workflow-line-color-error,red)',\n FLOWING = 'var(--g-workflow-line-color-flowing,#4d53e8)', // 流动线条,默认使用主题色\n}\n\nexport interface LineCenterPoint {\n x: number;\n y: number;\n labelX: number; // Relative to where the line begins\n labelY: number; // Relative to where the line begins\n}\n\nexport interface WorkflowLineRenderContribution {\n entity: WorkflowLineEntity;\n path: string;\n center?: LineCenterPoint;\n bounds: Rectangle;\n update: (params: { fromPos: LinePoint; toPos: LinePoint }) => void;\n calcDistance: (pos: IPoint) => number;\n}\n\nexport type WorkflowLineRenderContributionFactory = (new (\n entity: WorkflowLineEntity\n) => WorkflowLineRenderContribution) & {\n type: LineRenderType;\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { IPoint, Event } from '@flowgram-vue/utils';\nimport {\n FlowNodeEntity,\n FlowNodeEntityOrId,\n FlowOperationBaseService,\n} from '@flowgram-vue/document';\n\nimport { WorkflowJSON } from './workflow-json';\n\nexport interface NodePostionUpdateEvent {\n node: FlowNodeEntity;\n oldPosition: IPoint;\n newPosition: IPoint;\n}\n\nexport interface WorkflowOperationBaseService extends FlowOperationBaseService {\n /**\n * 节点位置更新事件\n */\n readonly onNodePostionUpdate: Event<NodePostionUpdateEvent>;\n /**\n * 更新节点位置\n * @param nodeOrId\n * @param position\n * @returns\n */\n updateNodePosition(nodeOrId: FlowNodeEntityOrId, position: IPoint): void;\n\n /**\n * 更新节点与线条\n */\n fromJSON(json: WorkflowJSON): void;\n}\n\nexport const WorkflowOperationBaseService = Symbol('WorkflowOperationBaseService');\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport * from './workflow-json';\nexport * from './workflow-edge';\nexport * from './workflow-node';\nexport * from './workflow-registry';\nexport * from './workflow-line';\nexport * from './workflow-sub-canvas';\nexport * from './workflow-operation';\nexport * from './workflow-drag';\n\nexport const URLParams = Symbol('');\n\nexport interface URLParams {\n [key: string]: string;\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@flowgram-vue/free-layout-core",
3
+ "version": "0.2.0",
4
+ "homepage": "https://flowgram.ai/",
5
+ "repository": "https://github.com/Crayon-hua/flowgram-vue",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ },
14
+ "./typings": {
15
+ "types": "./dist/typings.d.ts",
16
+ "import": "./dist/typings.js",
17
+ "require": "./dist/typings.cjs"
18
+ }
19
+ },
20
+ "main": "./dist/index.cjs",
21
+ "module": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "typesVersions": {
24
+ "*": {
25
+ "typings": [
26
+ "./src/typings/index.ts"
27
+ ]
28
+ }
29
+ },
30
+ "files": [
31
+ "src",
32
+ "dist"
33
+ ],
34
+ "dependencies": {
35
+ "inversify": "^6.0.1",
36
+ "reflect-metadata": "~0.2.2",
37
+ "lodash-es": "^4.17.21",
38
+ "nanoid": "^5.0.9",
39
+ "@flowgram-vue/core": "0.2.0",
40
+ "@flowgram-vue/reactive": "0.2.0",
41
+ "@flowgram-vue/document": "0.2.0",
42
+ "@flowgram-vue/utils": "0.2.0",
43
+ "@flowgram-vue/node": "0.2.0",
44
+ "@flowgram-vue/form-core": "0.2.0"
45
+ },
46
+ "peerDependencies": {
47
+ "vue": "^3.3.0"
48
+ },
49
+ "devDependencies": {
50
+ "@types/bezier-js": "4.1.3",
51
+ "@types/lodash-es": "^4.17.12",
52
+ "@types/node": "^20",
53
+ "@vitejs/plugin-vue": "^6.0.1",
54
+ "@vitest/coverage-v8": "^3.2.4",
55
+ "@vue/test-utils": "^2.4.6",
56
+ "eslint": "^9.0.0",
57
+ "jsdom": "^26.1.0",
58
+ "typescript": "^5.8.3",
59
+ "vitest": "^3.2.4",
60
+ "vue": "^3.5.18",
61
+ "@flowgram-vue/eslint-config": "0.2.0",
62
+ "@flowgram-vue/ts-config": "0.2.0",
63
+ "@flowgram-vue/build-config": "0.2.0"
64
+ },
65
+ "publishConfig": {
66
+ "access": "public",
67
+ "registry": "https://registry.npmjs.org/"
68
+ },
69
+ "scripts": {
70
+ "build": "flowgram-build",
71
+ "test": "vitest run",
72
+ "test:cov": "vitest run --coverage",
73
+ "lint": "eslint .",
74
+ "ts-check": "tsc --noEmit",
75
+ "build:fast": "flowgram-build --fast",
76
+ "build:watch": "flowgram-build --watch"
77
+ }
78
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ export {
7
+ useConfigEntity,
8
+ useService,
9
+ usePlayground,
10
+ useListenEvents,
11
+ usePlaygroundContainer,
12
+ usePlaygroundContext,
13
+ useEntities,
14
+ useEntityFromContext,
15
+ useEntityDataFromContext,
16
+ useRefresh,
17
+ } from '@flowgram-vue/core';
18
+ export * from './typings';
19
+ export * from './use-node-render';
20
+ export * from './use-node-render-context';
21
+ export * from './use-current-dom-node';
22
+ export * from './use-current-entity';
23
+ export * from './use-workflow-document';
24
+ export * from './use-playground-readonly-state';
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import type { Ref } from 'vue';
7
+ import { type NodeFormProps } from '@flowgram-vue/node';
8
+ import { FlowNodeEntity } from '@flowgram-vue/document';
9
+
10
+ import { type WorkflowPortEntity } from '../entities';
11
+
12
+ export type NodePointerEvent = MouseEvent | TouchEvent;
13
+
14
+ export interface NodeRenderReturnType {
15
+ id: string;
16
+ type: string | number;
17
+ /**
18
+ * 当前节点
19
+ */
20
+ node: FlowNodeEntity;
21
+ /**
22
+ * 节点 data 数据
23
+ */
24
+ data: any;
25
+ /**
26
+ * 更新节点 data 数据
27
+ */
28
+ updateData: (newData: any) => void;
29
+ /**
30
+ * 节点选中
31
+ */
32
+ selected: boolean;
33
+ /**
34
+ * 节点激活
35
+ */
36
+ activated: boolean;
37
+ /**
38
+ * 节点展开
39
+ */
40
+ expanded: boolean;
41
+ /**
42
+ * 触发拖拽
43
+ * @param e
44
+ */
45
+ startDrag: (e: NodePointerEvent) => void;
46
+ /**
47
+ * 当前节点的点位信息
48
+ */
49
+ ports: WorkflowPortEntity[];
50
+ /**
51
+ * 删除节点
52
+ */
53
+ deleteNode: () => void;
54
+ /**
55
+ * 选中节点
56
+ * @param e
57
+ */
58
+ selectNode: (e: MouseEvent) => void;
59
+ /**
60
+ * 全局 readonly 状态
61
+ */
62
+ readonly: boolean;
63
+ /**
64
+ * 拖拽线条的目标 node id
65
+ */
66
+ linkingNodeId: string;
67
+ /**
68
+ * 节点 ref
69
+ */
70
+ nodeRef: Ref<HTMLDivElement | null>;
71
+ /**
72
+ * 节点 focus 事件
73
+ */
74
+ onFocus: () => void;
75
+ /**
76
+ * 节点 blur 事件
77
+ */
78
+ onBlur: () => void;
79
+ /**
80
+ * 渲染表单,只有节点引擎开启才能使用
81
+ */
82
+ form: NodeFormProps<any> | undefined;
83
+ /**
84
+ * 获取节点的扩展数据
85
+ */
86
+ getExtInfo<T = any>(): T;
87
+ /**
88
+ * 更新节点的扩展数据
89
+ * @param extInfo
90
+ */
91
+ updateExtInfo<T = any>(extInfo: T, fullUpdate?: boolean): void;
92
+ /**
93
+ * 展开/收起节点
94
+ * @param expanded
95
+ */
96
+ toggleExpand(): void;
97
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { FlowNodeRenderData } from '@flowgram-vue/document';
7
+ import { useEntityFromContext } from '@flowgram-vue/core';
8
+
9
+ import { type WorkflowNodeEntity } from '../entities';
10
+
11
+ /**
12
+ * 获取当前渲染的 dom 节点
13
+ */
14
+ export function useCurrentDomNode(): HTMLDivElement {
15
+ const entity = useEntityFromContext<WorkflowNodeEntity>();
16
+ const renderData = entity.getData(FlowNodeRenderData)!;
17
+ return renderData.node;
18
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { useEntityFromContext } from '@flowgram-vue/core';
7
+
8
+ import { type WorkflowNodeEntity } from '../entities';
9
+
10
+ /**
11
+ * 获取当前节点
12
+ */
13
+ export function useCurrentEntity(): WorkflowNodeEntity {
14
+ return useEntityFromContext<WorkflowNodeEntity>();
15
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { inject, type InjectionKey } from 'vue';
7
+
8
+ import { NodeRenderReturnType } from './typings';
9
+
10
+ export const NodeRenderContextKey: InjectionKey<NodeRenderReturnType> =
11
+ Symbol('NodeRenderContext');
12
+
13
+ /** @deprecated 使用 NodeRenderContextKey */
14
+ export const NodeRenderContext = NodeRenderContextKey;
15
+
16
+ export function useNodeRenderContext(): NodeRenderReturnType {
17
+ return inject(NodeRenderContextKey, {} as NodeRenderReturnType);
18
+ }
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { inject, onBeforeUnmount, ref } from 'vue';
7
+
8
+ import { useObserve } from '@flowgram-vue/reactive';
9
+ import { getNodeForm } from '@flowgram-vue/node';
10
+ import { FlowNodeRenderData } from '@flowgram-vue/document';
11
+ import {
12
+ MouseTouchEvent,
13
+ PlaygroundEntityContextKey,
14
+ useListenEvents,
15
+ useRefresh,
16
+ useService,
17
+ } from '@flowgram-vue/core';
18
+
19
+ import { WorkflowDragService, WorkflowSelectService } from '../service';
20
+ import { type WorkflowNodeEntity } from '../entities';
21
+ import { usePlaygroundReadonlyState } from './use-playground-readonly-state';
22
+ import { type NodePointerEvent, type NodeRenderReturnType } from './typings';
23
+
24
+ function checkTargetDraggable(el: any): boolean {
25
+ return (
26
+ el &&
27
+ el.tagName !== 'INPUT' &&
28
+ el.tagName !== 'TEXTAREA' &&
29
+ !el.closest('.flow-canvas-not-draggable')
30
+ );
31
+ }
32
+ /**
33
+ * - 下面的 firefox 为了修复一个 bug
34
+ * - firefox 下 draggable 属性会影响节点 input 内容 focus:https://jsfiddle.net/Aydar/ztsvbyep/3/
35
+ * - 该 bug 在 firefox 浏览器上存在了很久,需要作兼容:https://bugzilla.mozilla.org/show_bug.cgi?id=739071
36
+ */
37
+ const isFirefox = typeof navigator !== 'undefined' && navigator?.userAgent?.includes?.('Firefox');
38
+
39
+ export function useNodeRender(nodeFromProps?: WorkflowNodeEntity): NodeRenderReturnType {
40
+ const node =
41
+ nodeFromProps || (inject(PlaygroundEntityContextKey, undefined) as WorkflowNodeEntity);
42
+ const renderData = node.getData(FlowNodeRenderData)!;
43
+ const portsData = node.ports!;
44
+ const readonly = usePlaygroundReadonlyState();
45
+ const dragService = useService<WorkflowDragService>(WorkflowDragService);
46
+ const selectionService = useService<WorkflowSelectService>(WorkflowSelectService);
47
+ const isDragging = { current: false };
48
+ const formValueDependRef = { current: false };
49
+ const refresh = useRefresh();
50
+ const nodeRef = ref<HTMLDivElement | null>(null);
51
+ const linkingNodeId = ref('');
52
+
53
+ const lineDragDisposable = dragService.onDragLineEventChange(({ type, onDragNodeId }) => {
54
+ if (type === 'onDrag') {
55
+ linkingNodeId.value = onDragNodeId || '';
56
+ } else {
57
+ linkingNodeId.value = '';
58
+ }
59
+ });
60
+
61
+ const startDrag = (e: NodePointerEvent) => {
62
+ MouseTouchEvent.preventDefault(e);
63
+ if (!selectionService.isSelected(node.id)) {
64
+ selectNode(e as MouseEvent);
65
+ }
66
+ if (!MouseTouchEvent.isTouchEvent(e)) {
67
+ // 输入框不能拖拽
68
+ if (!checkTargetDraggable(e.target) || !checkTargetDraggable(document.activeElement)) {
69
+ return;
70
+ }
71
+ }
72
+ isDragging.current = true;
73
+ // 拖拽选中的节点
74
+ dragService.startDragSelectedNodes(e)?.finally(() =>
75
+ setTimeout(() => {
76
+ isDragging.current = false;
77
+ })
78
+ );
79
+ };
80
+ /**
81
+ * 单选节点
82
+ */
83
+ const selectNode = (e: MouseEvent) => {
84
+ // 触发了拖拽就不要再触发单选
85
+ if (isDragging.current) {
86
+ return;
87
+ }
88
+ // 追加选择
89
+ if (e.shiftKey) {
90
+ selectionService.toggleSelect(node);
91
+ } else {
92
+ selectionService.selectNode(node);
93
+ }
94
+ if (e.target) {
95
+ (e.target as HTMLDivElement).focus();
96
+ }
97
+ };
98
+ const deleteNode = () => node.dispose();
99
+ // 监听端口变化
100
+ useListenEvents(portsData.onDataChange);
101
+
102
+ const onFocus = () => {
103
+ if (isFirefox) {
104
+ nodeRef.value?.setAttribute('draggable', 'false');
105
+ }
106
+ };
107
+ const onBlur = () => {
108
+ if (isFirefox) {
109
+ nodeRef.value?.setAttribute('draggable', 'true');
110
+ }
111
+ };
112
+ const getExtInfo = () => node.getExtInfo() as any;
113
+ const updateExtInfo = (data: any, fullUpdate?: boolean) => {
114
+ node.updateExtInfo(data, fullUpdate);
115
+ };
116
+ const form = getNodeForm(node);
117
+ // Listen FormState change
118
+ const formState = useObserve<any>(form?.state);
119
+ const toggleExpand = () => {
120
+ renderData.toggleExpand();
121
+ };
122
+ const formValuesDisposable = form?.onFormValuesChange(() => {
123
+ if (formValueDependRef.current) {
124
+ refresh();
125
+ }
126
+ });
127
+
128
+ onBeforeUnmount(() => {
129
+ lineDragDisposable.dispose();
130
+ formValuesDisposable?.dispose();
131
+ });
132
+
133
+ return {
134
+ id: node.id,
135
+ type: node.flowNodeType,
136
+ get data() {
137
+ if (form) {
138
+ formValueDependRef.current = true;
139
+ return form.values;
140
+ }
141
+ return getExtInfo();
142
+ },
143
+ updateData(values: any) {
144
+ if (form) {
145
+ form.updateFormValues(values);
146
+ } else {
147
+ updateExtInfo(values, true);
148
+ }
149
+ },
150
+ node,
151
+ get selected() {
152
+ return selectionService.isSelected(node.id);
153
+ },
154
+ get activated() {
155
+ return selectionService.isActivated(node.id);
156
+ },
157
+ get expanded() {
158
+ return renderData.expanded;
159
+ },
160
+ startDrag,
161
+ get ports() {
162
+ return portsData.allPorts;
163
+ },
164
+ deleteNode,
165
+ selectNode,
166
+ get readonly() {
167
+ return readonly.value;
168
+ },
169
+ get linkingNodeId() {
170
+ return linkingNodeId.value;
171
+ },
172
+ nodeRef,
173
+ onFocus,
174
+ onBlur,
175
+ getExtInfo,
176
+ updateExtInfo,
177
+ toggleExpand,
178
+ get form() {
179
+ if (!form) return undefined;
180
+ return {
181
+ ...form,
182
+ get values() {
183
+ formValueDependRef.current = true;
184
+ return form.values!;
185
+ },
186
+ get state() {
187
+ return formState;
188
+ },
189
+ };
190
+ },
191
+ };
192
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { onBeforeUnmount, type Ref, shallowRef } from 'vue';
7
+
8
+ import { usePlayground } from '@flowgram-vue/core';
9
+ import { type Disposable } from '@flowgram-vue/utils';
10
+
11
+ /**
12
+ * 获取 readonly 状态。返回 Ref,listenChange 为 true 时订阅 playground 只读变化。
13
+ */
14
+ export function usePlaygroundReadonlyState(listenChange?: boolean): Ref<boolean> {
15
+ const playground = usePlayground();
16
+ const readonly = shallowRef(playground.config.readonly);
17
+ let dispose: Disposable | undefined;
18
+ if (listenChange) {
19
+ dispose = playground.config.onReadonlyOrDisabledChange(() => {
20
+ readonly.value = playground.config.readonly;
21
+ });
22
+ }
23
+ onBeforeUnmount(() => dispose?.dispose());
24
+ return readonly;
25
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { useService } from '@flowgram-vue/core';
7
+
8
+ import { WorkflowDocument } from '../workflow-document';
9
+
10
+ export function useWorkflowDocument(): WorkflowDocument {
11
+ return useService<WorkflowDocument>(WorkflowDocument);
12
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ export enum EditorCursorState {
7
+ GRAB = 'GRAB',
8
+ SELECT = 'SELECT',
9
+ }
10
+
11
+ export enum InteractiveType {
12
+ /** 鼠标优先交互模式 */
13
+ MOUSE = 'MOUSE',
14
+
15
+ /** 触控板优先交互模式 */
16
+ PAD = 'PAD',
17
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ export * from './workflow-node-entity';
7
+ export * from './workflow-line-entity';
8
+ export * from './workflow-port-entity';