@flowgram-vue/fixed-semi-materials 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 +0 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +0 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
- package/src/assets/ellipsis.ts +20 -0
- package/src/assets/icons.ts +154 -0
- package/src/assets/index.ts +17 -0
- package/src/components/adder.vue +66 -0
- package/src/components/branch-adder.vue +55 -0
- package/src/components/collapse.vue +84 -0
- package/src/components/constants.ts +7 -0
- package/src/components/drag-highlight-adder.vue +54 -0
- package/src/components/drag-node.vue +45 -0
- package/src/components/dragging-adder.vue +40 -0
- package/src/components/index.ts +32 -0
- package/src/components/metadata.ts +87 -0
- package/src/components/nodes.vue +32 -0
- package/src/components/playground-tools.vue +33 -0
- package/src/components/slot-adder.vue +44 -0
- package/src/components/slot-collapse.vue +55 -0
- package/src/components/try-catch-collapse.vue +124 -0
- package/src/composables/use-fixed-playground-tools.ts +118 -0
- package/src/env.d.ts +10 -0
- package/src/index.ts +9 -0
- package/src/styles.css +225 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { ref } from 'vue';
|
|
7
|
+
import { nanoid } from 'nanoid';
|
|
8
|
+
import {
|
|
9
|
+
FlowNodeTransformData,
|
|
10
|
+
FlowOperationBaseService,
|
|
11
|
+
type FlowNodeEntity,
|
|
12
|
+
} from '@flowgram-vue/document';
|
|
13
|
+
import { usePlayground, useService } from '@flowgram-vue/core';
|
|
14
|
+
|
|
15
|
+
import { IconPlus } from '../assets';
|
|
16
|
+
import NodesPicker from './nodes.vue';
|
|
17
|
+
|
|
18
|
+
defineOptions({ name: 'Adder' });
|
|
19
|
+
|
|
20
|
+
const props = defineProps<{
|
|
21
|
+
from: FlowNodeEntity;
|
|
22
|
+
to?: FlowNodeEntity;
|
|
23
|
+
hoverActivated?: boolean;
|
|
24
|
+
}>();
|
|
25
|
+
|
|
26
|
+
const visible = ref(false);
|
|
27
|
+
const playground = usePlayground();
|
|
28
|
+
const flowOperationService = useService(FlowOperationBaseService);
|
|
29
|
+
|
|
30
|
+
const add = (addProps: { type: string; blocks?: () => unknown }) => {
|
|
31
|
+
const block = flowOperationService.addFromNode(props.from, {
|
|
32
|
+
id: addProps.type + nanoid(5),
|
|
33
|
+
type: addProps.type,
|
|
34
|
+
blocks: addProps.blocks ? (addProps.blocks() as never) : undefined,
|
|
35
|
+
});
|
|
36
|
+
setTimeout(() => {
|
|
37
|
+
playground.scrollToView({
|
|
38
|
+
bounds: block.getData<FlowNodeTransformData>(FlowNodeTransformData)!.bounds,
|
|
39
|
+
scrollToCenter: true,
|
|
40
|
+
});
|
|
41
|
+
}, 10);
|
|
42
|
+
visible.value = false;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const onMouseDown = (e: MouseEvent) => e.stopPropagation();
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<div
|
|
50
|
+
v-if="!playground.config.readonlyOrDisabled"
|
|
51
|
+
class="fg-fixed-chrome"
|
|
52
|
+
style="position: relative"
|
|
53
|
+
>
|
|
54
|
+
<div
|
|
55
|
+
class="fg-adder-wrap"
|
|
56
|
+
:class="{ 'is-hovered': props.hoverActivated }"
|
|
57
|
+
@mousedown="onMouseDown"
|
|
58
|
+
@click.stop="visible = !visible"
|
|
59
|
+
>
|
|
60
|
+
<IconPlus v-if="props.hoverActivated" />
|
|
61
|
+
</div>
|
|
62
|
+
<div v-if="visible" class="fg-popover" @mousedown.stop>
|
|
63
|
+
<NodesPicker :on-select="add" />
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</template>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { nanoid } from 'nanoid';
|
|
7
|
+
import {
|
|
8
|
+
FlowNodeRenderData,
|
|
9
|
+
FlowNodeTransformData,
|
|
10
|
+
FlowOperationBaseService,
|
|
11
|
+
type FlowNodeEntity,
|
|
12
|
+
} from '@flowgram-vue/document';
|
|
13
|
+
import { usePlayground, useService } from '@flowgram-vue/core';
|
|
14
|
+
|
|
15
|
+
import { IconPlus } from '../assets';
|
|
16
|
+
|
|
17
|
+
defineOptions({ name: 'BranchAdder' });
|
|
18
|
+
|
|
19
|
+
const props = defineProps<{
|
|
20
|
+
activated?: boolean;
|
|
21
|
+
node: FlowNodeEntity;
|
|
22
|
+
}>();
|
|
23
|
+
|
|
24
|
+
const nodeData = props.node.firstChild?.getData<FlowNodeRenderData>(FlowNodeRenderData);
|
|
25
|
+
const playground = usePlayground();
|
|
26
|
+
const flowOperationService = useService(FlowOperationBaseService);
|
|
27
|
+
const isVertical = props.node.isVertical;
|
|
28
|
+
|
|
29
|
+
function addBranch() {
|
|
30
|
+
const block = flowOperationService.addBlock(props.node, { id: nanoid(5) });
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
playground.scrollToView({
|
|
33
|
+
bounds: block.getData<FlowNodeTransformData>(FlowNodeTransformData)!.bounds,
|
|
34
|
+
scrollToCenter: true,
|
|
35
|
+
});
|
|
36
|
+
}, 10);
|
|
37
|
+
}
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<template>
|
|
41
|
+
<div
|
|
42
|
+
v-if="!playground.config.readonlyOrDisabled"
|
|
43
|
+
class="fg-branch-adder"
|
|
44
|
+
:class="{
|
|
45
|
+
'is-activated': props.activated || nodeData?.hovered,
|
|
46
|
+
'is-horizontal': !isVertical,
|
|
47
|
+
}"
|
|
48
|
+
@mouseenter="nodeData?.toggleMouseEnter()"
|
|
49
|
+
@mouseleave="nodeData?.toggleMouseLeave()"
|
|
50
|
+
>
|
|
51
|
+
<div class="fg-branch-hit" aria-hidden="true" @click="addBranch">
|
|
52
|
+
<IconPlus />
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</template>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import {
|
|
7
|
+
FlowNodeEntity,
|
|
8
|
+
FlowNodeRenderData,
|
|
9
|
+
FlowNodeTransformData,
|
|
10
|
+
} from '@flowgram-vue/document';
|
|
11
|
+
import { usePlayground } from '@flowgram-vue/core';
|
|
12
|
+
import type { CSSProperties } from 'vue';
|
|
13
|
+
|
|
14
|
+
import { Arrow } from '../assets';
|
|
15
|
+
|
|
16
|
+
defineOptions({ name: 'Collapse' });
|
|
17
|
+
|
|
18
|
+
const props = defineProps<{
|
|
19
|
+
node: FlowNodeEntity;
|
|
20
|
+
collapseNode: FlowNodeEntity;
|
|
21
|
+
activateNode?: FlowNodeEntity;
|
|
22
|
+
forceVisible?: boolean;
|
|
23
|
+
hoverActivated?: boolean;
|
|
24
|
+
style?: CSSProperties;
|
|
25
|
+
}>();
|
|
26
|
+
|
|
27
|
+
const playground = usePlayground();
|
|
28
|
+
const activateData = props.activateNode?.getData(FlowNodeRenderData);
|
|
29
|
+
const transform = props.collapseNode.getData(FlowNodeTransformData);
|
|
30
|
+
|
|
31
|
+
const scrollToActivateNode = () => {
|
|
32
|
+
setTimeout(() => {
|
|
33
|
+
playground.config.scrollToView({
|
|
34
|
+
position: props.activateNode?.getData(FlowNodeTransformData)?.outputPoint,
|
|
35
|
+
scrollToCenter: true,
|
|
36
|
+
});
|
|
37
|
+
}, 100);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const collapseBlock = () => {
|
|
41
|
+
if (!transform) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
transform.collapsed = true;
|
|
45
|
+
activateData?.toggleMouseLeave();
|
|
46
|
+
scrollToActivateNode();
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const openBlock = () => {
|
|
50
|
+
if (!transform) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
transform.collapsed = false;
|
|
54
|
+
scrollToActivateNode();
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const childCount = transform
|
|
58
|
+
? transform.collapsed
|
|
59
|
+
? props.collapseNode.allCollapsedChildren.filter(
|
|
60
|
+
(child) => !child.hidden && child !== props.activateNode
|
|
61
|
+
).length
|
|
62
|
+
: 0
|
|
63
|
+
: 0;
|
|
64
|
+
|
|
65
|
+
const circleColor = '#fff';
|
|
66
|
+
const color = props.hoverActivated ? '#82A7FC' : '#BBBFC4';
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<template>
|
|
70
|
+
<div
|
|
71
|
+
v-if="transform"
|
|
72
|
+
class="fg-collapse"
|
|
73
|
+
:class="{
|
|
74
|
+
'is-hovered': props.hoverActivated,
|
|
75
|
+
'is-horizontal-collapse': !props.activateNode?.isVertical && !transform.collapsed,
|
|
76
|
+
}"
|
|
77
|
+
aria-hidden="true"
|
|
78
|
+
:style="props.style"
|
|
79
|
+
@click="transform.collapsed ? openBlock() : collapseBlock()"
|
|
80
|
+
>
|
|
81
|
+
<template v-if="transform.collapsed">{{ childCount }}</template>
|
|
82
|
+
<Arrow v-else :color="color" :circle-color="circleColor" />
|
|
83
|
+
</div>
|
|
84
|
+
</template>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { FlowNodeTransformData, type FlowNodeEntity } from '@flowgram-vue/document';
|
|
7
|
+
|
|
8
|
+
import { Ellipse } from '../assets';
|
|
9
|
+
|
|
10
|
+
defineOptions({ name: 'DragHighlightAdder' });
|
|
11
|
+
|
|
12
|
+
const props = defineProps<{
|
|
13
|
+
node: FlowNodeEntity;
|
|
14
|
+
}>();
|
|
15
|
+
|
|
16
|
+
const getMinSize = (preWidth: number, nextWidth: number): number => {
|
|
17
|
+
if (!preWidth || preWidth < 0) {
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
if (!nextWidth || nextWidth < 0) {
|
|
21
|
+
return preWidth;
|
|
22
|
+
}
|
|
23
|
+
return Math.min(preWidth, nextWidth) || 0;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const transformBounds = props.node.getData<FlowNodeTransformData>(FlowNodeTransformData)?.bounds;
|
|
27
|
+
const isVertical = props.node.isVertical;
|
|
28
|
+
|
|
29
|
+
let barWidth = 0;
|
|
30
|
+
let barHeight = 0;
|
|
31
|
+
if (isVertical) {
|
|
32
|
+
const preWidth = (transformBounds?.width || 0) - 16;
|
|
33
|
+
const nextNodeBounds =
|
|
34
|
+
props.node?.next?.getData<FlowNodeTransformData>(FlowNodeTransformData)?.bounds?.width;
|
|
35
|
+
const nextWidth = (nextNodeBounds || 0) - 16;
|
|
36
|
+
barWidth = getMinSize(preWidth, nextWidth);
|
|
37
|
+
barHeight = 2;
|
|
38
|
+
} else {
|
|
39
|
+
const preHeight = (transformBounds?.height || 0) - 16;
|
|
40
|
+
const nextNodeBounds =
|
|
41
|
+
props.node?.next?.getData<FlowNodeTransformData>(FlowNodeTransformData)?.bounds?.height;
|
|
42
|
+
const nextHeight = (nextNodeBounds || 0) - 16;
|
|
43
|
+
barWidth = 2;
|
|
44
|
+
barHeight = getMinSize(preHeight, nextHeight);
|
|
45
|
+
}
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<div class="fg-highlight-line" :style="{ flexDirection: isVertical ? 'row' : 'column' }">
|
|
50
|
+
<Ellipse />
|
|
51
|
+
<div class="fg-highlight-bar" :style="{ width: `${barWidth}px`, height: `${barHeight}px` }" />
|
|
52
|
+
<Ellipse />
|
|
53
|
+
</div>
|
|
54
|
+
</template>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import type { FlowNodeEntity, FlowNodeJSON } from '@flowgram-vue/document';
|
|
7
|
+
|
|
8
|
+
defineOptions({ name: 'DragNode' });
|
|
9
|
+
|
|
10
|
+
const props = defineProps<{
|
|
11
|
+
dragStart?: FlowNodeEntity;
|
|
12
|
+
dragJSON?: FlowNodeJSON;
|
|
13
|
+
dragNodes: FlowNodeEntity[];
|
|
14
|
+
}>();
|
|
15
|
+
|
|
16
|
+
const dragLength = (props.dragNodes || [])
|
|
17
|
+
.map((_node) =>
|
|
18
|
+
_node.allCollapsedChildren.length
|
|
19
|
+
? _node.allCollapsedChildren.filter((_n) => !_n.hidden).length
|
|
20
|
+
: 1
|
|
21
|
+
)
|
|
22
|
+
.reduce((acm, curr) => acm + curr, 0);
|
|
23
|
+
|
|
24
|
+
const label = props.dragStart?.id || props.dragJSON?.id;
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<div class="fg-drag-node">
|
|
29
|
+
{{ label }}
|
|
30
|
+
<template v-if="dragLength > 1">
|
|
31
|
+
<div class="fg-drag-counts">{{ dragLength }}</div>
|
|
32
|
+
<div
|
|
33
|
+
class="fg-drag-node"
|
|
34
|
+
:style="{
|
|
35
|
+
position: 'absolute',
|
|
36
|
+
top: '5px',
|
|
37
|
+
right: '-5px',
|
|
38
|
+
left: '5px',
|
|
39
|
+
bottom: '-5px',
|
|
40
|
+
opacity: 0.5,
|
|
41
|
+
}"
|
|
42
|
+
/>
|
|
43
|
+
</template>
|
|
44
|
+
</div>
|
|
45
|
+
</template>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { computed } from 'vue';
|
|
7
|
+
import { usePlayground } from '@flowgram-vue/core';
|
|
8
|
+
import { FlowDragLayer } from '@flowgram-vue/renderer';
|
|
9
|
+
import type { FlowNodeEntity } from '@flowgram-vue/document';
|
|
10
|
+
|
|
11
|
+
defineOptions({ name: 'DraggingAdder' });
|
|
12
|
+
|
|
13
|
+
const props = defineProps<{
|
|
14
|
+
from?: FlowNodeEntity;
|
|
15
|
+
}>();
|
|
16
|
+
|
|
17
|
+
const playground = usePlayground();
|
|
18
|
+
const layer = playground.getLayer(FlowDragLayer);
|
|
19
|
+
|
|
20
|
+
const canShow = computed(() => {
|
|
21
|
+
if (!layer) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
if (
|
|
25
|
+
layer.options.canDrop &&
|
|
26
|
+
!layer.options.canDrop({
|
|
27
|
+
dragNodes: layer.dragEntities || [],
|
|
28
|
+
dropNode: props.from as FlowNodeEntity,
|
|
29
|
+
isBranch: false,
|
|
30
|
+
})
|
|
31
|
+
) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
35
|
+
});
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<div v-if="canShow" class="fg-dragging-adder" />
|
|
40
|
+
</template>
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
import { Ellipse } from '../assets';
|
|
9
|
+
import Adder from './adder.vue';
|
|
10
|
+
import BranchAdder from './branch-adder.vue';
|
|
11
|
+
import Collapse from './collapse.vue';
|
|
12
|
+
import DragHighlightAdder from './drag-highlight-adder.vue';
|
|
13
|
+
import DragNode from './drag-node.vue';
|
|
14
|
+
import DraggingAdder from './dragging-adder.vue';
|
|
15
|
+
import SlotAdder from './slot-adder.vue';
|
|
16
|
+
import SlotCollapse from './slot-collapse.vue';
|
|
17
|
+
import TryCatchCollapse from './try-catch-collapse.vue';
|
|
18
|
+
|
|
19
|
+
export { default as PlaygroundTools } from './playground-tools.vue';
|
|
20
|
+
|
|
21
|
+
export const defaultFixedSemiMaterials = {
|
|
22
|
+
[FlowRendererKey.ADDER]: Adder,
|
|
23
|
+
[FlowRendererKey.COLLAPSE]: Collapse,
|
|
24
|
+
[FlowRendererKey.TRY_CATCH_COLLAPSE]: TryCatchCollapse,
|
|
25
|
+
[FlowRendererKey.BRANCH_ADDER]: BranchAdder,
|
|
26
|
+
[FlowRendererKey.DRAG_NODE]: DragNode,
|
|
27
|
+
[FlowRendererKey.DRAGGABLE_ADDER]: DraggingAdder,
|
|
28
|
+
[FlowRendererKey.DRAG_HIGHLIGHT_ADDER]: DragHighlightAdder,
|
|
29
|
+
[FlowRendererKey.DRAG_BRANCH_HIGHLIGHT_ADDER]: Ellipse,
|
|
30
|
+
[FlowRendererKey.SLOT_COLLAPSE]: SlotCollapse,
|
|
31
|
+
[FlowRendererKey.SLOT_ADDER]: SlotAdder,
|
|
32
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { h, type Component } from 'vue';
|
|
7
|
+
import { nanoid } from 'nanoid';
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
BiBootstrapReboot,
|
|
11
|
+
BiCloud,
|
|
12
|
+
FeAlignCenter,
|
|
13
|
+
IconParkRightBranch,
|
|
14
|
+
IconStyleBorder,
|
|
15
|
+
PhCircleBold,
|
|
16
|
+
} from '../assets';
|
|
17
|
+
|
|
18
|
+
export interface NodeMeta {
|
|
19
|
+
type: string;
|
|
20
|
+
label: string;
|
|
21
|
+
icon: Component;
|
|
22
|
+
schemaType?: string;
|
|
23
|
+
branchEnd?: boolean;
|
|
24
|
+
blocks?: () => Array<{ id: string }>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const metadata = {
|
|
28
|
+
nodes: [
|
|
29
|
+
{
|
|
30
|
+
type: 'start',
|
|
31
|
+
label: 'Start',
|
|
32
|
+
icon: IconStyleBorder,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
type: 'dynamicSplit',
|
|
36
|
+
label: 'Split Branch',
|
|
37
|
+
icon: IconParkRightBranch,
|
|
38
|
+
blocks() {
|
|
39
|
+
return [{ id: nanoid(5) }, { id: nanoid(5) }];
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: 'end',
|
|
44
|
+
label: 'Branch End',
|
|
45
|
+
icon: FeAlignCenter,
|
|
46
|
+
branchEnd: true,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: 'loop',
|
|
50
|
+
schemaType: 'loop',
|
|
51
|
+
label: 'Loop',
|
|
52
|
+
icon: BiBootstrapReboot,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: 'tryCatch',
|
|
56
|
+
schemaType: 'tryCatch',
|
|
57
|
+
label: 'TryCatch',
|
|
58
|
+
icon: IconParkRightBranch,
|
|
59
|
+
blocks() {
|
|
60
|
+
return [
|
|
61
|
+
{ id: `try_${nanoid(5)}` },
|
|
62
|
+
{ id: `catch_${nanoid(5)}` },
|
|
63
|
+
{ id: `catch_${nanoid(5)}` },
|
|
64
|
+
];
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
type: 'noop',
|
|
69
|
+
label: 'Noop Node',
|
|
70
|
+
icon: BiCloud,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
type: 'end',
|
|
74
|
+
label: 'End',
|
|
75
|
+
icon: PhCircleBold,
|
|
76
|
+
},
|
|
77
|
+
] as NodeMeta[],
|
|
78
|
+
find(type: string) {
|
|
79
|
+
return metadata.nodes.find((m) => m.type === type);
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export function renderMetaIcon(icon: Component) {
|
|
84
|
+
return h(icon);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export default metadata;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import type { FlowNodeEntity } from '@flowgram-vue/document';
|
|
7
|
+
import metadata from './metadata';
|
|
8
|
+
|
|
9
|
+
defineOptions({ name: 'NodesPicker' });
|
|
10
|
+
|
|
11
|
+
defineProps<{
|
|
12
|
+
onSelect: (meta: (typeof metadata.nodes)[number]) => void;
|
|
13
|
+
}>();
|
|
14
|
+
|
|
15
|
+
const addings = metadata.nodes.filter((node) => node.type !== 'start');
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<div class="fg-nodes-wrap" :style="{ width: `${80 * 2 + 20}px` }">
|
|
20
|
+
<div
|
|
21
|
+
v-for="(n, i) in addings"
|
|
22
|
+
:key="i"
|
|
23
|
+
class="fg-node-wrap"
|
|
24
|
+
@click="onSelect(n)"
|
|
25
|
+
>
|
|
26
|
+
<div style="font-size: 14px">
|
|
27
|
+
<component :is="n.icon" />
|
|
28
|
+
</div>
|
|
29
|
+
<div class="fg-node-label">{{ n.label }}</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { computed } from 'vue';
|
|
7
|
+
|
|
8
|
+
import { useFixedPlaygroundTools } from '../composables/use-fixed-playground-tools';
|
|
9
|
+
|
|
10
|
+
defineOptions({ name: 'PlaygroundTools' });
|
|
11
|
+
|
|
12
|
+
const props = defineProps<{
|
|
13
|
+
layoutText?: string;
|
|
14
|
+
}>();
|
|
15
|
+
|
|
16
|
+
const tools = useFixedPlaygroundTools();
|
|
17
|
+
const zoomLabel = computed(() => `${Math.floor(tools.zoom * 100)}%`);
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<template>
|
|
21
|
+
<div class="fg-tools">
|
|
22
|
+
<label>
|
|
23
|
+
<input type="checkbox" :checked="!tools.isVertical" @change="tools.changeLayout()" />
|
|
24
|
+
{{ props.layoutText || 'isHorizontal' }}
|
|
25
|
+
</label>
|
|
26
|
+
<button type="button" title="fit view" @click="tools.fitView()">fit</button>
|
|
27
|
+
<button type="button" title="zoom out" @click="tools.zoomout()">-</button>
|
|
28
|
+
<button type="button" title="zoom in" @click="tools.zoomin()">+</button>
|
|
29
|
+
<button type="button" title="undo" :disabled="!tools.canUndo" @click="tools.undo()">undo</button>
|
|
30
|
+
<button type="button" title="redo" :disabled="!tools.canRedo" @click="tools.redo()">redo</button>
|
|
31
|
+
<span>{{ zoomLabel }}</span>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { nanoid } from 'nanoid';
|
|
7
|
+
import {
|
|
8
|
+
FlowDocument,
|
|
9
|
+
FlowNodeRenderData,
|
|
10
|
+
type FlowNodeEntity,
|
|
11
|
+
} from '@flowgram-vue/document';
|
|
12
|
+
import { useService } from '@flowgram-vue/core';
|
|
13
|
+
|
|
14
|
+
import { IconPlus } from '../assets';
|
|
15
|
+
|
|
16
|
+
defineOptions({ name: 'SlotAdder' });
|
|
17
|
+
|
|
18
|
+
const props = defineProps<{
|
|
19
|
+
node: FlowNodeEntity;
|
|
20
|
+
}>();
|
|
21
|
+
|
|
22
|
+
const nodeData = props.node.firstChild?.getData<FlowNodeRenderData>(FlowNodeRenderData);
|
|
23
|
+
const document = useService(FlowDocument) as FlowDocument;
|
|
24
|
+
|
|
25
|
+
function addPort() {
|
|
26
|
+
document.addNode({
|
|
27
|
+
id: nanoid(5),
|
|
28
|
+
type: 'custom',
|
|
29
|
+
parent: props.node,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<template>
|
|
35
|
+
<div
|
|
36
|
+
class="fg-slot-adder"
|
|
37
|
+
@mouseenter="nodeData?.toggleMouseEnter()"
|
|
38
|
+
@mouseleave="nodeData?.toggleMouseLeave()"
|
|
39
|
+
>
|
|
40
|
+
<button type="button" class="fg-native-btn" @click="addPort">
|
|
41
|
+
<IconPlus />
|
|
42
|
+
</button>
|
|
43
|
+
</div>
|
|
44
|
+
</template>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { ref, computed } from 'vue';
|
|
7
|
+
import {
|
|
8
|
+
FlowNodeRenderData,
|
|
9
|
+
FlowNodeTransformData,
|
|
10
|
+
type FlowNodeEntity,
|
|
11
|
+
} from '@flowgram-vue/document';
|
|
12
|
+
|
|
13
|
+
import Collapse from './collapse.vue';
|
|
14
|
+
|
|
15
|
+
defineOptions({ name: 'SlotCollapse' });
|
|
16
|
+
|
|
17
|
+
const props = defineProps<{
|
|
18
|
+
node: FlowNodeEntity;
|
|
19
|
+
}>();
|
|
20
|
+
|
|
21
|
+
const hoverActivated = ref(false);
|
|
22
|
+
const icon = props.node.firstChild!;
|
|
23
|
+
const iconActivated = icon.getData(FlowNodeRenderData).activated;
|
|
24
|
+
const iconHeight = icon.getData(FlowNodeTransformData).size.height;
|
|
25
|
+
const isChildVisible = computed(
|
|
26
|
+
() => props.node.collapsed || hoverActivated.value || iconActivated
|
|
27
|
+
);
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<template>
|
|
31
|
+
<div
|
|
32
|
+
:style="{
|
|
33
|
+
width: '30px',
|
|
34
|
+
height: `${iconHeight || 100}px`,
|
|
35
|
+
display: 'flex',
|
|
36
|
+
alignItems: 'center',
|
|
37
|
+
justifyContent: 'center',
|
|
38
|
+
}"
|
|
39
|
+
@mouseenter="hoverActivated = true"
|
|
40
|
+
@mouseleave="hoverActivated = false"
|
|
41
|
+
>
|
|
42
|
+
<Collapse
|
|
43
|
+
v-if="isChildVisible"
|
|
44
|
+
:style="
|
|
45
|
+
!props.node.collapsed
|
|
46
|
+
? { transform: props.node.isVertical ? 'rotate(-90deg)' : 'rotate(90deg)' }
|
|
47
|
+
: {}
|
|
48
|
+
"
|
|
49
|
+
:node="props.node"
|
|
50
|
+
:activate-node="icon"
|
|
51
|
+
:collapse-node="props.node"
|
|
52
|
+
:hover-activated="hoverActivated"
|
|
53
|
+
/>
|
|
54
|
+
</div>
|
|
55
|
+
</template>
|