@flowgram-vue/fixed-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.
- package/LICENSE +22 -0
- package/dist/index.cjs +2327 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.js +2323 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
- package/src/activities/block-icon.ts +55 -0
- package/src/activities/block-order-icon.ts +64 -0
- package/src/activities/block.ts +192 -0
- package/src/activities/break.ts +14 -0
- package/src/activities/dynamic-split.ts +94 -0
- package/src/activities/empty.ts +35 -0
- package/src/activities/end.ts +26 -0
- package/src/activities/index.ts +24 -0
- package/src/activities/inline-blocks.ts +197 -0
- package/src/activities/input.ts +152 -0
- package/src/activities/loop-extends/constants.ts +25 -0
- package/src/activities/loop-extends/index.ts +10 -0
- package/src/activities/loop-extends/loop-empty-branch.ts +60 -0
- package/src/activities/loop-extends/loop-inline-blocks.ts +140 -0
- package/src/activities/loop-extends/loop-left-empty-block.ts +43 -0
- package/src/activities/loop-extends/loop-right-empty-block.ts +18 -0
- package/src/activities/loop.ts +198 -0
- package/src/activities/multi-inputs.ts +98 -0
- package/src/activities/multi-outputs.ts +65 -0
- package/src/activities/output.ts +18 -0
- package/src/activities/root.ts +23 -0
- package/src/activities/simple-split.ts +47 -0
- package/src/activities/slot/constants.ts +56 -0
- package/src/activities/slot/extends/index.ts +8 -0
- package/src/activities/slot/extends/slot-block.ts +229 -0
- package/src/activities/slot/extends/slot-icon.ts +32 -0
- package/src/activities/slot/extends/slot-inline-blocks.ts +102 -0
- package/src/activities/slot/index.ts +8 -0
- package/src/activities/slot/slot.ts +108 -0
- package/src/activities/slot/typings.ts +13 -0
- package/src/activities/slot/utils/create.ts +105 -0
- package/src/activities/slot/utils/layout.ts +49 -0
- package/src/activities/slot/utils/node.ts +38 -0
- package/src/activities/slot/utils/transition.ts +222 -0
- package/src/activities/start.ts +21 -0
- package/src/activities/static-split.ts +29 -0
- package/src/activities/try-catch-extends/catch-block.ts +78 -0
- package/src/activities/try-catch-extends/catch-inline-blocks.ts +122 -0
- package/src/activities/try-catch-extends/constants.ts +27 -0
- package/src/activities/try-catch-extends/index.ts +11 -0
- package/src/activities/try-catch-extends/main-inline-blocks.ts +147 -0
- package/src/activities/try-catch-extends/try-block.ts +26 -0
- package/src/activities/try-catch-extends/try-slot.ts +48 -0
- package/src/activities/try-catch.ts +176 -0
- package/src/fixed-layout-container-module.ts +20 -0
- package/src/flow-registers.ts +117 -0
- package/src/index.ts +45 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FlowNodeRegistry, FlowNodeBaseType, getDefaultSpacing } from '@flowgram-vue/document';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
drawStraightAdder,
|
|
10
|
+
drawStraightLine,
|
|
11
|
+
getInputPoint,
|
|
12
|
+
getOutputPoint,
|
|
13
|
+
} from './utils/transition';
|
|
14
|
+
import { insideSlot } from './utils/node';
|
|
15
|
+
import { getAllPortsMiddle } from './utils/layout';
|
|
16
|
+
import { createSlotFromJSON } from './utils/create';
|
|
17
|
+
import { SlotInlineBlocksRegistry, SlotIconRegistry } from './extends';
|
|
18
|
+
import {
|
|
19
|
+
SLOT_NODE_LAST_SPACING,
|
|
20
|
+
SLOT_SPACING,
|
|
21
|
+
SLOT_START_DISTANCE,
|
|
22
|
+
SlotSpacingKey,
|
|
23
|
+
} from './constants';
|
|
24
|
+
|
|
25
|
+
export const SlotRegistry: FlowNodeRegistry = {
|
|
26
|
+
type: FlowNodeBaseType.SLOT,
|
|
27
|
+
extend: 'block',
|
|
28
|
+
meta: {
|
|
29
|
+
// Slot 节点内部暂时不允许拖拽
|
|
30
|
+
draggable: (node) => !insideSlot(node),
|
|
31
|
+
hidden: true,
|
|
32
|
+
spacing: (node) => getDefaultSpacing(node.entity, SlotSpacingKey.SLOT_SPACING, SLOT_SPACING),
|
|
33
|
+
padding: (node) => ({
|
|
34
|
+
left: 0,
|
|
35
|
+
right: node.collapsed
|
|
36
|
+
? getDefaultSpacing(node.entity, SlotSpacingKey.SLOT_START_DISTANCE, SLOT_START_DISTANCE)
|
|
37
|
+
: 0,
|
|
38
|
+
bottom: !insideSlot(node.entity) && node.isLast ? SLOT_NODE_LAST_SPACING : 0,
|
|
39
|
+
top: 0,
|
|
40
|
+
}),
|
|
41
|
+
copyDisable: false,
|
|
42
|
+
defaultExpanded: false,
|
|
43
|
+
},
|
|
44
|
+
/**
|
|
45
|
+
* 业务通常需要重载方法
|
|
46
|
+
*/
|
|
47
|
+
onCreate: createSlotFromJSON,
|
|
48
|
+
getLines: (transition) => [
|
|
49
|
+
...(!insideSlot(transition.entity) ? drawStraightLine(transition) : []),
|
|
50
|
+
],
|
|
51
|
+
getLabels: (transition) => [
|
|
52
|
+
...(!insideSlot(transition.entity) ? drawStraightAdder(transition) : []),
|
|
53
|
+
],
|
|
54
|
+
getInputPoint,
|
|
55
|
+
getOutputPoint,
|
|
56
|
+
onAfterUpdateLocalTransform(transform) {
|
|
57
|
+
const { isVertical } = transform.entity;
|
|
58
|
+
|
|
59
|
+
if (!isVertical) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const icon = transform.firstChild;
|
|
64
|
+
const inlineBlocks = transform.lastChild;
|
|
65
|
+
|
|
66
|
+
if (!icon || !inlineBlocks) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const iconSize = icon.localBounds.height;
|
|
71
|
+
const inlineBlocksSize = inlineBlocks.localBounds.height;
|
|
72
|
+
|
|
73
|
+
if (transform.collapsed || !inlineBlocks) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// 所有 Ports 的中间点
|
|
78
|
+
const portsMiddle = getAllPortsMiddle(inlineBlocks);
|
|
79
|
+
|
|
80
|
+
icon.entity.clearMemoLocal();
|
|
81
|
+
inlineBlocks.entity.clearMemoLocal();
|
|
82
|
+
|
|
83
|
+
if (iconSize / 2 + portsMiddle > inlineBlocksSize || !inlineBlocks.children.length) {
|
|
84
|
+
icon.transform.update({
|
|
85
|
+
position: { x: icon.transform.position.x, y: 0 },
|
|
86
|
+
});
|
|
87
|
+
inlineBlocks.transform.update({
|
|
88
|
+
position: {
|
|
89
|
+
x: inlineBlocks.transform.position.x,
|
|
90
|
+
y: Math.max(iconSize / 2 - inlineBlocksSize / 2, 0),
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
inlineBlocks.transform.update({
|
|
98
|
+
position: { x: inlineBlocks.transform.position.x, y: 0 },
|
|
99
|
+
});
|
|
100
|
+
icon?.transform.update({
|
|
101
|
+
position: {
|
|
102
|
+
x: icon.transform.position.x,
|
|
103
|
+
y: Math.max(portsMiddle - iconSize / 2, 0), // 所有 port 的中间点
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
},
|
|
107
|
+
extendChildRegistries: [SlotIconRegistry, SlotInlineBlocksRegistry],
|
|
108
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FlowNodeBaseType } from '@flowgram-vue/document';
|
|
7
|
+
|
|
8
|
+
export enum SlotNodeType {
|
|
9
|
+
Slot = FlowNodeBaseType.SLOT,
|
|
10
|
+
SlotBlock = FlowNodeBaseType.SLOT_BLOCK,
|
|
11
|
+
SlotInlineBlocks = 'slotInlineBlocks',
|
|
12
|
+
SlotBlockInlineBlocks = 'slotBlockInlineBlocks',
|
|
13
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FlowNodeBaseType } from '@flowgram-vue/document';
|
|
7
|
+
import { type FlowNodeEntity } from '@flowgram-vue/document';
|
|
8
|
+
import { FlowNodeJSON } from '@flowgram-vue/document';
|
|
9
|
+
|
|
10
|
+
import { SlotNodeType } from '../typings';
|
|
11
|
+
|
|
12
|
+
// Slot 样例数据
|
|
13
|
+
// const mock = {
|
|
14
|
+
// type: 'slot',
|
|
15
|
+
// id: 'reactor_parent',
|
|
16
|
+
// blocks: [
|
|
17
|
+
// {
|
|
18
|
+
// id: 'port_LnSdK',
|
|
19
|
+
// blocks: [{ type: 'Slot', id: 'reactor_child' }],
|
|
20
|
+
// },
|
|
21
|
+
// {
|
|
22
|
+
// id: 'port_60X7U',
|
|
23
|
+
// },
|
|
24
|
+
// {
|
|
25
|
+
// id: 'port_JWhcm',
|
|
26
|
+
// },
|
|
27
|
+
// {
|
|
28
|
+
// id: 'port_scHWa',
|
|
29
|
+
// },
|
|
30
|
+
// ],
|
|
31
|
+
// };
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 创建 Slot 子节点
|
|
35
|
+
* - Slot
|
|
36
|
+
* - SlotBlockIcon
|
|
37
|
+
* - SlotInlineBlocks
|
|
38
|
+
* - SlotBlock 1
|
|
39
|
+
* - SlotBlockIcon 1
|
|
40
|
+
* - ChildSlot 1
|
|
41
|
+
* - ChildSlot 2
|
|
42
|
+
* - SlotBlock 2
|
|
43
|
+
*
|
|
44
|
+
* 范例数据:
|
|
45
|
+
* {
|
|
46
|
+
* type: 'Slot',
|
|
47
|
+
* id: 'reactor_parent',
|
|
48
|
+
* blocks: [
|
|
49
|
+
* {
|
|
50
|
+
* id: 'port_LnSdK',
|
|
51
|
+
* blocks: [{ type: 'Slot', id: 'reactor_child' }],
|
|
52
|
+
* },
|
|
53
|
+
* {
|
|
54
|
+
* id: 'port_60X7U',
|
|
55
|
+
* }
|
|
56
|
+
* ],
|
|
57
|
+
* }
|
|
58
|
+
*
|
|
59
|
+
*/
|
|
60
|
+
export const createSlotFromJSON = (node: FlowNodeEntity, json: FlowNodeJSON): FlowNodeEntity[] => {
|
|
61
|
+
const { document } = node;
|
|
62
|
+
|
|
63
|
+
const addedNodes: FlowNodeEntity[] = [];
|
|
64
|
+
|
|
65
|
+
// 块列表开始节点,用来展示块的按钮
|
|
66
|
+
const blockIconNode = document.addNode({
|
|
67
|
+
id: `$slotIcon$${node.id}`,
|
|
68
|
+
type: FlowNodeBaseType.BLOCK_ICON,
|
|
69
|
+
originParent: node,
|
|
70
|
+
parent: node,
|
|
71
|
+
});
|
|
72
|
+
const inlineBlocksNode = document.addNode({
|
|
73
|
+
id: `$slotInlineBlocks$${node.id}`,
|
|
74
|
+
type: SlotNodeType.SlotInlineBlocks,
|
|
75
|
+
originParent: node,
|
|
76
|
+
parent: node,
|
|
77
|
+
});
|
|
78
|
+
addedNodes.push(blockIconNode);
|
|
79
|
+
addedNodes.push(inlineBlocksNode);
|
|
80
|
+
|
|
81
|
+
const portJSONList = json.blocks || [];
|
|
82
|
+
|
|
83
|
+
portJSONList.forEach((_portJSON) => {
|
|
84
|
+
const port = document.addNode({
|
|
85
|
+
type: SlotNodeType.SlotBlock,
|
|
86
|
+
..._portJSON,
|
|
87
|
+
originParent: node,
|
|
88
|
+
parent: inlineBlocksNode,
|
|
89
|
+
});
|
|
90
|
+
addedNodes.push(port);
|
|
91
|
+
|
|
92
|
+
(_portJSON.blocks || []).forEach((_portChild) => {
|
|
93
|
+
document.addNode(
|
|
94
|
+
{
|
|
95
|
+
type: SlotNodeType.Slot,
|
|
96
|
+
..._portChild,
|
|
97
|
+
parent: port,
|
|
98
|
+
},
|
|
99
|
+
addedNodes
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return addedNodes;
|
|
105
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { mean } from 'lodash-es';
|
|
7
|
+
import { FlowNodeTransformData } from '@flowgram-vue/document';
|
|
8
|
+
|
|
9
|
+
export const getDisplayFirstChildTop = (transform: FlowNodeTransformData): number => {
|
|
10
|
+
if (transform.firstChild) {
|
|
11
|
+
return transform.localBounds.top + getDisplayFirstChildTop(transform.firstChild);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return transform.localBounds.center.y;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 获取单个 Port 的中间点
|
|
19
|
+
* @param inlineBlocks
|
|
20
|
+
* @returns
|
|
21
|
+
*/
|
|
22
|
+
export const getPortMiddle = (_port: FlowNodeTransformData) => {
|
|
23
|
+
if (!_port.children.length) {
|
|
24
|
+
return _port.localBounds.top;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const portChildInputs = [_port.firstChild!, _port.lastChild!].map((_portChild) =>
|
|
28
|
+
getDisplayFirstChildTop(_portChild)
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
return _port.localBounds.top + mean(portChildInputs);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 获取所有 Port 的中间点
|
|
36
|
+
* @param inlineBlocks
|
|
37
|
+
* @returns
|
|
38
|
+
*/
|
|
39
|
+
export const getAllPortsMiddle = (inlineBlocks: FlowNodeTransformData) => {
|
|
40
|
+
if (!inlineBlocks.children.length) {
|
|
41
|
+
return inlineBlocks.localBounds.height / 2;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const portInputs = [inlineBlocks.firstChild!, inlineBlocks.lastChild!].map((_port) =>
|
|
45
|
+
getPortMiddle(_port)
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return mean(portInputs);
|
|
49
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FlowNodeEntity } from '@flowgram-vue/document';
|
|
7
|
+
import { FlowNodeTransformData } from '@flowgram-vue/document';
|
|
8
|
+
|
|
9
|
+
import { SlotNodeType } from '../typings';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Slot 节点是否可下钻,看 inlineBlocks 是否有子节点
|
|
13
|
+
* @param Slot Slot 节点
|
|
14
|
+
*/
|
|
15
|
+
export const canSlotDrilldown = (Slot: FlowNodeEntity): boolean =>
|
|
16
|
+
!!Slot?.lastCollapsedChild?.blocks.length;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 是否是 Slot 内部
|
|
20
|
+
* @param entity
|
|
21
|
+
* @returns
|
|
22
|
+
*/
|
|
23
|
+
export const insideSlot = (entity?: FlowNodeEntity): boolean =>
|
|
24
|
+
!!entity?.parent?.isTypeOrExtendType(SlotNodeType.SlotBlock);
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 获取在页面上实际渲染的第一个 Child 节点
|
|
28
|
+
* @param node
|
|
29
|
+
*/
|
|
30
|
+
export const getDisplayFirstChildTransform = (
|
|
31
|
+
transform: FlowNodeTransformData
|
|
32
|
+
): FlowNodeTransformData => {
|
|
33
|
+
if (transform.firstChild) {
|
|
34
|
+
return getDisplayFirstChildTransform(transform.firstChild);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return transform;
|
|
38
|
+
};
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { IPoint, Point } from '@flowgram-vue/utils';
|
|
7
|
+
import {
|
|
8
|
+
type FlowNodeTransitionData,
|
|
9
|
+
FlowTransitionLineEnum,
|
|
10
|
+
FlowTransitionLabelEnum,
|
|
11
|
+
type FlowNodeTransformData,
|
|
12
|
+
type FlowTransitionLine,
|
|
13
|
+
type FlowTransitionLabel,
|
|
14
|
+
getDefaultSpacing,
|
|
15
|
+
} from '@flowgram-vue/document';
|
|
16
|
+
|
|
17
|
+
import { RENDER_SLOT_COLLAPSE_KEY, SlotSpacingKey, SLOT_START_DISTANCE } from '../constants';
|
|
18
|
+
import { getDisplayFirstChildTransform } from './node';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 画 Slot 节点虚线起点
|
|
22
|
+
* @param iconTransform blockIcon 的 transform
|
|
23
|
+
* @returns
|
|
24
|
+
*/
|
|
25
|
+
export const getSlotChildLineStartPoint = (iconTransform?: FlowNodeTransformData): IPoint => {
|
|
26
|
+
if (!iconTransform) {
|
|
27
|
+
return { x: 0, y: 0 };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const startDistance = getDefaultSpacing(
|
|
31
|
+
iconTransform.entity,
|
|
32
|
+
SlotSpacingKey.SLOT_START_DISTANCE,
|
|
33
|
+
SLOT_START_DISTANCE
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
if (!iconTransform.entity.isVertical) {
|
|
37
|
+
return {
|
|
38
|
+
x: iconTransform?.bounds.center.x,
|
|
39
|
+
y: iconTransform?.bounds.bottom + startDistance,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
x: iconTransform?.bounds.right + startDistance,
|
|
44
|
+
y: iconTransform?.bounds.center.y,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const getOutputPoint = (transform: FlowNodeTransformData): IPoint => {
|
|
49
|
+
const icon = transform.firstChild;
|
|
50
|
+
|
|
51
|
+
if (!icon) {
|
|
52
|
+
return { x: 0, y: 0 };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!transform.entity.isVertical) {
|
|
56
|
+
return {
|
|
57
|
+
x: transform.bounds.right,
|
|
58
|
+
y: icon.outputPoint.y,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
x: icon.outputPoint.x,
|
|
64
|
+
y: transform.bounds.bottom,
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const getInputPoint = (transform: FlowNodeTransformData): IPoint => {
|
|
69
|
+
const icon = transform.firstChild;
|
|
70
|
+
|
|
71
|
+
if (!icon) {
|
|
72
|
+
return { x: 0, y: 0 };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!transform.entity.isVertical) {
|
|
76
|
+
return {
|
|
77
|
+
x: transform.bounds.left,
|
|
78
|
+
y: icon.outputPoint.y,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return icon.inputPoint;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 获取实连线终点
|
|
87
|
+
* @param transition
|
|
88
|
+
* @returns
|
|
89
|
+
*/
|
|
90
|
+
export const getTransitionToPoint = (transition: FlowNodeTransitionData): IPoint => {
|
|
91
|
+
let toPoint = transition.transform.next?.inputPoint;
|
|
92
|
+
const icon = transition.transform.firstChild;
|
|
93
|
+
|
|
94
|
+
const parent = transition.transform.parent;
|
|
95
|
+
|
|
96
|
+
if (!icon || !parent) {
|
|
97
|
+
return { x: 0, y: 0 };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!transition.transform.next) {
|
|
101
|
+
if (!transition.entity.isVertical) {
|
|
102
|
+
toPoint = {
|
|
103
|
+
x: parent.outputPoint.x,
|
|
104
|
+
y: icon.outputPoint.y,
|
|
105
|
+
};
|
|
106
|
+
} else {
|
|
107
|
+
toPoint = {
|
|
108
|
+
x: icon.outputPoint.x,
|
|
109
|
+
y: parent.outputPoint.y,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return toPoint || { x: 0, y: 0 };
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* 画实现线
|
|
119
|
+
* @param transition Slot 节点的 transition
|
|
120
|
+
* @returns
|
|
121
|
+
*/
|
|
122
|
+
export const drawStraightLine = (transition: FlowNodeTransitionData): FlowTransitionLine[] => {
|
|
123
|
+
const icon = transition.transform.firstChild;
|
|
124
|
+
const toPoint = getTransitionToPoint(transition);
|
|
125
|
+
|
|
126
|
+
if (!icon) {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return [
|
|
131
|
+
{
|
|
132
|
+
type: FlowTransitionLineEnum.STRAIGHT_LINE,
|
|
133
|
+
from: icon.outputPoint,
|
|
134
|
+
to: toPoint,
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
type: FlowTransitionLineEnum.STRAIGHT_LINE,
|
|
138
|
+
from: icon.inputPoint,
|
|
139
|
+
to: transition.transform.inputPoint,
|
|
140
|
+
},
|
|
141
|
+
];
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export const drawCollapseLabel = (transition: FlowNodeTransitionData): FlowTransitionLabel[] => {
|
|
145
|
+
const icon = transition.transform;
|
|
146
|
+
|
|
147
|
+
return [
|
|
148
|
+
{
|
|
149
|
+
type: FlowTransitionLabelEnum.CUSTOM_LABEL,
|
|
150
|
+
renderKey: RENDER_SLOT_COLLAPSE_KEY,
|
|
151
|
+
offset: getSlotChildLineStartPoint(icon),
|
|
152
|
+
props: {
|
|
153
|
+
node: transition.entity.parent,
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
];
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export const drawCollapseLine = (transition: FlowNodeTransitionData): FlowTransitionLine[] => {
|
|
160
|
+
const startDistance = getDefaultSpacing(
|
|
161
|
+
transition.transform.entity,
|
|
162
|
+
SlotSpacingKey.SLOT_START_DISTANCE,
|
|
163
|
+
SLOT_START_DISTANCE
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
return [
|
|
167
|
+
{
|
|
168
|
+
type: FlowTransitionLineEnum.STRAIGHT_LINE,
|
|
169
|
+
from: getSlotChildLineStartPoint(transition.transform),
|
|
170
|
+
to: Point.move(
|
|
171
|
+
getSlotChildLineStartPoint(transition.transform),
|
|
172
|
+
transition.entity.isVertical ? { x: -startDistance, y: 0 } : { x: 0, y: -startDistance }
|
|
173
|
+
),
|
|
174
|
+
style: {
|
|
175
|
+
strokeDasharray: '5 5',
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* 画实线上的叫号
|
|
183
|
+
* @param transition
|
|
184
|
+
* @returns
|
|
185
|
+
*/
|
|
186
|
+
export const drawStraightAdder = (transition: FlowNodeTransitionData): FlowTransitionLabel[] => {
|
|
187
|
+
const toPoint = getTransitionToPoint(transition);
|
|
188
|
+
const fromPoint = transition.transform.firstChild!.outputPoint;
|
|
189
|
+
|
|
190
|
+
const hoverProps = transition.entity.isVertical
|
|
191
|
+
? {
|
|
192
|
+
hoverHeight: toPoint.y - fromPoint.y,
|
|
193
|
+
hoverWidth: transition.transform.firstChild?.bounds.width,
|
|
194
|
+
}
|
|
195
|
+
: {
|
|
196
|
+
hoverHeight: transition.transform.firstChild?.bounds.height,
|
|
197
|
+
hoverWidth: toPoint.x - fromPoint.x,
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
return [
|
|
201
|
+
{
|
|
202
|
+
offset: Point.getMiddlePoint(fromPoint, toPoint),
|
|
203
|
+
type: FlowTransitionLabelEnum.ADDER_LABEL,
|
|
204
|
+
props: hoverProps,
|
|
205
|
+
},
|
|
206
|
+
];
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* 获取端口的子节点线条输入点
|
|
211
|
+
* @param _child
|
|
212
|
+
* @returns
|
|
213
|
+
*/
|
|
214
|
+
export const getPortChildInput = (_child?: FlowNodeTransformData) => {
|
|
215
|
+
if (!_child) {
|
|
216
|
+
return { x: 0, y: 0 };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const firstChild = getDisplayFirstChildTransform(_child);
|
|
220
|
+
|
|
221
|
+
return { x: _child.bounds.left, y: firstChild.bounds.center.y };
|
|
222
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FlowNodeBaseType, type FlowNodeRegistry } from '@flowgram-vue/document';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 开始节点
|
|
10
|
+
*/
|
|
11
|
+
export const StartRegistry: FlowNodeRegistry = {
|
|
12
|
+
type: FlowNodeBaseType.START,
|
|
13
|
+
meta: {
|
|
14
|
+
isStart: true,
|
|
15
|
+
draggable: false,
|
|
16
|
+
selectable: false, // 触发器等开始节点不能被框选
|
|
17
|
+
deleteDisable: true, // 禁止删除
|
|
18
|
+
copyDisable: true, // 禁止copy
|
|
19
|
+
addDisable: true, // 禁止添加
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FlowNodeBaseType, type FlowNodeRegistry, FlowNodeSplitType } from '@flowgram-vue/document';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 不能动态添加分支的分支节点
|
|
10
|
+
* staticSplit: (最原始的 id)
|
|
11
|
+
* blockIcon
|
|
12
|
+
* inlineBlocks
|
|
13
|
+
* block1
|
|
14
|
+
* blockOrderIcon
|
|
15
|
+
* block2
|
|
16
|
+
* blockOrderIcon
|
|
17
|
+
*/
|
|
18
|
+
export const StaticSplitRegistry: FlowNodeRegistry = {
|
|
19
|
+
extend: FlowNodeSplitType.DYNAMIC_SPLIT,
|
|
20
|
+
type: FlowNodeSplitType.STATIC_SPLIT,
|
|
21
|
+
extendChildRegistries: [
|
|
22
|
+
{
|
|
23
|
+
type: FlowNodeBaseType.INLINE_BLOCKS,
|
|
24
|
+
getLabels() {
|
|
25
|
+
return [];
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
DEFAULT_SPACING,
|
|
8
|
+
FlowNodeBaseType,
|
|
9
|
+
type FlowNodeRegistry,
|
|
10
|
+
FlowTransitionLineEnum,
|
|
11
|
+
} from '@flowgram-vue/document';
|
|
12
|
+
|
|
13
|
+
import { TryCatchSpacings, TryCatchTypeEnum } from './constants';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* catch 分支
|
|
17
|
+
*/
|
|
18
|
+
export const CatchBlockRegistry: FlowNodeRegistry = {
|
|
19
|
+
extend: FlowNodeBaseType.BLOCK,
|
|
20
|
+
type: TryCatchTypeEnum.CATCH_BLOCK,
|
|
21
|
+
meta: {
|
|
22
|
+
hidden: true,
|
|
23
|
+
spacing: DEFAULT_SPACING.NULL,
|
|
24
|
+
},
|
|
25
|
+
getLines(transition) {
|
|
26
|
+
const { transform } = transition;
|
|
27
|
+
const { isVertical } = transition.entity;
|
|
28
|
+
const parentPoint = transform.parent!;
|
|
29
|
+
const { inputPoint, outputPoint } = transform;
|
|
30
|
+
let parentInputPoint;
|
|
31
|
+
if (isVertical) {
|
|
32
|
+
parentInputPoint = {
|
|
33
|
+
x: parentPoint.inputPoint.x,
|
|
34
|
+
y: parentPoint.inputPoint.y - TryCatchSpacings.CATCH_INLINE_SPACING,
|
|
35
|
+
};
|
|
36
|
+
} else {
|
|
37
|
+
parentInputPoint = {
|
|
38
|
+
x: parentPoint.inputPoint.x - TryCatchSpacings.CATCH_INLINE_SPACING,
|
|
39
|
+
y: parentPoint.inputPoint.y,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const lines = [
|
|
44
|
+
{
|
|
45
|
+
type: FlowTransitionLineEnum.DIVERGE_LINE,
|
|
46
|
+
from: parentInputPoint,
|
|
47
|
+
to: inputPoint,
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
// 最后一个节点是 end 节点,不绘制 mergeLine
|
|
52
|
+
if (!transition.isNodeEnd) {
|
|
53
|
+
let mergePoint;
|
|
54
|
+
if (isVertical) {
|
|
55
|
+
mergePoint = {
|
|
56
|
+
x: parentPoint.outputPoint.x,
|
|
57
|
+
y: parentPoint.bounds.bottom,
|
|
58
|
+
};
|
|
59
|
+
} else {
|
|
60
|
+
mergePoint = {
|
|
61
|
+
x: parentPoint.bounds.right,
|
|
62
|
+
y: parentPoint.outputPoint.y,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
lines.push({
|
|
67
|
+
type: FlowTransitionLineEnum.MERGE_LINE,
|
|
68
|
+
from: outputPoint,
|
|
69
|
+
to: mergePoint,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return lines;
|
|
74
|
+
},
|
|
75
|
+
getLabels() {
|
|
76
|
+
return [];
|
|
77
|
+
},
|
|
78
|
+
};
|