Files
xyflow/src/container/FlowRenderer/index.tsx
T

139 lines
3.6 KiB
TypeScript

import React, { useCallback, memo, ReactNode, WheelEvent, MouseEvent } from 'react';
import shallow from 'zustand/shallow';
import { useStore } from '../../store';
import useGlobalKeyHandler from '../../hooks/useGlobalKeyHandler';
import useKeyPress from '../../hooks/useKeyPress';
import { GraphViewProps } from '../GraphView';
import ZoomPane from '../ZoomPane';
import UserSelection from '../../components/UserSelection';
import NodesSelection from '../../components/NodesSelection';
import { ReactFlowState } from '../../types';
interface FlowRendererProps
extends Omit<
GraphViewProps,
| 'snapToGrid'
| 'nodeTypes'
| 'edgeTypes'
| 'snapGrid'
| 'connectionLineType'
| 'arrowHeadColor'
| 'onlyRenderVisibleElements'
| 'selectNodesOnDrag'
| 'defaultMarkerColor'
> {
children: ReactNode;
}
const selector = (s: ReactFlowState) => ({
setNodesSelectionActive: s.setNodesSelectionActive,
resetSelectedElements: s.resetSelectedElements,
nodesSelectionActive: s.nodesSelectionActive,
});
const FlowRenderer = ({
children,
onPaneClick,
onPaneContextMenu,
onPaneScroll,
deleteKeyCode,
onMove,
onMoveStart,
onMoveEnd,
selectionKeyCode,
multiSelectionKeyCode,
zoomActivationKeyCode,
elementsSelectable,
zoomOnScroll,
zoomOnPinch,
panOnScroll,
panOnScrollSpeed,
panOnScrollMode,
zoomOnDoubleClick,
paneMoveable,
defaultPosition,
defaultZoom,
preventScrolling,
onSelectionDragStart,
onSelectionDrag,
onSelectionDragStop,
onSelectionContextMenu,
noWheelClassName,
noPanClassName,
}: FlowRendererProps) => {
const { setNodesSelectionActive, resetSelectedElements, nodesSelectionActive } = useStore(selector, shallow);
const selectionKeyPressed = useKeyPress(selectionKeyCode);
useGlobalKeyHandler({ deleteKeyCode, multiSelectionKeyCode });
const onClick = useCallback(
(event: MouseEvent) => {
onPaneClick?.(event);
setNodesSelectionActive(false);
resetSelectedElements();
},
[onPaneClick]
);
const onContextMenu = useCallback(
(event: MouseEvent) => {
onPaneContextMenu?.(event);
},
[onPaneContextMenu]
);
const onWheel = useCallback(
(event: WheelEvent) => {
onPaneScroll?.(event);
},
[onPaneScroll]
);
return (
<ZoomPane
onMove={onMove}
onMoveStart={onMoveStart}
onMoveEnd={onMoveEnd}
selectionKeyPressed={selectionKeyPressed}
elementsSelectable={elementsSelectable}
zoomOnScroll={zoomOnScroll}
zoomOnPinch={zoomOnPinch}
panOnScroll={panOnScroll}
panOnScrollSpeed={panOnScrollSpeed}
panOnScrollMode={panOnScrollMode}
zoomOnDoubleClick={zoomOnDoubleClick}
paneMoveable={paneMoveable}
defaultPosition={defaultPosition}
defaultZoom={defaultZoom}
zoomActivationKeyCode={zoomActivationKeyCode}
preventScrolling={preventScrolling}
noWheelClassName={noWheelClassName}
noPanClassName={noPanClassName}
>
{children}
<UserSelection selectionKeyPressed={selectionKeyPressed} />
{nodesSelectionActive && (
<NodesSelection
onSelectionDragStart={onSelectionDragStart}
onSelectionDrag={onSelectionDrag}
onSelectionDragStop={onSelectionDragStop}
onSelectionContextMenu={onSelectionContextMenu}
noPanClassName={noPanClassName}
/>
)}
<div
className="react-flow__pane react-flow__container"
onClick={onClick}
onContextMenu={onContextMenu}
onWheel={onWheel}
/>
</ZoomPane>
);
};
FlowRenderer.displayName = 'FlowRenderer';
export default memo(FlowRenderer);