import React, { memo, useCallback, FC, useEffect, useState, PropsWithChildren } from 'react'; import cc from 'classcat'; import { useStore, useStoreApi } from '../../store'; import useReactFlow from '../../hooks/useReactFlow'; 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 { ControlProps, ControlButtonProps, ReactFlowState } from '../../types'; export const ControlButton: FC> = ({ children, className, ...rest }) => ( ); 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, }) => { const store = useStoreApi(); const [isVisible, setIsVisible] = useState(false); const isInteractive = useStore(isInteractiveSelector); const { zoomIn, zoomOut, fitView } = useReactFlow(); const mapClasses = cc(['react-flow__controls', className]); const onZoomInHandler = useCallback(() => { zoomIn?.(); onZoomIn?.(); }, [zoomIn, onZoomIn]); const onZoomOutHandler = useCallback(() => { zoomOut?.(); onZoomOut?.(); }, [zoomOut, onZoomOut]); const onFitViewHandler = useCallback(() => { fitView?.(fitViewOptions); onFitView?.(); }, [fitView, fitViewOptions, onFitView]); const onInteractiveChangeHandler = useCallback(() => { store.setState({ nodesDraggable: !isInteractive, nodesConnectable: !isInteractive, elementsSelectable: !isInteractive, }); onInteractiveChange?.(!isInteractive); }, [isInteractive, onInteractiveChange]); useEffect(() => { setIsVisible(true); }, []); if (!isVisible) { return null; } return (
{showZoom && ( <> )} {showFitView && ( )} {showInteractive && ( {isInteractive ? : } )} {children}
); }; Controls.displayName = 'Controls'; export default memo(Controls);