import { memo, useEffect, useState } from 'react'; import type { FC, PropsWithChildren } from 'react'; import cc from 'classcat'; import { useStore, useStoreApi, useReactFlow, Panel } from '@reactflow/core'; import type { ReactFlowState } from '@reactflow/core'; import PlusIcon from './Icons/Plus'; import MinusIcon from './Icons/Minus'; import FitviewIcon from './Icons/FitView'; import LockIcon from './Icons/Lock'; import UnlockIcon from './Icons/Unlock'; import ControlButton from './ControlButton'; import type { ControlProps } from './types'; const isInteractiveSelector = (s: ReactFlowState) => s.nodesDraggable && s.nodesConnectable && s.elementsSelectable; const Controls: FC> = ({ style, showZoom = true, showFitView = true, showInteractive = true, fitViewOptions, onZoomIn, onZoomOut, onFitView, onInteractiveChange, className, children, position = 'bottom-left', }) => { const store = useStoreApi(); const [isVisible, setIsVisible] = useState(false); const isInteractive = useStore(isInteractiveSelector); const { zoomIn, zoomOut, fitView } = useReactFlow(); useEffect(() => { setIsVisible(true); }, []); if (!isVisible) { return null; } 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); }; return ( {showZoom && ( <> )} {showFitView && ( )} {showInteractive && ( {isInteractive ? : } )} {children} ); }; Controls.displayName = 'Controls'; export default memo(Controls);