@rxflow/base
Version:
BaseFlow - 核心 Flow 组件库
225 lines (223 loc) • 9.05 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _FullscreenExitOutlined = _interopRequireDefault(require("@ant-design/icons/FullscreenExitOutlined"));
var _FullscreenOutlined = _interopRequireDefault(require("@ant-design/icons/FullscreenOutlined"));
var _ZoomInOutlined = _interopRequireDefault(require("@ant-design/icons/lib/icons/ZoomInOutlined"));
var _ZoomOutOutlined = _interopRequireDefault(require("@ant-design/icons/lib/icons/ZoomOutOutlined"));
var _react = require("@xyflow/react");
var _ahooks = require("ahooks");
var _antd = require("antd");
var _classcat = _interopRequireDefault(require("classcat"));
var _react2 = _interopRequireWildcard(require("react"));
var _jsxRuntime = require("react/jsx-runtime");
var _shallow = require("zustand/shallow");
var _icons = require("./icons");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/*
* @author: yanxianliang
* @date: 2025-06-09 09:45
* @desc: 画布控制器
*
* Copyright (c) 2025 by yanxianliang, All Rights Reserved.
*/
const selector = s => ({
isInteractive: s.nodesDraggable || s.nodesConnectable || s.elementsSelectable,
minZoomReached: s.transform[2] <= s.minZoom,
maxZoomReached: s.transform[2] >= s.maxZoom
});
function Controls({
style,
showZoom = true,
showFitView = true,
showInteractive = false,
showFullscreen = true,
showMiniMap,
containerRef,
fitViewOptions,
onZoomIn,
onZoomOut,
onFitView,
onInteractiveChange,
className,
children,
position = 'bottom-left',
orientation = 'vertical',
'aria-label': ariaLabel = 'React Flow controls',
minimapVisible,
setMinimapVisible,
showForceLayout
}) {
const [isFullscreen, {
toggleFullscreen
}] = (0, _ahooks.useFullscreen)(containerRef);
const tooltipPlacement = (0, _react2.useMemo)(() => {
switch (position) {
case 'top-left':
case 'center-left':
case 'top-center':
if (orientation === 'horizontal') {
return 'bottom';
}
return 'right';
case 'top-right':
case 'center-right':
if (orientation === 'horizontal') {
return 'bottom';
}
return 'left';
case 'bottom-left':
case 'bottom-center':
if (orientation === 'horizontal') {
return 'top';
}
return 'right';
case 'bottom-right':
if (orientation === 'horizontal') {
return 'top';
}
return 'left';
default:
return 'top';
}
}, []);
const store = (0, _react.useStoreApi)();
const {
isInteractive,
minZoomReached,
maxZoomReached
} = (0, _react.useStore)(selector, _shallow.shallow);
const {
zoomIn,
zoomOut,
fitView
} = (0, _react.useReactFlow)();
const onZoomInHandler = () => {
zoomIn();
onZoomIn?.();
};
const onZoomOutHandler = () => {
zoomOut();
onZoomOut?.();
};
const onFitViewHandler = () => {
fitView(fitViewOptions);
onFitView?.();
};
const onToggleInteractivity = () => {
store.setState({
nodesDraggable: !isInteractive,
nodesConnectable: !isInteractive,
elementsSelectable: !isInteractive
});
onInteractiveChange?.(!isInteractive);
};
const onForceLayout = () => {
// TODO 美化布局
};
const onToggleMiniMap = () => {
setMinimapVisible(!minimapVisible);
};
const orientationClass = orientation === 'horizontal' ? 'horizontal' : 'vertical';
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_react.Panel, {
className: (0, _classcat.default)(['react-flow__controls', orientationClass, className]),
position: position,
style: style,
"data-testid": "rf__controls",
"aria-label": ariaLabel,
children: [showZoom && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Tooltip, {
title: '放大',
placement: tooltipPlacement,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_react.ControlButton, {
onClick: onZoomInHandler,
className: "react-flow__controls-zoomin",
title: '放大',
"aria-label": 'zoom in',
disabled: maxZoomReached,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ZoomInOutlined.default, {})
})
})
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Tooltip, {
title: '缩小',
placement: tooltipPlacement,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_react.ControlButton, {
onClick: onZoomOutHandler,
className: "react-flow__controls-zoomout",
title: '缩小',
"aria-label": 'zoom out',
disabled: minZoomReached,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ZoomOutOutlined.default, {})
})
})
})]
}), showFitView && /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Tooltip, {
title: '自适应视图',
placement: tooltipPlacement,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_react.ControlButton, {
className: "react-flow__controls-fitview",
onClick: onFitViewHandler,
title: '自适应视图',
"aria-label": 'fit view',
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.FitViewIcon, {})
})
})
}), showFullscreen && /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Tooltip, {
title: isFullscreen ? '取消全屏' : '全屏',
placement: tooltipPlacement,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_react.ControlButton, {
className: "react-flow__controls-fullscreen",
onClick: toggleFullscreen,
title: isFullscreen ? '取消全屏' : '全屏',
"aria-label": "toggle fullscreen",
children: isFullscreen ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_FullscreenExitOutlined.default, {}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_FullscreenOutlined.default, {})
})
})
}), showMiniMap && /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Tooltip, {
title: minimapVisible ? '关闭缩略图' : '开启缩略图',
placement: tooltipPlacement,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_react.ControlButton, {
className: "react-flow__controls-interactive",
onClick: onToggleMiniMap,
title: minimapVisible ? '关闭缩略图' : '开启缩略图',
"aria-label": "toggle minimap",
children: minimapVisible ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.UnMinimap, {}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.Minimap, {})
})
})
}), showInteractive && /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Tooltip, {
title: isInteractive ? '解锁' : '锁定',
placement: tooltipPlacement,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_react.ControlButton, {
className: "react-flow__controls-interactive",
onClick: onToggleInteractivity,
title: isInteractive ? '解锁' : '锁定',
"aria-label": "toggle interactivity",
children: isInteractive ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.UnlockIcon, {}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.LockIcon, {})
})
})
}), showForceLayout && /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Tooltip, {
title: '美化布局',
placement: tooltipPlacement,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_react.ControlButton, {
className: "react-flow__controls-layout",
onClick: onForceLayout,
title: '美化布局',
"aria-label": "force layout",
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.ForceLayout, {})
})
})
}), children]
});
}
var _default = exports.default = /*#__PURE__*/(0, _react2.memo)(Controls);