UNPKG

@rxflow/base

Version:

BaseFlow - 核心 Flow 组件库

253 lines (250 loc) 14.6 kB
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } 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; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } /** * @author: yanxianliang * @date: 2025-07-27 16:33 * @modified:2025/7/27 16:33 by yanxianliang * @desc: Flow * * Copyright (c) 2025 by yanxianliang, All Rights Reserved. */ import '@xyflow/react/dist/style.css'; import { Legend } from "./components"; import { MarkerDefinitions } from "./components"; import { useForceUpdate } from "./hooks"; import { useGetState } from "./hooks"; import { useNodeTypes } from "./hooks"; import { useTheme } from "./hooks"; import { useThemeVars } from "./hooks"; import { Background, BackgroundVariant, MiniMap, ReactFlow, SelectionMode, useReactFlow, useStoreApi } from "@xyflow/react"; import { useMemoizedFn } from "ahooks"; import { omit } from "lodash"; import React, { useEffect, useMemo, useRef, useState } from "react"; import Controls from "./components/Controls"; import { DebugInfo } from "./components/DebugInfo"; import { ManhattanEdge } from "./edges/manhattan"; import { useGetEdgesChangeHandlers } from "./hooks/edges/useGetEdgesChangeHandlers"; import { useSetNodeDragging } from "./hooks/node/useSetNodeDragging"; import { useForceUpdateTimes } from "./hooks/render/useForceUpdateTimes"; import { useListenRender } from "./hooks/useListenRender"; import { Scrollbar } from "./plugins/scrollbar"; import { hasDimensionsChange } from "./utils/hasDimensionsChange"; import "./index.less"; import { baseLayout } from "./utils/layouts/base"; import { jsx as _jsx } from "react/jsx-runtime"; import { jsxs as _jsxs } from "react/jsx-runtime"; var proOptions = { hideAttribution: true }; // 默认隐藏水印 export function Flow(props) { var width = props.width, height = props.height, _props$showControls = props.showControls, showControls = _props$showControls === void 0 ? true : _props$showControls, _props$controlsPositi = props.controlsPosition, controlsPosition = _props$controlsPositi === void 0 ? 'top-right' : _props$controlsPositi, controlsOrientation = props.controlsOrientation, showMiniMap = props.showMiniMap, showLegend = props.showLegend, _props$background = props.background, background = _props$background === void 0 ? '#F2F7FAFF' : _props$background, showFullscreen = props.showFullscreen, showForceLayout = props.showForceLayout, showInteractive = props.showInteractive, showFitView = props.showFitView, showZoom = props.showZoom, _props$onlyRenderVisi = props.onlyRenderVisibleElements, onlyRenderVisibleElements = _props$onlyRenderVisi === void 0 ? true : _props$onlyRenderVisi, _rootStyle = props.rootStyle, fitViewOptions = props.fitViewOptions, nodes = props.nodes, edges = props.edges, _props$layout = props.layout, layout = _props$layout === void 0 ? baseLayout : _props$layout, _props$autoCenter = props.autoCenter, autoCenter = _props$autoCenter === void 0 ? false : _props$autoCenter, _props$omitProps = props.omitProps, omitProps = _props$omitProps === void 0 ? [] : _props$omitProps, _props$forceLayout = props.forceLayout, forceLayout = _props$forceLayout === void 0 ? !!props.layout : _props$forceLayout, getMiniMapNodeColor = props.getMiniMapNodeColor, markers = props.markers, plugins = props.plugins, readOnly = props.readOnly, onZoomOut = props.onZoomOut, onZoomIn = props.onZoomIn, onFitView = props.onFitView, onInteractiveChange = props.onInteractiveChange, customControls = props.customControls, _nodeTypes = props.nodeTypes, onEdgesChange = props.onEdgesChange, children = props.children, forceFitView = props.forceFitView; useListenRender(); // 性能监听 hook var _useState = useState(!!(showMiniMap && !showControls)), _useState2 = _slicedToArray(_useState, 2), minimapVisible = _useState2[0], setMinimapVisible = _useState2[1]; // 不显示控制器是默认按照字段控制 miniMap显示状态 var storeApi = useStoreApi(); var containerRef = useRef(null); var theme = useTheme(); var themeVars = useThemeVars(); var nodeTypes = useNodeTypes(_nodeTypes); // 获取注册的节点类型 var forceUpdateTimes = useForceUpdateTimes(); var triggerLayout = useForceUpdate(); var setNodeDragging = useSetNodeDragging(); var instance = useReactFlow(); var getState = useGetState(); var rootStyle = useMemo(function () { return _objectSpread(_objectSpread({ width: typeof width === 'number' ? "".concat(width, "px") : width, height: typeof height === 'number' ? "".concat(height, "px") : height }, _rootStyle), themeVars); }, [width, height, _rootStyle, themeVars]); var _useMemo = useMemo(function () { var store = storeApi.getState(); return layout({ nodeTypes: nodeTypes, originNodes: nodes || [], originEdges: edges || [], theme: theme, onlyRenderVisibleElements: onlyRenderVisibleElements, // 不支持修改该参数 store: store, state: getState(), flowProps: props }); }, [nodes, edges, forceUpdateTimes]), _nodes = _useMemo.nodes, _edges = _useMemo.edges; var flowProps = useMemo(function () { var options = _objectSpread(_objectSpread({ selectNodesOnDrag: false, preventScrolling: true, panOnScroll: false, zoomOnScroll: true, nodesDraggable: false, proOptions: proOptions, fitViewOptions: _objectSpread({ nodes: _nodes !== null && _nodes !== void 0 && _nodes.length && autoCenter ? [_nodes[0]] : undefined }, props.fitViewOptions), fitView: true, onlyRenderVisibleElements: onlyRenderVisibleElements }, omit(props, ['flowInstanceRef', 'width', 'height', 'nodes', 'edges', 'fitViewOptions', 'theme', 'background', 'nodeTypes', 'showControls', 'showMiniMap', 'autoCenter', 'rootStyle', 'layout', 'onNodesChange', 'omitProps', 'forceLayout', 'controlsPosition', 'getMiniMapNodeColor', 'markers', 'onBeforeLayout', 'onLayout', 'onAfterLayout', 'plugins', 'readOnly', 'showFitView', 'showFullscreen', 'showInteractive', 'showZoom', 'showForceLayout', 'onInteractiveChange', 'onZoomOut', 'onZoomIn', 'onFitView', 'customControls', 'controlsOrientation'].concat(_toConsumableArray(omitProps)))), {}, { edgeTypes: _objectSpread({ manhattan: ManhattanEdge }, props.edgeTypes || {}) }); if (plugins !== null && plugins !== void 0 && plugins.scroller) { var _options$panOnDrag, _options$selectionOnD, _options$selectionMod; // 只读模式也需要 options.zoomOnScroll = false; options.panOnScroll = true; options.panOnDrag = (_options$panOnDrag = options.panOnDrag) !== null && _options$panOnDrag !== void 0 ? _options$panOnDrag : [1, 2]; options.selectionOnDrag = (_options$selectionOnD = options.selectionOnDrag) !== null && _options$selectionOnD !== void 0 ? _options$selectionOnD : true; options.selectionMode = (_options$selectionMod = options.selectionMode) !== null && _options$selectionMod !== void 0 ? _options$selectionMod : SelectionMode.Partial; } if (readOnly) { options.nodesDraggable = false; options.nodesConnectable = false; options.elementsSelectable = false; } return options; }, [props, _nodes, readOnly, onlyRenderVisibleElements]); var onNodesChange = useMemoizedFn(function (changes) { var _props$onNodesChange; if (forceLayout && hasDimensionsChange(changes)) { // 强制布局 triggerLayout(); } (_props$onNodesChange = props.onNodesChange) === null || _props$onNodesChange === void 0 || _props$onNodesChange.call(props, changes); }); var onNodeDragStart = useMemoizedFn(function (event, node, nodes) { var _flowProps$onNodeDrag; setNodeDragging(true); (_flowProps$onNodeDrag = flowProps.onNodeDragStart) === null || _flowProps$onNodeDrag === void 0 || _flowProps$onNodeDrag.call(flowProps, event, node, nodes); }); var onNodeDragStop = useMemoizedFn(function (event, node, nodes) { var _flowProps$onNodeDrag2; setNodeDragging(false); (_flowProps$onNodeDrag2 = flowProps.onNodeDragStop) === null || _flowProps$onNodeDrag2 === void 0 || _flowProps$onNodeDrag2.call(flowProps, event, node, nodes); }); var getEdgesChangeHandlers = useGetEdgesChangeHandlers(); var _onEdgesChange = useMemoizedFn(function (changes) { var _getEdgesChangeHandle; onEdgesChange === null || onEdgesChange === void 0 || onEdgesChange(changes); // 触发注册事件 (_getEdgesChangeHandle = getEdgesChangeHandlers()) === null || _getEdgesChangeHandle === void 0 || _getEdgesChangeHandle.forEach(function (onEdgesChange) { onEdgesChange === null || onEdgesChange === void 0 || onEdgesChange(changes); }); }); useEffect(function () { if (forceFitView) { instance.fitView(fitViewOptions); } }, [nodes]); return /*#__PURE__*/_jsxs("div", { ref: containerRef, style: rootStyle, children: [/*#__PURE__*/_jsx(DebugInfo, { debug: props.debug }), markers ? /*#__PURE__*/_jsx(MarkerDefinitions, { marks: markers }) : null, /*#__PURE__*/_jsxs(ReactFlow, _objectSpread(_objectSpread({ nodeTypes: nodeTypes }, flowProps), {}, { nodes: _nodes, edges: _edges, onNodesChange: onNodesChange, onNodeDragStart: onNodeDragStart, onNodeDragStop: onNodeDragStop, onEdgesChange: _onEdgesChange, children: [plugins !== null && plugins !== void 0 && plugins.scroller ? /*#__PURE__*/_jsx(Scrollbar, _objectSpread(_objectSpread({}, plugins.scroller), {}, { width: width, height: height })) : null, /*#__PURE__*/_jsx(Background, { bgColor: background, className: 'rxflow-bg-hide-pattern', variant: BackgroundVariant.Lines }), minimapVisible && /*#__PURE__*/_jsx(MiniMap, { zoomable: true, pannable: true, nodeColor: getMiniMapNodeColor }), showControls && /*#__PURE__*/_jsx(Controls, { showFullscreen: showFullscreen, containerRef: containerRef, fitViewOptions: fitViewOptions, position: controlsPosition, showInteractive: showInteractive, showMiniMap: showMiniMap, showFitView: showFitView, showZoom: showZoom, setMinimapVisible: setMinimapVisible, minimapVisible: minimapVisible, showForceLayout: showForceLayout, onFitView: onFitView, onZoomOut: onZoomOut, onZoomIn: onZoomIn, onInteractiveChange: onInteractiveChange, children: customControls, orientation: controlsOrientation }), showLegend && /*#__PURE__*/_jsx(Legend, { showLegend: showLegend }), children] }))] }); }