@ant-design/pro-flow
Version:
A React based Flow components
177 lines (175 loc) • 7.62 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _taggedTemplateLiteral from "@babel/runtime/helpers/esm/taggedTemplateLiteral";
var _templateObject, _templateObject2;
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import { createStyles, cx } from 'antd-style';
import isEqual from 'fast-deep-equal';
import { debounce } from 'lodash-es';
import { forwardRef, useCallback, useEffect, useMemo, useRef } from 'react';
import { Flexbox } from 'react-layout-kit';
import ReactFlow, { Background, BackgroundVariant, SelectionMode, useNodesInitialized, useOnViewportChange, useReactFlow } from 'reactflow';
import 'reactflow/dist/style.css';
import CanvasLoading from "../../CanvasLoading";
import ContextMenu from "../features/ContextMenu";
import ControlAction from "../features/ControlAction";
import { useFlowEditor } from "../hooks/useFlowEditor";
import { useHotkeyManager } from "../hooks/useHotkeyManager";
import { flowEditorSelectors, useStore } from "../store";
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
export var useStyles = createStyles(function (_ref) {
var css = _ref.css,
token = _ref.token;
return {
container: css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n background: ", ";\n\n -webkit-font-smoothing: antialiased;\n\n .react-flow__pane {\n cursor: default;\n }\n .react-flow__edge-path,\n .react-flow__connection-path {\n stroke: ", ";\n stroke-width: 3px;\n }\n\n .react-flow__edge.selected .react-flow__edge-path,\n .react-flow__edge:focus .react-flow__edge-path,\n .react-flow__edge:focus-visible .react-flow__edge-path {\n stroke: ", ";\n stroke-width: 4px;\n }\n "])), token.colorBgLayout, token.colorBorder, token.colorPrimary),
minimap: css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n overflow: hidden;\n height: 150px;\n background: ", ";\n border-radius: 4px;\n "])), token.colorBgContainer)
};
});
var FlowEditor = /*#__PURE__*/forwardRef(function (_ref2, ref) {
var nodeTypes = _ref2.nodeTypes,
_ref2$contextMenuEnab = _ref2.contextMenuEnabled,
contextMenuEnabled = _ref2$contextMenuEnab === void 0 ? true : _ref2$contextMenuEnab,
style = _ref2.style,
className = _ref2.className,
flowProps = _ref2.flowProps,
defaultViewport = _ref2.defaultViewport,
children = _ref2.children,
_ref2$background = _ref2.background,
background = _ref2$background === void 0 ? true : _ref2$background,
_ref2$miniMap = _ref2.miniMap,
miniMap = _ref2$miniMap === void 0 ? true : _ref2$miniMap,
_ref2$hotkeyManager = _ref2.hotkeyManager,
hotkeyManager = _ref2$hotkeyManager === void 0 ? true : _ref2$hotkeyManager,
onNodesInit = _ref2.onNodesInit,
_ref2$beforeConnect = _ref2.beforeConnect,
beforeConnect = _ref2$beforeConnect === void 0 ? function () {
return true;
} : _ref2$beforeConnect,
_ref2$onConnect = _ref2.onConnect,
onConnect = _ref2$onConnect === void 0 ? function () {} : _ref2$onConnect,
_ref2$afterConnect = _ref2.afterConnect,
afterConnect = _ref2$afterConnect === void 0 ? function () {} : _ref2$afterConnect;
var _useStyles = useStyles(),
theme = _useStyles.theme,
styles = _useStyles.styles;
var nodes = useStore(flowEditorSelectors.nodeList, isEqual);
var edges = useStore(flowEditorSelectors.edgeList, isEqual);
var editor = useFlowEditor();
var nodesInitialized = useNodesInitialized();
var firstRender = useRef(false);
var flowInit = useMemo(function () {
if (nodesInitialized) {
return true;
}
if (nodes.length > 0) {
return false;
} else {
return true;
}
}, [nodes, nodesInitialized]);
var _useStore = useStore(function (s) {
return [s.handleNodesChange, s.handleEdgesChange, s.updateEdgesOnConnection, s.onViewPortChange
// s.onEdgesChange,
];
}),
_useStore2 = _slicedToArray(_useStore, 4),
handleNodesChange = _useStore2[0],
handleEdgesChange = _useStore2[1],
updateEdgesOnConnection = _useStore2[2],
onViewPortChange
// onEdgesChange,
= _useStore2[3];
var instance = useReactFlow();
// 添加快捷键监听
useHotkeyManager(hotkeyManager);
// 抛出 viewport 变化的事件
useOnViewportChange({
onChange: onViewPortChange ? debounce(onViewPortChange, 300) : undefined
});
useEffect(function () {
if (firstRender.current) {
return;
}
firstRender.current = true;
// 先把画布的 viewport 设置好
if (!defaultViewport) {
instance.fitView();
} else {
instance.setViewport(defaultViewport);
}
}, [nodesInitialized]);
useEffect(function () {
if (nodesInitialized) {
onNodesInit === null || onNodesInit === void 0 || onNodesInit(editor);
}
}, [nodesInitialized]);
var handleConnect = useCallback(function (connection) {
if (!beforeConnect(connection)) {
return;
}
if (onConnect) {
onConnect(connection);
}
var edge = updateEdgesOnConnection(connection);
if (afterConnect && edge) {
afterConnect(edge);
}
}, [onConnect, beforeConnect, afterConnect]);
return /*#__PURE__*/_jsxs(Flexbox, {
height: '100%',
width: '100%',
style: {
position: 'relative'
},
children: [!flowInit && /*#__PURE__*/_jsx(CanvasLoading, {}), /*#__PURE__*/_jsxs(ReactFlow, _objectSpread(_objectSpread({
nodeTypes: nodeTypes,
ref: ref,
className: cx(styles.container, className)
// 如果外部传入 viewport,则使用外部的 viewport
,
defaultViewport: defaultViewport
// 否则就 fit view
,
fitView: !defaultViewport,
fitViewOptions: {
padding: 3
},
nodes: nodes,
edges: edges
// snapToGrid
,
snapGrid: [20, 20],
minZoom: 0.05
// 画布配置逻辑
,
panOnScroll: true,
panOnDrag: false,
zoomOnScroll: false,
selectionOnDrag: true,
style: style
}, flowProps), {}, {
// 选择模式逻辑
selectionMode: SelectionMode.Partial,
selectionKeyCode: ['Meta', 'Shift'],
multiSelectionKeyCode: ['Meta', 'Shift'],
selectNodesOnDrag: true,
onNodesChange: handleNodesChange,
onEdgesChange: handleEdgesChange
// Connect 相关逻辑
,
onConnect: handleConnect,
disableKeyboardA11y: true,
proOptions: {
hideAttribution: true
},
children: [background && /*#__PURE__*/_jsx(Background, {
color: theme.colorTextQuaternary,
variant: BackgroundVariant.Dots,
size: 2
}), miniMap && /*#__PURE__*/_jsx(ControlAction, {}), contextMenuEnabled && /*#__PURE__*/_jsx(ContextMenu, {}), children]
}))]
});
});
export default FlowEditor;