Skip to content

Commit 9ddbbcf

Browse files
committed
feat: 迭代开发
2 parents 50b76e2 + 939c2c3 commit 9ddbbcf

File tree

28 files changed

+422
-333
lines changed

28 files changed

+422
-333
lines changed

docs/xflow/XFlowProvider.md renamed to docs/xflow/FlowProvider.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ group:
99

1010
# 基础交互
1111

12-
<code src="./demo/xflow-provider/index.tsx"></code>
12+
<code src="./demo/flow-provider/index.tsx"></code>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const edges = [{ source: '1', target: '2', id: '234123' }];
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from "react";
2+
3+
import XFlow, { FlowProvider, useNodes } from '@xrenders/xflow';
4+
import { edges as initialEdges } from './edges';
5+
import { nodes as initialNodes } from './nodes';
6+
import settings from './setting';
7+
8+
const App = () => {
9+
return (
10+
<FlowProvider>
11+
<div style={{ height: '600px' }}>
12+
<XFlow
13+
initialValues={{ nodes: initialNodes, edges: initialEdges }}
14+
settings={settings}
15+
nodeSelector={{
16+
showSearch: true,
17+
}}
18+
/>
19+
</div>
20+
<Sidebar />
21+
</FlowProvider>
22+
);
23+
};
24+
25+
function Sidebar() {
26+
// This hook will only work if the component it's used in is a child of a
27+
// <FlowProvider />.
28+
const nodes = useNodes();
29+
30+
return (
31+
<aside>
32+
{nodes?.map(node => (
33+
<div key={node.id}>
34+
Node {node.id} - x: {node.position.x.toFixed(2)}, y:{' '}
35+
{node.position.y.toFixed(2)}
36+
</div>
37+
))}
38+
</aside>
39+
);
40+
}
41+
42+
export default () => {
43+
return (
44+
<FlowProvider>
45+
<App />
46+
</FlowProvider>
47+
);
48+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export const nodes = [
2+
{
3+
id: '1',
4+
type: 'Start',
5+
data: {},
6+
position: {
7+
x: 40,
8+
y: 240,
9+
},
10+
},
11+
{
12+
id: '2',
13+
type: 'End',
14+
data: {},
15+
position: {
16+
x: 500,
17+
y: 240,
18+
},
19+
},
20+
];

docs/xflow/demo/xflow-provider/index.tsx

Lines changed: 0 additions & 48 deletions
This file was deleted.

packages/x-flow/src/Wrapper.tsx

Lines changed: 0 additions & 28 deletions
This file was deleted.

packages/x-flow/src/XFlow.tsx

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,24 @@ import produce, { setAutoFreeze } from 'immer';
1111
import { debounce } from 'lodash';
1212
import type { FC } from 'react';
1313
import React, { memo, useEffect, useMemo, useRef, useState } from 'react';
14-
import { useShallow } from 'zustand/react/shallow';
1514
import CandidateNode from './components/CandidateNode';
1615
import CustomEdge from './components/CustomEdge';
1716
import PanelContainer from './components/PanelContainer';
1817
import { useEventEmitterContextContext } from './models/event-emitter';
1918

2019
import CustomNodeComponent from './components/CustomNode';
2120
import { useStore, useStoreApi } from './hooks/useStore';
21+
import { useTemporalStore } from './hooks/useTemporalStore';
22+
2223
import Operator from './operator';
23-
import XFlowProps from './types';
24+
import FlowProps from './types';
2425
import { transformNodes, uuid } from './utils';
2526
import autoLayoutNodes from './utils/autoLayoutNodes';
2627

28+
import { shallow } from 'zustand/shallow';
2729
import NodeEditor from './components/NodeEditor';
30+
import { useFlow } from './hooks/useFlow';
2831
import './index.less';
29-
import { Wrapper } from './Wrapper';
3032

3133
const CustomNode = memo(CustomNodeComponent);
3234
const edgeTypes = { buttonedge: memo(CustomEdge) };
@@ -36,45 +38,40 @@ const edgeTypes = { buttonedge: memo(CustomEdge) };
3638
* XFlow 入口
3739
*
3840
*/
39-
const App: FC<XFlowProps> = memo(props => {
41+
const XFlow: FC<FlowProps> = memo(props => {
4042
const { initialValues, settings } = props;
4143
const workflowContainerRef = useRef<HTMLDivElement>(null);
4244
const store = useStoreApi();
43-
const { updateEdge, zoomTo } = useReactFlow();
44-
// const { undo, redo, record } = useTemporalStore();
45+
const { zoomTo } = useReactFlow();
4546
const {
4647
layout,
4748
nodes,
4849
edges,
50+
panOnDrag,
4951
onNodesChange,
5052
onEdgesChange,
5153
onConnect,
52-
setNodes,
53-
setEdges,
54-
addNodes,
55-
addEdges,
5654
setLayout,
5755
setCandidateNode,
5856
setMousePosition,
5957
} = useStore(
60-
useShallow(state => ({
58+
state => ({
6159
nodes: state.nodes,
6260
edges: state.edges,
6361
layout: state.layout,
62+
panOnDrag: state.panOnDrag,
6463
setLayout: state.setLayout,
65-
setNodes: state.setNodes,
66-
setEdges: state.setEdges,
67-
addNodes: state.addNodes,
68-
addEdges: state.addEdges,
6964
setMousePosition: state.setMousePosition,
7065
setCandidateNode: state.setCandidateNode,
7166
onNodesChange: state.onNodesChange,
7267
onEdgesChange: state.onEdgesChange,
7368
onConnect: state.onConnect,
74-
}))
69+
}),
70+
shallow
7571
);
72+
const { setNodes, setEdges } = useFlow();
7673
const [activeNode, setActiveNode] = useState<any>(null);
77-
74+
const temporalStore = useTemporalStore();
7875
useEffect(() => {
7976
zoomTo(0.8);
8077
setAutoFreeze(false);
@@ -85,9 +82,10 @@ const App: FC<XFlowProps> = memo(props => {
8582

8683
useEffect(() => {
8784
setLayout(props.layout);
85+
// TODO: 默认关闭时间机器,可以向 zundo 贡献一个配置
86+
temporalStore.pause();
8887
setNodes(transformNodes(initialValues?.nodes));
8988
setEdges(initialValues?.edges);
90-
store.temporal.getState().pause();
9189
}, []);
9290

9391
useEventListener('keydown', e => {
@@ -235,6 +233,7 @@ const App: FC<XFlowProps> = memo(props => {
235233
return (
236234
<div id="xflow-container" ref={workflowContainerRef}>
237235
<ReactFlow
236+
panOnDrag={panOnDrag}
238237
nodeTypes={nodeTypes}
239238
edgeTypes={edgeTypes}
240239
nodes={nodes}
@@ -288,12 +287,4 @@ const App: FC<XFlowProps> = memo(props => {
288287
);
289288
});
290289

291-
const XFlow: FC<XFlowProps> = (props) => {
292-
const { initialValues } = props;
293-
return (
294-
<Wrapper nodes={initialValues?.nodes} edges={initialValues.edges}>
295-
<App {...props}/>
296-
</Wrapper>
297-
);
298-
};
299290
export default XFlow;
Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,55 @@
1-
import React from 'react';
2-
import { memo } from 'react';
3-
import produce from 'immer';
4-
import { useShallow } from 'zustand/react/shallow';
51
import { useReactFlow, useViewport } from '@xyflow/react';
62
import { useEventListener } from 'ahooks';
7-
import CustomNode from '../CustomNode';
3+
import React, { memo } from 'react';
4+
import { shallow } from 'zustand/shallow';
85
import { useStore } from '../../hooks/useStore';
6+
import CustomNode from '../CustomNode';
97

108
const CandidateNode = () => {
119
const { zoom } = useViewport();
1210
const reactflow = useReactFlow();
13-
14-
const {
15-
nodes,
16-
candidateNode,
17-
mousePosition,
18-
addNodes,
19-
setCandidateNode
20-
} = useStore(
21-
useShallow((state: any) => ({
11+
const { candidateNode, mousePosition, setCandidateNode, addNodes } = useStore(
12+
(state: any) => ({
2213
nodes: state.nodes,
2314
edges: state.edges,
15+
addNodes: state.addNodes,
2416
candidateNode: state.candidateNode,
2517
mousePosition: state.mousePosition,
26-
addNodes: state.addNodes,
2718
setCandidateNode: state.setCandidateNode,
2819
onNodesChange: state.onNodesChange,
2920
onEdgesChange: state.onEdgesChange,
30-
}))
21+
}),
22+
shallow
3123
);
3224

33-
useEventListener('click', (ev) => {
25+
useEventListener('click', ev => {
3426
if (!candidateNode) {
3527
return;
3628
}
3729
ev.preventDefault();
3830
const { screenToFlowPosition } = reactflow;
39-
const { x, y } = screenToFlowPosition({ x: mousePosition.pageX, y: mousePosition.pageY });
40-
41-
const newNodes = produce(nodes, (draft: any) => {
42-
draft.push({
43-
...candidateNode,
44-
data: {
45-
...candidateNode.data,
46-
_isCandidate: false,
47-
},
48-
position: { x, y }
49-
});
31+
const { x, y } = screenToFlowPosition({
32+
x: mousePosition.pageX,
33+
y: mousePosition.pageY,
5034
});
35+
36+
const newNodes = {
37+
...candidateNode,
38+
data: {
39+
...candidateNode.data,
40+
_isCandidate: false,
41+
},
42+
position: { x, y },
43+
};
44+
// @ts-ignore
5145
addNodes(newNodes);
5246
setCandidateNode(null);
5347
});
5448

5549
if (!candidateNode) {
56-
return null
50+
return null;
5751
}
5852

59-
console.log(mousePosition, '=======000000')
60-
6153
return (
6254
<div
6355
style={{
@@ -66,12 +58,15 @@ const CandidateNode = () => {
6658
transform: `scale(${zoom})`,
6759
transformOrigin: '0 0',
6860
position: 'absolute',
69-
zIndex: 10000
61+
zIndex: 10000,
7062
}}
7163
>
72-
<CustomNode {...candidateNode as any} type={candidateNode?.data?._nodeType } />
64+
<CustomNode
65+
{...(candidateNode as any)}
66+
type={candidateNode?.data?._nodeType}
67+
/>
7368
</div>
7469
);
75-
}
70+
};
7671

7772
export default memo(CandidateNode);

0 commit comments

Comments
 (0)