@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,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Point } from '@flowgram-vue/utils';
|
|
7
|
+
import { FlowRendererKey } from '@flowgram-vue/renderer';
|
|
8
|
+
import {
|
|
9
|
+
FlowNodeBaseType,
|
|
10
|
+
type FlowNodeRegistry,
|
|
11
|
+
FlowNodeRenderData,
|
|
12
|
+
FlowTransitionLabelEnum,
|
|
13
|
+
FlowNodeSplitType,
|
|
14
|
+
getDefaultSpacing,
|
|
15
|
+
ConstantKeys,
|
|
16
|
+
} from '@flowgram-vue/document';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 多输入节点, 只能作为 开始节点
|
|
20
|
+
* - multiInputs:
|
|
21
|
+
* - inlineBlocks
|
|
22
|
+
* - input
|
|
23
|
+
* - input
|
|
24
|
+
*/
|
|
25
|
+
export const MultiInputsRegistry: FlowNodeRegistry = {
|
|
26
|
+
type: FlowNodeBaseType.MULTI_INPUTS,
|
|
27
|
+
extend: FlowNodeSplitType.SIMPLE_SPLIT,
|
|
28
|
+
extendChildRegistries: [
|
|
29
|
+
{
|
|
30
|
+
type: FlowNodeBaseType.BLOCK_ICON,
|
|
31
|
+
meta: {
|
|
32
|
+
hidden: true,
|
|
33
|
+
spacing: 0,
|
|
34
|
+
},
|
|
35
|
+
getLines() {
|
|
36
|
+
return [];
|
|
37
|
+
},
|
|
38
|
+
getLabels() {
|
|
39
|
+
return [];
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: FlowNodeBaseType.INLINE_BLOCKS,
|
|
44
|
+
meta: {
|
|
45
|
+
inlineSpacingPre: 0,
|
|
46
|
+
},
|
|
47
|
+
getLabels(transition) {
|
|
48
|
+
const isVertical = transition.entity.isVertical;
|
|
49
|
+
const currentTransform = transition.transform;
|
|
50
|
+
const spacing = getDefaultSpacing(
|
|
51
|
+
transition.entity,
|
|
52
|
+
ConstantKeys.INLINE_BLOCKS_PADDING_BOTTOM
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
if (currentTransform.collapsed || transition.entity.childrenLength === 0) {
|
|
56
|
+
return [
|
|
57
|
+
{
|
|
58
|
+
type: FlowTransitionLabelEnum.CUSTOM_LABEL,
|
|
59
|
+
renderKey: FlowRendererKey.BRANCH_ADDER,
|
|
60
|
+
offset: Point.move(
|
|
61
|
+
currentTransform.outputPoint,
|
|
62
|
+
isVertical ? { y: spacing } : { x: spacing }
|
|
63
|
+
),
|
|
64
|
+
props: {
|
|
65
|
+
// 激活状态
|
|
66
|
+
activated: transition.entity.getData(FlowNodeRenderData)!.activated,
|
|
67
|
+
transform: currentTransform,
|
|
68
|
+
// 传给外部使用的 node 信息
|
|
69
|
+
node: currentTransform.originParent?.entity,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return [
|
|
76
|
+
{
|
|
77
|
+
type: FlowTransitionLabelEnum.CUSTOM_LABEL,
|
|
78
|
+
renderKey: FlowRendererKey.BRANCH_ADDER,
|
|
79
|
+
offset: Point.move(
|
|
80
|
+
currentTransform.outputPoint,
|
|
81
|
+
isVertical ? { y: -spacing / 2 } : { x: -spacing / 2 }
|
|
82
|
+
),
|
|
83
|
+
props: {
|
|
84
|
+
// 激活状态
|
|
85
|
+
activated: transition.entity.getData(FlowNodeRenderData)!.activated,
|
|
86
|
+
transform: currentTransform,
|
|
87
|
+
// 传给外部使用的 node 信息
|
|
88
|
+
node: currentTransform.originParent?.entity,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
getLabels() {
|
|
96
|
+
return [];
|
|
97
|
+
},
|
|
98
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
FlowLayoutDefault,
|
|
8
|
+
type FlowNodeRegistry,
|
|
9
|
+
FlowNodeSplitType,
|
|
10
|
+
FlowNodeBaseType,
|
|
11
|
+
} from '@flowgram-vue/document';
|
|
12
|
+
|
|
13
|
+
import { DynamicSplitRegistry } from './dynamic-split';
|
|
14
|
+
import { BlockRegistry } from './block';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 多输出节点
|
|
18
|
+
* - multiOutputs:
|
|
19
|
+
* - blockIcon
|
|
20
|
+
* - inlineBlocks
|
|
21
|
+
* - output or multiOutputs
|
|
22
|
+
* - output or multiOutputs
|
|
23
|
+
*/
|
|
24
|
+
export const MultiOuputsRegistry: FlowNodeRegistry = {
|
|
25
|
+
type: FlowNodeBaseType.MULTI_OUTPUTS,
|
|
26
|
+
extend: FlowNodeSplitType.SIMPLE_SPLIT,
|
|
27
|
+
meta: {
|
|
28
|
+
isNodeEnd: true,
|
|
29
|
+
},
|
|
30
|
+
getLines: (transition, layout) => {
|
|
31
|
+
// 嵌套在 mutliOutputs 下边
|
|
32
|
+
if (transition.entity.parent?.flowNodeType === FlowNodeBaseType.INLINE_BLOCKS) {
|
|
33
|
+
return BlockRegistry.getLines!(transition, layout);
|
|
34
|
+
}
|
|
35
|
+
return [];
|
|
36
|
+
},
|
|
37
|
+
getLabels: (transition, layout) => [
|
|
38
|
+
...DynamicSplitRegistry.getLabels!(transition, layout),
|
|
39
|
+
...BlockRegistry.getLabels!(transition, layout),
|
|
40
|
+
],
|
|
41
|
+
getOutputPoint(transform, layout) {
|
|
42
|
+
const isVertical = FlowLayoutDefault.isVertical(layout);
|
|
43
|
+
const lastChildOutput = transform.lastChild?.outputPoint;
|
|
44
|
+
|
|
45
|
+
if (isVertical) {
|
|
46
|
+
return {
|
|
47
|
+
x: lastChildOutput ? lastChildOutput.x : transform.bounds.center.x,
|
|
48
|
+
y: transform.bounds.bottom,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
x: transform.bounds.right,
|
|
54
|
+
y: lastChildOutput ? lastChildOutput.y : transform.bounds.center.y,
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
extendChildRegistries: [
|
|
58
|
+
{
|
|
59
|
+
type: FlowNodeBaseType.BLOCK_ICON,
|
|
60
|
+
meta: {
|
|
61
|
+
// isNodeEnd: true
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
+
* 输出节点, 一般作为 end 节点
|
|
10
|
+
*/
|
|
11
|
+
export const OuputRegistry: FlowNodeRegistry = {
|
|
12
|
+
type: FlowNodeBaseType.OUTPUT,
|
|
13
|
+
extend: FlowNodeBaseType.BLOCK,
|
|
14
|
+
meta: {
|
|
15
|
+
hidden: false,
|
|
16
|
+
isNodeEnd: true,
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { DEFAULT_SPACING, FlowNodeBaseType, type FlowNodeRegistry } from '@flowgram-vue/document';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 根节点
|
|
10
|
+
*/
|
|
11
|
+
export const RootRegistry: FlowNodeRegistry = {
|
|
12
|
+
type: FlowNodeBaseType.ROOT,
|
|
13
|
+
meta: {
|
|
14
|
+
spacing: DEFAULT_SPACING.NULL,
|
|
15
|
+
hidden: true,
|
|
16
|
+
},
|
|
17
|
+
getInputPoint(transform) {
|
|
18
|
+
return transform.firstChild?.inputPoint || transform.bounds.topCenter;
|
|
19
|
+
},
|
|
20
|
+
getOutputPoint(transform) {
|
|
21
|
+
return transform.lastChild?.outputPoint || transform.bounds.bottomCenter;
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
type FlowNodeRegistry,
|
|
8
|
+
FlowNodeSplitType,
|
|
9
|
+
FlowNodeBaseType,
|
|
10
|
+
FlowNodeJSON,
|
|
11
|
+
FlowNodeEntity,
|
|
12
|
+
} from '@flowgram-vue/document';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* - simpleSplit: (最原始的 id)
|
|
16
|
+
* blockIcon
|
|
17
|
+
* inlineBlocks
|
|
18
|
+
* node1
|
|
19
|
+
* node2
|
|
20
|
+
*/
|
|
21
|
+
export const SimpleSplitRegistry: FlowNodeRegistry = {
|
|
22
|
+
type: FlowNodeSplitType.SIMPLE_SPLIT,
|
|
23
|
+
extend: FlowNodeSplitType.DYNAMIC_SPLIT,
|
|
24
|
+
onBlockChildCreate(
|
|
25
|
+
originParent: FlowNodeEntity,
|
|
26
|
+
blockData: FlowNodeJSON,
|
|
27
|
+
addedNodes: FlowNodeEntity[] = [] // 新创建的节点都要存在这里
|
|
28
|
+
) {
|
|
29
|
+
const { document } = originParent;
|
|
30
|
+
const parent = document.getNode(`$inlineBlocks$${originParent.id}`);
|
|
31
|
+
const realBlock = document.addNode(
|
|
32
|
+
{
|
|
33
|
+
...blockData,
|
|
34
|
+
type: blockData.type || FlowNodeBaseType.BLOCK,
|
|
35
|
+
parent,
|
|
36
|
+
},
|
|
37
|
+
addedNodes
|
|
38
|
+
);
|
|
39
|
+
addedNodes.push(realBlock);
|
|
40
|
+
return realBlock;
|
|
41
|
+
},
|
|
42
|
+
// addChild(node, json, options = {}) {
|
|
43
|
+
// const { index } = options;
|
|
44
|
+
// const document = node.document;
|
|
45
|
+
// return document.addBlock(node, json, undefined, undefined, index);
|
|
46
|
+
// }
|
|
47
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FlowRendererKey } from '@flowgram-vue/renderer';
|
|
7
|
+
|
|
8
|
+
export const RENDER_SLOT_ADDER_KEY: string = FlowRendererKey.SLOT_ADDER;
|
|
9
|
+
export const RENDER_SLOT_LABEL_KEY: string = FlowRendererKey.SLOT_LABEL;
|
|
10
|
+
export const RENDER_SLOT_COLLAPSE_KEY: string = FlowRendererKey.SLOT_COLLAPSE;
|
|
11
|
+
|
|
12
|
+
export const SlotSpacingKey = {
|
|
13
|
+
/**
|
|
14
|
+
* = Next Node - Slot END
|
|
15
|
+
*/
|
|
16
|
+
SLOT_SPACING: 'SLOT_SPACING',
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* = Slot Start Line - Slot Icon Right
|
|
20
|
+
*/
|
|
21
|
+
SLOT_START_DISTANCE: 'SLOT_START_DISTANCE',
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* = Slot Radius
|
|
25
|
+
*/
|
|
26
|
+
SLOT_RADIUS: 'SLOT_RADIUS',
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* = Slot Port - Slot Start
|
|
30
|
+
*/
|
|
31
|
+
SLOT_PORT_DISTANCE: 'SLOT_PORT_DISTANCE',
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* = Slot Label - Slot Start
|
|
35
|
+
*/
|
|
36
|
+
SLOT_LABEL_DISTANCE: 'SLOT_LABEL_DISTANCE',
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* = Slot Block - Slot Port
|
|
40
|
+
*/
|
|
41
|
+
SLOT_BLOCK_PORT_DISTANCE: 'SLOT_BLOCK_PORT_DISTANCE',
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Vertical Layout: Slot Block - Slot Block
|
|
45
|
+
*/
|
|
46
|
+
SLOT_BLOCK_VERTICAL_SPACING: 'SLOT_BLOCK_VERTICAL_SPACING',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const SLOT_START_DISTANCE = 16;
|
|
50
|
+
export const SLOT_PORT_DISTANCE = 100;
|
|
51
|
+
export const SLOT_LABEL_DISTANCE = 32;
|
|
52
|
+
export const SLOT_BLOCK_PORT_DISTANCE = 32.5;
|
|
53
|
+
export const SLOT_RADIUS = 16;
|
|
54
|
+
export const SLOT_SPACING = 32;
|
|
55
|
+
export const SLOT_BLOCK_VERTICAL_SPACING = 32.5;
|
|
56
|
+
export const SLOT_NODE_LAST_SPACING = 10;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { SlotIconRegistry } from './slot-icon';
|
|
7
|
+
export { SlotInlineBlocksRegistry } from './slot-inline-blocks';
|
|
8
|
+
export { SlotBlockRegistry } from './slot-block';
|
|
@@ -0,0 +1,229 @@
|
|
|
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 {
|
|
8
|
+
FlowNodeRegistry,
|
|
9
|
+
FlowNodeBaseType,
|
|
10
|
+
FlowTransitionLabelEnum,
|
|
11
|
+
FlowTransitionLineEnum,
|
|
12
|
+
getDefaultSpacing,
|
|
13
|
+
Vertex,
|
|
14
|
+
} from '@flowgram-vue/document';
|
|
15
|
+
import { FlowNodeTransformData } from '@flowgram-vue/document';
|
|
16
|
+
|
|
17
|
+
import { getPortChildInput, getSlotChildLineStartPoint } from '../utils/transition';
|
|
18
|
+
import { SlotNodeType } from '../typings';
|
|
19
|
+
import {
|
|
20
|
+
RENDER_SLOT_ADDER_KEY,
|
|
21
|
+
SlotSpacingKey,
|
|
22
|
+
SLOT_PORT_DISTANCE,
|
|
23
|
+
SLOT_RADIUS,
|
|
24
|
+
SLOT_LABEL_DISTANCE,
|
|
25
|
+
RENDER_SLOT_LABEL_KEY,
|
|
26
|
+
SLOT_BLOCK_VERTICAL_SPACING,
|
|
27
|
+
} from '../constants';
|
|
28
|
+
|
|
29
|
+
export const SlotBlockRegistry: FlowNodeRegistry = {
|
|
30
|
+
type: SlotNodeType.SlotBlock,
|
|
31
|
+
extend: FlowNodeBaseType.BLOCK,
|
|
32
|
+
meta: {
|
|
33
|
+
inlineSpacingAfter: 0,
|
|
34
|
+
inlineSpacingPre: 0,
|
|
35
|
+
spacing: (transform) => {
|
|
36
|
+
// 水平布局没有子节点情况
|
|
37
|
+
if (!transform.entity.isVertical && transform.size.width === 0) {
|
|
38
|
+
return 90;
|
|
39
|
+
}
|
|
40
|
+
return getDefaultSpacing(
|
|
41
|
+
transform.entity,
|
|
42
|
+
SlotSpacingKey.SLOT_BLOCK_VERTICAL_SPACING,
|
|
43
|
+
SLOT_BLOCK_VERTICAL_SPACING
|
|
44
|
+
);
|
|
45
|
+
},
|
|
46
|
+
isInlineBlocks: (node) => !node.isVertical,
|
|
47
|
+
},
|
|
48
|
+
getLines(transition) {
|
|
49
|
+
const icon = transition.transform.parent?.pre;
|
|
50
|
+
const start = getSlotChildLineStartPoint(icon);
|
|
51
|
+
const portPoint = transition.transform.inputPoint;
|
|
52
|
+
|
|
53
|
+
const radius = getDefaultSpacing(
|
|
54
|
+
transition.transform.entity,
|
|
55
|
+
SlotSpacingKey.SLOT_RADIUS,
|
|
56
|
+
SLOT_RADIUS
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
let startPortVertices: Vertex[] = [{ x: start.x, y: portPoint.y }];
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* When Radius is not enough, we should use truncate strategy
|
|
63
|
+
* 弧度不够时,采取截断策略
|
|
64
|
+
*/
|
|
65
|
+
if (transition.entity.isVertical) {
|
|
66
|
+
const deltaY = Math.abs(portPoint.y - start.y);
|
|
67
|
+
let deltaX = radius;
|
|
68
|
+
let isTruncated = false;
|
|
69
|
+
|
|
70
|
+
if (deltaY < radius * 2) {
|
|
71
|
+
isTruncated = true;
|
|
72
|
+
if (deltaY < radius) {
|
|
73
|
+
// Calculate the x by circle equation
|
|
74
|
+
deltaX = Math.sqrt(radius ** 2 - (radius - deltaY) ** 2);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
startPortVertices = [
|
|
79
|
+
{
|
|
80
|
+
x: start.x + deltaX,
|
|
81
|
+
y: start.y,
|
|
82
|
+
radiusX: radius,
|
|
83
|
+
radiusY: radius,
|
|
84
|
+
radiusOverflow: 'truncate',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
x: start.x + deltaX,
|
|
88
|
+
y: portPoint.y,
|
|
89
|
+
...(isTruncated ? { radiusX: 0, radiusY: 0 } : {}),
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* When One Children, we should keep dash array align, so we draw one line directly to child nodes
|
|
96
|
+
* 只有一个子节点时,我们通常需要保证两条虚线是连贯的,因此我们直接合并,绘制一条线连到子节点
|
|
97
|
+
*/
|
|
98
|
+
if (transition.transform.children.length === 1) {
|
|
99
|
+
return [
|
|
100
|
+
{
|
|
101
|
+
type: FlowTransitionLineEnum.ROUNDED_LINE,
|
|
102
|
+
from: start,
|
|
103
|
+
to: getPortChildInput(transition.transform.children[0]),
|
|
104
|
+
vertices: startPortVertices,
|
|
105
|
+
style: {
|
|
106
|
+
strokeDasharray: '5 5',
|
|
107
|
+
},
|
|
108
|
+
radius,
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return [
|
|
114
|
+
{
|
|
115
|
+
type: FlowTransitionLineEnum.ROUNDED_LINE,
|
|
116
|
+
from: start,
|
|
117
|
+
to: portPoint,
|
|
118
|
+
vertices: startPortVertices,
|
|
119
|
+
style: {
|
|
120
|
+
strokeDasharray: '5 5',
|
|
121
|
+
},
|
|
122
|
+
radius,
|
|
123
|
+
},
|
|
124
|
+
...transition.transform.children.map((_child) => {
|
|
125
|
+
const childInput = getPortChildInput(_child);
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
type: FlowTransitionLineEnum.ROUNDED_LINE,
|
|
129
|
+
radius,
|
|
130
|
+
from: portPoint,
|
|
131
|
+
to: childInput,
|
|
132
|
+
vertices: [{ x: portPoint.x, y: childInput.y }],
|
|
133
|
+
style: {
|
|
134
|
+
strokeDasharray: '5 5',
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}),
|
|
138
|
+
];
|
|
139
|
+
},
|
|
140
|
+
getLabels(transition) {
|
|
141
|
+
const icon = transition.transform.parent?.pre;
|
|
142
|
+
const start = getSlotChildLineStartPoint(icon);
|
|
143
|
+
const portPoint = transition.transform.inputPoint;
|
|
144
|
+
|
|
145
|
+
return [
|
|
146
|
+
{
|
|
147
|
+
type: FlowTransitionLabelEnum.CUSTOM_LABEL,
|
|
148
|
+
renderKey: RENDER_SLOT_ADDER_KEY,
|
|
149
|
+
props: {
|
|
150
|
+
node: transition.entity,
|
|
151
|
+
},
|
|
152
|
+
offset: portPoint,
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
type: FlowTransitionLabelEnum.CUSTOM_LABEL,
|
|
156
|
+
renderKey: RENDER_SLOT_LABEL_KEY,
|
|
157
|
+
props: {
|
|
158
|
+
node: transition.entity,
|
|
159
|
+
},
|
|
160
|
+
offset: {
|
|
161
|
+
x:
|
|
162
|
+
start.x +
|
|
163
|
+
getDefaultSpacing(
|
|
164
|
+
transition.entity,
|
|
165
|
+
SlotSpacingKey.SLOT_LABEL_DISTANCE,
|
|
166
|
+
SLOT_LABEL_DISTANCE
|
|
167
|
+
),
|
|
168
|
+
y: portPoint.y,
|
|
169
|
+
},
|
|
170
|
+
origin: [0, 0.5],
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
},
|
|
174
|
+
getInputPoint(transform) {
|
|
175
|
+
const icon = transform.parent?.pre;
|
|
176
|
+
const start = getSlotChildLineStartPoint(icon);
|
|
177
|
+
|
|
178
|
+
let inputY = transform.bounds.center.y;
|
|
179
|
+
if (transform.children.length) {
|
|
180
|
+
inputY = mean([
|
|
181
|
+
getPortChildInput(transform.firstChild).y,
|
|
182
|
+
getPortChildInput(transform.lastChild).y,
|
|
183
|
+
]);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
x:
|
|
188
|
+
start.x +
|
|
189
|
+
getDefaultSpacing(transform.entity, SlotSpacingKey.SLOT_PORT_DISTANCE, SLOT_PORT_DISTANCE),
|
|
190
|
+
y: inputY,
|
|
191
|
+
};
|
|
192
|
+
},
|
|
193
|
+
getChildDelta(child, layout) {
|
|
194
|
+
const hasChild = !!child.firstChild;
|
|
195
|
+
|
|
196
|
+
if (child.entity.isVertical) {
|
|
197
|
+
// 绑定普通节点时进行重心纠偏
|
|
198
|
+
let deltaX = hasChild ? 0 : -child.originDeltaX;
|
|
199
|
+
|
|
200
|
+
return { x: deltaX, y: 0 };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
let deltaY = hasChild ? 0 : -child.originDeltaY;
|
|
204
|
+
|
|
205
|
+
const preTransform = child.entity.pre?.getData(FlowNodeTransformData);
|
|
206
|
+
if (preTransform) {
|
|
207
|
+
const { localBounds: preBounds } = preTransform;
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
x: 0,
|
|
211
|
+
y: preBounds.bottom + 30 + deltaY,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return { x: 0, y: deltaY };
|
|
216
|
+
},
|
|
217
|
+
getChildLabels() {
|
|
218
|
+
return [];
|
|
219
|
+
},
|
|
220
|
+
getChildLines() {
|
|
221
|
+
return [];
|
|
222
|
+
},
|
|
223
|
+
getDelta(transform) {
|
|
224
|
+
return {
|
|
225
|
+
x: 0,
|
|
226
|
+
y: 0,
|
|
227
|
+
};
|
|
228
|
+
},
|
|
229
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FlowNodeRegistry, FlowNodeBaseType } from '@flowgram-vue/document';
|
|
7
|
+
|
|
8
|
+
import { drawCollapseLabel, drawCollapseLine } from '../utils/transition';
|
|
9
|
+
import { canSlotDrilldown, insideSlot } from '../utils/node';
|
|
10
|
+
|
|
11
|
+
export const SlotIconRegistry: FlowNodeRegistry = {
|
|
12
|
+
type: FlowNodeBaseType.BLOCK_ICON,
|
|
13
|
+
meta: {
|
|
14
|
+
defaultExpanded: false,
|
|
15
|
+
spacing: 0,
|
|
16
|
+
},
|
|
17
|
+
getLines: (transition) => [
|
|
18
|
+
...(canSlotDrilldown(transition.entity.parent!) ? drawCollapseLine(transition) : []),
|
|
19
|
+
],
|
|
20
|
+
getLabels: (transition) => [
|
|
21
|
+
...(canSlotDrilldown(transition.entity.parent!) ? drawCollapseLabel(transition) : []),
|
|
22
|
+
],
|
|
23
|
+
getDelta: (transform) => {
|
|
24
|
+
// Slot 节点内部时,重新纠正重心调整产生的偏移
|
|
25
|
+
if (insideSlot(transform.entity.parent)) {
|
|
26
|
+
return transform.entity.isVertical
|
|
27
|
+
? { x: -transform.originDeltaX, y: 0 }
|
|
28
|
+
: { x: 0, y: -transform.originDeltaY };
|
|
29
|
+
}
|
|
30
|
+
return { x: 0, y: 0 };
|
|
31
|
+
},
|
|
32
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
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
|
+
import { FlowNodeTransformData } from '@flowgram-vue/document';
|
|
8
|
+
|
|
9
|
+
import { SlotNodeType } from '../typings';
|
|
10
|
+
import {
|
|
11
|
+
SlotSpacingKey,
|
|
12
|
+
SLOT_START_DISTANCE,
|
|
13
|
+
SLOT_PORT_DISTANCE,
|
|
14
|
+
SLOT_BLOCK_PORT_DISTANCE,
|
|
15
|
+
} from '../constants';
|
|
16
|
+
|
|
17
|
+
export const SlotInlineBlocksRegistry: FlowNodeRegistry = {
|
|
18
|
+
type: SlotNodeType.SlotInlineBlocks,
|
|
19
|
+
extend: FlowNodeBaseType.BLOCK,
|
|
20
|
+
meta: {
|
|
21
|
+
spacing: 0,
|
|
22
|
+
inlineSpacingPre: 0,
|
|
23
|
+
inlineSpacingAfter: 0,
|
|
24
|
+
isInlineBlocks: (node) => !node.isVertical,
|
|
25
|
+
},
|
|
26
|
+
getLines() {
|
|
27
|
+
return [];
|
|
28
|
+
},
|
|
29
|
+
getLabels() {
|
|
30
|
+
return [];
|
|
31
|
+
},
|
|
32
|
+
getChildDelta(child, layout) {
|
|
33
|
+
if (child.entity.isVertical) {
|
|
34
|
+
return { x: 0, y: 0 };
|
|
35
|
+
}
|
|
36
|
+
const preTransform = child.entity.pre?.getData(FlowNodeTransformData);
|
|
37
|
+
if (preTransform) {
|
|
38
|
+
const { localBounds: preBounds } = preTransform;
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
x: 0,
|
|
42
|
+
y: preBounds.bottom + 30,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return { x: 0, y: 0 };
|
|
47
|
+
},
|
|
48
|
+
/**
|
|
49
|
+
* 控制条件分支居右布局
|
|
50
|
+
*/
|
|
51
|
+
getDelta(transform) {
|
|
52
|
+
if (!transform.children.length) {
|
|
53
|
+
return { x: 0, y: 0 };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const icon = transform.pre;
|
|
57
|
+
if (!icon) {
|
|
58
|
+
return { x: 0, y: 0 };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const startDistance = getDefaultSpacing(
|
|
62
|
+
transform.entity,
|
|
63
|
+
SlotSpacingKey.SLOT_START_DISTANCE,
|
|
64
|
+
SLOT_START_DISTANCE
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const portDistance = getDefaultSpacing(
|
|
68
|
+
transform.entity,
|
|
69
|
+
SlotSpacingKey.SLOT_PORT_DISTANCE,
|
|
70
|
+
SLOT_PORT_DISTANCE
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const portBlockDistance = getDefaultSpacing(
|
|
74
|
+
transform.entity,
|
|
75
|
+
SlotSpacingKey.SLOT_BLOCK_PORT_DISTANCE,
|
|
76
|
+
SLOT_BLOCK_PORT_DISTANCE
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
if (!transform.entity.isVertical) {
|
|
80
|
+
const noChildren = transform?.children?.every?.((_port) => !_port.children.length);
|
|
81
|
+
/**
|
|
82
|
+
* 如果没有 children 的时候,不需要有右侧的间距,避免水平布局的时候 Slot 右侧空间过大。
|
|
83
|
+
*/
|
|
84
|
+
if (noChildren) {
|
|
85
|
+
return {
|
|
86
|
+
x: portDistance - icon.localBounds.width / 2,
|
|
87
|
+
y: icon.localBounds.bottom + startDistance,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
x: portDistance + portBlockDistance - icon.localBounds.width / 2,
|
|
92
|
+
y: icon.localBounds.bottom + startDistance,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const slotInlineBlockDelta = startDistance + portDistance + portBlockDistance;
|
|
97
|
+
return {
|
|
98
|
+
x: icon.localBounds.right + slotInlineBlockDelta,
|
|
99
|
+
y: -icon.localBounds.height,
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
};
|