UNPKG

@rxflow/base

Version:

BaseFlow - 核心 Flow 组件库

231 lines (230 loc) 10.4 kB
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-06-09 09:45 * @desc: 画布控制器 * * Copyright (c) 2025 by yanxianliang, All Rights Reserved. */ import FullscreenExitOutlined from '@ant-design/icons/FullscreenExitOutlined'; import FullscreenOutlined from '@ant-design/icons/FullscreenOutlined'; import ZoomInOutlined from "@ant-design/icons/lib/icons/ZoomInOutlined"; import ZoomOutOutlined from "@ant-design/icons/lib/icons/ZoomOutOutlined"; import { ControlButton, Panel, useReactFlow, useStore, useStoreApi } from "@xyflow/react"; import { useFullscreen } from "ahooks"; import { Tooltip } from 'antd'; import cc from 'classcat'; import React, { memo, useMemo } from "react"; import { Fragment } from "react/jsx-runtime"; import { shallow } from "zustand/shallow"; import { FitViewIcon, ForceLayout, LockIcon, Minimap, UnlockIcon, UnMinimap } from "./icons"; import { jsx as _jsx } from "react/jsx-runtime"; import { jsxs as _jsxs } from "react/jsx-runtime"; var selector = function selector(s) { return { isInteractive: s.nodesDraggable || s.nodesConnectable || s.elementsSelectable, minZoomReached: s.transform[2] <= s.minZoom, maxZoomReached: s.transform[2] >= s.maxZoom }; }; function Controls(_ref) { var style = _ref.style, _ref$showZoom = _ref.showZoom, showZoom = _ref$showZoom === void 0 ? true : _ref$showZoom, _ref$showFitView = _ref.showFitView, showFitView = _ref$showFitView === void 0 ? true : _ref$showFitView, _ref$showInteractive = _ref.showInteractive, showInteractive = _ref$showInteractive === void 0 ? false : _ref$showInteractive, _ref$showFullscreen = _ref.showFullscreen, showFullscreen = _ref$showFullscreen === void 0 ? true : _ref$showFullscreen, showMiniMap = _ref.showMiniMap, containerRef = _ref.containerRef, fitViewOptions = _ref.fitViewOptions, onZoomIn = _ref.onZoomIn, onZoomOut = _ref.onZoomOut, onFitView = _ref.onFitView, onInteractiveChange = _ref.onInteractiveChange, className = _ref.className, children = _ref.children, _ref$position = _ref.position, position = _ref$position === void 0 ? 'bottom-left' : _ref$position, _ref$orientation = _ref.orientation, orientation = _ref$orientation === void 0 ? 'vertical' : _ref$orientation, _ref$ariaLabel = _ref['aria-label'], ariaLabel = _ref$ariaLabel === void 0 ? 'React Flow controls' : _ref$ariaLabel, minimapVisible = _ref.minimapVisible, setMinimapVisible = _ref.setMinimapVisible, showForceLayout = _ref.showForceLayout; var _useFullscreen = useFullscreen(containerRef), _useFullscreen2 = _slicedToArray(_useFullscreen, 2), isFullscreen = _useFullscreen2[0], toggleFullscreen = _useFullscreen2[1].toggleFullscreen; var tooltipPlacement = useMemo(function () { 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'; } }, []); var store = useStoreApi(); var _useStore = useStore(selector, shallow), isInteractive = _useStore.isInteractive, minZoomReached = _useStore.minZoomReached, maxZoomReached = _useStore.maxZoomReached; var _useReactFlow = useReactFlow(), zoomIn = _useReactFlow.zoomIn, zoomOut = _useReactFlow.zoomOut, fitView = _useReactFlow.fitView; var onZoomInHandler = function onZoomInHandler() { zoomIn(); onZoomIn === null || onZoomIn === void 0 || onZoomIn(); }; var onZoomOutHandler = function onZoomOutHandler() { zoomOut(); onZoomOut === null || onZoomOut === void 0 || onZoomOut(); }; var onFitViewHandler = function onFitViewHandler() { fitView(fitViewOptions); onFitView === null || onFitView === void 0 || onFitView(); }; var onToggleInteractivity = function onToggleInteractivity() { store.setState({ nodesDraggable: !isInteractive, nodesConnectable: !isInteractive, elementsSelectable: !isInteractive }); onInteractiveChange === null || onInteractiveChange === void 0 || onInteractiveChange(!isInteractive); }; var onForceLayout = function onForceLayout() { // TODO 美化布局 }; var onToggleMiniMap = function onToggleMiniMap() { setMinimapVisible(!minimapVisible); }; var orientationClass = orientation === 'horizontal' ? 'horizontal' : 'vertical'; return /*#__PURE__*/_jsxs(Panel, { className: cc(['react-flow__controls', orientationClass, className]), position: position, style: style, "data-testid": "rf__controls", "aria-label": ariaLabel, children: [showZoom && /*#__PURE__*/_jsxs(Fragment, { children: [/*#__PURE__*/_jsx(Tooltip, { title: '放大', placement: tooltipPlacement, children: /*#__PURE__*/_jsx("span", { children: /*#__PURE__*/_jsx(ControlButton, { onClick: onZoomInHandler, className: "react-flow__controls-zoomin", title: '放大', "aria-label": 'zoom in', disabled: maxZoomReached, children: /*#__PURE__*/_jsx(ZoomInOutlined, {}) }) }) }), /*#__PURE__*/_jsx(Tooltip, { title: '缩小', placement: tooltipPlacement, children: /*#__PURE__*/_jsx("span", { children: /*#__PURE__*/_jsx(ControlButton, { onClick: onZoomOutHandler, className: "react-flow__controls-zoomout", title: '缩小', "aria-label": 'zoom out', disabled: minZoomReached, children: /*#__PURE__*/_jsx(ZoomOutOutlined, {}) }) }) })] }), showFitView && /*#__PURE__*/_jsx(Tooltip, { title: '自适应视图', placement: tooltipPlacement, children: /*#__PURE__*/_jsx("span", { children: /*#__PURE__*/_jsx(ControlButton, { className: "react-flow__controls-fitview", onClick: onFitViewHandler, title: '自适应视图', "aria-label": 'fit view', children: /*#__PURE__*/_jsx(FitViewIcon, {}) }) }) }), showFullscreen && /*#__PURE__*/_jsx(Tooltip, { title: isFullscreen ? '取消全屏' : '全屏', placement: tooltipPlacement, children: /*#__PURE__*/_jsx("span", { children: /*#__PURE__*/_jsx(ControlButton, { className: "react-flow__controls-fullscreen", onClick: toggleFullscreen, title: isFullscreen ? '取消全屏' : '全屏', "aria-label": "toggle fullscreen", children: isFullscreen ? /*#__PURE__*/_jsx(FullscreenExitOutlined, {}) : /*#__PURE__*/_jsx(FullscreenOutlined, {}) }) }) }), showMiniMap && /*#__PURE__*/_jsx(Tooltip, { title: minimapVisible ? '关闭缩略图' : '开启缩略图', placement: tooltipPlacement, children: /*#__PURE__*/_jsx("span", { children: /*#__PURE__*/_jsx(ControlButton, { className: "react-flow__controls-interactive", onClick: onToggleMiniMap, title: minimapVisible ? '关闭缩略图' : '开启缩略图', "aria-label": "toggle minimap", children: minimapVisible ? /*#__PURE__*/_jsx(UnMinimap, {}) : /*#__PURE__*/_jsx(Minimap, {}) }) }) }), showInteractive && /*#__PURE__*/_jsx(Tooltip, { title: isInteractive ? '解锁' : '锁定', placement: tooltipPlacement, children: /*#__PURE__*/_jsx("span", { children: /*#__PURE__*/_jsx(ControlButton, { className: "react-flow__controls-interactive", onClick: onToggleInteractivity, title: isInteractive ? '解锁' : '锁定', "aria-label": "toggle interactivity", children: isInteractive ? /*#__PURE__*/_jsx(UnlockIcon, {}) : /*#__PURE__*/_jsx(LockIcon, {}) }) }) }), showForceLayout && /*#__PURE__*/_jsx(Tooltip, { title: '美化布局', placement: tooltipPlacement, children: /*#__PURE__*/_jsx("span", { children: /*#__PURE__*/_jsx(ControlButton, { className: "react-flow__controls-layout", onClick: onForceLayout, title: '美化布局', "aria-label": "force layout", children: /*#__PURE__*/_jsx(ForceLayout, {}) }) }) }), children] }); } export default /*#__PURE__*/memo(Controls);