Merge pull request #548 from wbkd/refactor/prophandling

Refactor/prophandling
This commit is contained in:
Moritz
2020-10-05 11:15:39 +02:00
committed by GitHub
7 changed files with 160 additions and 149 deletions
+1 -1
View File
@@ -216,7 +216,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
const width = useStoreState((state) => state.width); const width = useStoreState((state) => state.width);
const height = useStoreState((state) => state.height); const height = useStoreState((state) => state.height);
const { connectionLineStyle, connectionLineType, arrowHeadColor, connectionLineComponent } = props; const { connectionLineType, arrowHeadColor, connectionLineStyle, connectionLineComponent } = props;
if (!width) { if (!width) {
return null; return null;
+64 -40
View File
@@ -63,20 +63,20 @@ export interface GraphViewProps {
snapToGrid: boolean; snapToGrid: boolean;
snapGrid: [number, number]; snapGrid: [number, number];
onlyRenderVisibleNodes: boolean; onlyRenderVisibleNodes: boolean;
nodesDraggable: boolean; nodesDraggable?: boolean;
nodesConnectable: boolean; nodesConnectable?: boolean;
elementsSelectable: boolean; elementsSelectable?: boolean;
selectNodesOnDrag: boolean; selectNodesOnDrag?: boolean;
minZoom: number; minZoom?: number;
maxZoom: number; maxZoom?: number;
defaultZoom: number; defaultZoom: number;
defaultPosition: [number, number]; defaultPosition: [number, number];
translateExtent?: TranslateExtent; translateExtent?: TranslateExtent;
arrowHeadColor: string; arrowHeadColor: string;
markerEndId?: string; markerEndId?: string;
zoomOnScroll: boolean; zoomOnScroll?: boolean;
zoomOnDoubleClick: boolean; zoomOnDoubleClick?: boolean;
paneMoveable: boolean; paneMoveable?: boolean;
} }
const GraphView = ({ const GraphView = ({
@@ -114,7 +114,7 @@ const GraphView = ({
nodesDraggable, nodesDraggable,
nodesConnectable, nodesConnectable,
elementsSelectable, elementsSelectable,
selectNodesOnDrag, selectNodesOnDrag = true,
minZoom, minZoom,
maxZoom, maxZoom,
defaultZoom, defaultZoom,
@@ -140,39 +140,19 @@ const GraphView = ({
const setOnConnectStop = useStoreActions((actions) => actions.setOnConnectStop); const setOnConnectStop = useStoreActions((actions) => actions.setOnConnectStop);
const setOnConnectEnd = useStoreActions((actions) => actions.setOnConnectEnd); const setOnConnectEnd = useStoreActions((actions) => actions.setOnConnectEnd);
const setSnapGrid = useStoreActions((actions) => actions.setSnapGrid); const setSnapGrid = useStoreActions((actions) => actions.setSnapGrid);
const setSnapToGrid = useStoreActions((actions) => actions.setSnapToGrid);
const setNodesDraggable = useStoreActions((actions) => actions.setNodesDraggable); const setNodesDraggable = useStoreActions((actions) => actions.setNodesDraggable);
const setNodesConnectable = useStoreActions((actions) => actions.setNodesConnectable); const setNodesConnectable = useStoreActions((actions) => actions.setNodesConnectable);
const setElementsSelectable = useStoreActions((actions) => actions.setElementsSelectable); const setElementsSelectable = useStoreActions((actions) => actions.setElementsSelectable);
const setInitTransform = useStoreActions((actions) => actions.setInitTransform); const setInitTransform = useStoreActions((actions) => actions.setInitTransform);
const setMinMaxZoom = useStoreActions((actions) => actions.setMinMaxZoom); const setMinZoom = useStoreActions((actions) => actions.setMinZoom);
const setMaxZoom = useStoreActions((actions) => actions.setMaxZoom);
const setTranslateExtent = useStoreActions((actions) => actions.setTranslateExtent); const setTranslateExtent = useStoreActions((actions) => actions.setTranslateExtent);
const fitView = useStoreActions((actions) => actions.fitView); const fitView = useStoreActions((actions) => actions.fitView);
const zoom = useStoreActions((actions) => actions.zoom); const zoom = useStoreActions((actions) => actions.zoom);
const zoomTo = useStoreActions((actions) => actions.zoomTo); const zoomTo = useStoreActions((actions) => actions.zoomTo);
const currentStore = useStore(); const currentStore = useStore();
const onZoomPaneClick = useCallback(
(event: React.MouseEvent) => {
onPaneClick?.(event);
unsetNodesSelection();
},
[onPaneClick]
);
const onZoomPaneContextMenu = useCallback(
(event: React.MouseEvent) => {
onPaneContextMenu?.(event);
},
[onPaneContextMenu]
);
const onZoomPaneScroll = useCallback(
(event: WheelEvent) => {
onPaneScroll?.(event);
},
[onPaneScroll]
);
useResizeHandler(rendererNode); useResizeHandler(rendererNode);
useGlobalKeyHandler({ onElementsRemove, deleteKeyCode }); useGlobalKeyHandler({ onElementsRemove, deleteKeyCode });
useElementUpdater(elements); useElementUpdater(elements);
@@ -212,6 +192,28 @@ const GraphView = ({
} }
}, [d3Initialised, onLoad]); }, [d3Initialised, onLoad]);
const onZoomPaneClick = useCallback(
(event: React.MouseEvent) => {
onPaneClick?.(event);
unsetNodesSelection();
},
[onPaneClick]
);
const onZoomPaneContextMenu = useCallback(
(event: React.MouseEvent) => {
onPaneContextMenu?.(event);
},
[onPaneContextMenu]
);
const onZoomPaneScroll = useCallback(
(event: WheelEvent) => {
onPaneScroll?.(event);
},
[onPaneScroll]
);
useEffect(() => { useEffect(() => {
if (onConnect) { if (onConnect) {
setOnConnect(onConnect); setOnConnect(onConnect);
@@ -237,24 +239,46 @@ const GraphView = ({
}, [onConnectEnd]); }, [onConnectEnd]);
useEffect(() => { useEffect(() => {
setSnapGrid({ snapToGrid, snapGrid }); if (typeof snapToGrid !== 'undefined') {
}, [snapToGrid, snapGrid]); setSnapToGrid(snapToGrid);
}
}, [snapToGrid]);
useEffect(() => { useEffect(() => {
setNodesDraggable(nodesDraggable); if (typeof snapGrid !== 'undefined') {
setSnapGrid(snapGrid);
}
}, [snapGrid]);
useEffect(() => {
if (typeof nodesDraggable !== 'undefined') {
setNodesDraggable(nodesDraggable);
}
}, [nodesDraggable]); }, [nodesDraggable]);
useEffect(() => { useEffect(() => {
setNodesConnectable(nodesConnectable); if (typeof nodesConnectable !== 'undefined') {
setNodesConnectable(nodesConnectable);
}
}, [nodesConnectable]); }, [nodesConnectable]);
useEffect(() => { useEffect(() => {
setElementsSelectable(elementsSelectable); if (typeof elementsSelectable !== 'undefined') {
setElementsSelectable(elementsSelectable);
}
}, [elementsSelectable]); }, [elementsSelectable]);
useEffect(() => { useEffect(() => {
setMinMaxZoom({ minZoom, maxZoom }); if (typeof minZoom !== 'undefined') {
}, [minZoom, maxZoom]); setMinZoom(minZoom);
}
}, [minZoom]);
useEffect(() => {
if (typeof maxZoom !== 'undefined') {
setMaxZoom(maxZoom);
}
}, [maxZoom]);
useEffect(() => { useEffect(() => {
if (typeof translateExtent !== 'undefined') { if (typeof translateExtent !== 'undefined') {
+5 -5
View File
@@ -14,9 +14,9 @@ interface NodeRendererProps {
onNodeContextMenu?: (event: MouseEvent, node: Node) => void; onNodeContextMenu?: (event: MouseEvent, node: Node) => void;
onNodeDragStart?: (event: MouseEvent, node: Node) => void; onNodeDragStart?: (event: MouseEvent, node: Node) => void;
onNodeDragStop?: (event: MouseEvent, node: Node) => void; onNodeDragStop?: (event: MouseEvent, node: Node) => void;
onlyRenderVisibleNodes?: boolean; onlyRenderVisibleNodes: boolean;
snapToGrid?: boolean; snapToGrid: boolean;
snapGrid?: [number, number]; snapGrid: [number, number];
} }
function renderNode( function renderNode(
@@ -75,7 +75,7 @@ function renderNode(
); );
} }
const NodeRenderer = ({ onlyRenderVisibleNodes = true, ...props }: NodeRendererProps) => { const NodeRenderer = (props: NodeRendererProps) => {
const nodes = useStoreState((s) => s.nodes); const nodes = useStoreState((s) => s.nodes);
const transform = useStoreState((s) => s.transform); const transform = useStoreState((s) => s.transform);
const selectedElements = useStoreState((s) => s.selectedElements); const selectedElements = useStoreState((s) => s.selectedElements);
@@ -88,7 +88,7 @@ const NodeRenderer = ({ onlyRenderVisibleNodes = true, ...props }: NodeRendererP
transform: `translate(${transform[0]}px,${transform[1]}px) scale(${transform[2]})`, transform: `translate(${transform[0]}px,${transform[1]}px) scale(${transform[2]})`,
}; };
const renderNodes = onlyRenderVisibleNodes ? getNodesInside(nodes, viewportBox, transform, true) : nodes; const renderNodes = props.onlyRenderVisibleNodes ? getNodesInside(nodes, viewportBox, transform, true) : nodes;
return ( return (
<div className="react-flow__nodes" style={transformStyle}> <div className="react-flow__nodes" style={transformStyle}>
+54 -73
View File
@@ -36,6 +36,19 @@ import {
import '../../style.css'; import '../../style.css';
const defaultNodeTypes = {
input: InputNode,
default: DefaultNode,
output: OutputNode,
};
const defaultEdgeTypes = {
default: BezierEdge,
straight: StraightEdge,
step: StepEdge,
smoothstep: SmoothStepEdge,
};
export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onLoad'> { export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onLoad'> {
elements: Elements; elements: Elements;
onElementClick?: (event: MouseEvent, element: Node | Edge) => void; onElementClick?: (event: MouseEvent, element: Node | Edge) => void;
@@ -62,40 +75,38 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
onPaneScroll?: (event?: WheelEvent) => void; onPaneScroll?: (event?: WheelEvent) => void;
onPaneClick?: (event: MouseEvent) => void; onPaneClick?: (event: MouseEvent) => void;
onPaneContextMenu?: (event: MouseEvent) => void; onPaneContextMenu?: (event: MouseEvent) => void;
nodeTypes: NodeTypesType; nodeTypes?: NodeTypesType;
edgeTypes: EdgeTypesType; edgeTypes?: EdgeTypesType;
connectionLineType: ConnectionLineType; connectionLineType?: ConnectionLineType;
connectionLineStyle?: CSSProperties; connectionLineStyle?: CSSProperties;
connectionLineComponent?: ConnectionLineComponent; connectionLineComponent?: ConnectionLineComponent;
deleteKeyCode: number; deleteKeyCode?: number;
selectionKeyCode: number; selectionKeyCode?: number;
snapToGrid: boolean; snapToGrid?: boolean;
snapGrid: [number, number]; snapGrid?: [number, number];
onlyRenderVisibleNodes: boolean; onlyRenderVisibleNodes?: boolean;
nodesDraggable: boolean; nodesDraggable?: boolean;
nodesConnectable: boolean; nodesConnectable?: boolean;
elementsSelectable: boolean; elementsSelectable?: boolean;
selectNodesOnDrag: boolean; selectNodesOnDrag?: boolean;
paneMoveable: boolean; paneMoveable?: boolean;
minZoom: number; minZoom?: number;
maxZoom: number; maxZoom?: number;
defaultZoom: number; defaultZoom?: number;
defaultPosition: [number, number]; defaultPosition?: [number, number];
translateExtent?: TranslateExtent; translateExtent?: TranslateExtent;
arrowHeadColor: string; arrowHeadColor?: string;
markerEndId?: string; markerEndId?: string;
zoomOnScroll: boolean; zoomOnScroll?: boolean;
zoomOnDoubleClick: boolean; zoomOnDoubleClick?: boolean;
} }
const ReactFlow = ({ const ReactFlow = ({
style,
onElementClick,
elements = [], elements = [],
className, className,
children, nodeTypes = defaultNodeTypes,
nodeTypes, edgeTypes = defaultEdgeTypes,
edgeTypes, onElementClick,
onLoad, onLoad,
onMove, onMove,
onMoveStart, onMoveStart,
@@ -116,38 +127,40 @@ const ReactFlow = ({
onSelectionDrag, onSelectionDrag,
onSelectionDragStop, onSelectionDragStop,
onSelectionContextMenu, onSelectionContextMenu,
connectionLineType, connectionLineType = ConnectionLineType.Bezier,
connectionLineStyle, connectionLineStyle,
connectionLineComponent, connectionLineComponent,
deleteKeyCode, deleteKeyCode = 8,
selectionKeyCode, selectionKeyCode = 16,
snapToGrid, snapToGrid = false,
snapGrid, snapGrid = [15, 15],
onlyRenderVisibleNodes, onlyRenderVisibleNodes = true,
selectNodesOnDrag = true,
nodesDraggable, nodesDraggable,
nodesConnectable, nodesConnectable,
elementsSelectable, elementsSelectable,
selectNodesOnDrag,
minZoom, minZoom,
maxZoom, maxZoom,
defaultZoom, defaultZoom = 1,
defaultPosition, defaultPosition = [0, 0],
translateExtent, translateExtent,
arrowHeadColor, arrowHeadColor = '#b1b1b7',
markerEndId, markerEndId,
zoomOnScroll, zoomOnScroll = true,
zoomOnDoubleClick, zoomOnDoubleClick = true,
paneMoveable, paneMoveable = true,
onPaneClick, onPaneClick,
onPaneScroll, onPaneScroll,
onPaneContextMenu, onPaneContextMenu,
children,
...rest
}: ReactFlowProps) => { }: ReactFlowProps) => {
const nodeTypesParsed = useMemo(() => createNodeTypes(nodeTypes), [nodeTypes]); const nodeTypesParsed = useMemo(() => createNodeTypes(nodeTypes), []);
const edgeTypesParsed = useMemo(() => createEdgeTypes(edgeTypes), [edgeTypes]); const edgeTypesParsed = useMemo(() => createEdgeTypes(edgeTypes), []);
const reactFlowClasses = cc(['react-flow', className]); const reactFlowClasses = cc(['react-flow', className]);
return ( return (
<div style={style} className={reactFlowClasses}> <div {...rest} className={reactFlowClasses}>
<Wrapper> <Wrapper>
<GraphView <GraphView
onLoad={onLoad} onLoad={onLoad}
@@ -208,36 +221,4 @@ const ReactFlow = ({
ReactFlow.displayName = 'ReactFlow'; ReactFlow.displayName = 'ReactFlow';
ReactFlow.defaultProps = {
nodeTypes: {
input: InputNode,
default: DefaultNode,
output: OutputNode,
},
edgeTypes: {
default: BezierEdge,
straight: StraightEdge,
step: StepEdge,
smoothstep: SmoothStepEdge,
},
connectionLineType: ConnectionLineType.Bezier,
deleteKeyCode: 8,
selectionKeyCode: 16,
snapToGrid: false,
snapGrid: [15, 15],
onlyRenderVisibleNodes: true,
nodesDraggable: true,
nodesConnectable: true,
elementsSelectable: true,
selectNodesOnDrag: true,
paneMoveable: true,
minZoom: 0.5,
maxZoom: 2,
defaultZoom: 1,
defaultPosition: [0, 0],
arrowHeadColor: '#b1b1b7',
zoomOnScroll: true,
zoomOnDoubleClick: true,
};
export default ReactFlow; export default ReactFlow;
+10 -10
View File
@@ -6,11 +6,11 @@ import { FlowTransform, TranslateExtent } from '../types';
interface UseD3ZoomParams { interface UseD3ZoomParams {
zoomPane: MutableRefObject<Element | null>; zoomPane: MutableRefObject<Element | null>;
selectionKeyPressed: boolean; selectionKeyPressed: boolean;
zoomOnScroll: boolean; zoomOnScroll?: boolean;
zoomOnDoubleClick: boolean; zoomOnDoubleClick?: boolean;
paneMoveable: boolean; paneMoveable?: boolean;
defaultPosition: [number, number]; defaultPosition?: [number, number];
defaultZoom: number; defaultZoom?: number;
translateExtent?: TranslateExtent; translateExtent?: TranslateExtent;
onMove?: (flowTransform?: FlowTransform) => void; onMove?: (flowTransform?: FlowTransform) => void;
onMoveStart?: (flowTransform?: FlowTransform) => void; onMoveStart?: (flowTransform?: FlowTransform) => void;
@@ -33,12 +33,12 @@ export default ({
onMove, onMove,
onMoveStart, onMoveStart,
onMoveEnd, onMoveEnd,
zoomOnScroll, zoomOnScroll = true,
zoomOnDoubleClick, zoomOnDoubleClick = true,
selectionKeyPressed, selectionKeyPressed,
paneMoveable, paneMoveable = true,
defaultPosition, defaultPosition = [0, 0],
defaultZoom, defaultZoom = 1,
translateExtent, translateExtent,
}: UseD3ZoomParams): void => { }: UseD3ZoomParams): void => {
const prevTransform = useRef<FlowTransform>({ x: 0, y: 0, zoom: 0 }); const prevTransform = useRef<FlowTransform>({ x: 0, y: 0, zoom: 0 });
+23 -19
View File
@@ -28,6 +28,7 @@ import {
NodeDiffUpdate, NodeDiffUpdate,
FitViewParams, FitViewParams,
TranslateExtent, TranslateExtent,
SnapGrid,
} from '../types'; } from '../types';
type TransformXYK = { type TransformXYK = {
@@ -41,16 +42,6 @@ type NodeDimensionUpdate = {
nodeElement: HTMLDivElement; nodeElement: HTMLDivElement;
}; };
type SetMinMaxZoom = {
minZoom: number;
maxZoom: number;
};
type SetSnapGrid = {
snapToGrid: boolean;
snapGrid: [number, number];
};
type InitD3 = { type InitD3 = {
zoomPane: Element; zoomPane: Element;
defaultPosition: [number, number]; defaultPosition: [number, number];
@@ -85,7 +76,7 @@ export interface StoreModel {
connectionPosition: XYPosition; connectionPosition: XYPosition;
snapToGrid: boolean; snapToGrid: boolean;
snapGrid: [number, number]; snapGrid: SnapGrid;
nodesDraggable: boolean; nodesDraggable: boolean;
nodesConnectable: boolean; nodesConnectable: boolean;
@@ -124,11 +115,13 @@ export interface StoreModel {
initD3: Action<StoreModel, InitD3>; initD3: Action<StoreModel, InitD3>;
setMinMaxZoom: Action<StoreModel, SetMinMaxZoom>; setMinZoom: Action<StoreModel, number>;
setMaxZoom: Action<StoreModel, number>;
setTranslateExtent: Action<StoreModel, TranslateExtent>; setTranslateExtent: Action<StoreModel, TranslateExtent>;
setSnapGrid: Action<StoreModel, SetSnapGrid>; setSnapToGrid: Action<StoreModel, boolean>;
setSnapGrid: Action<StoreModel, SnapGrid>;
setConnectionPosition: Action<StoreModel, XYPosition>; setConnectionPosition: Action<StoreModel, XYPosition>;
@@ -187,7 +180,7 @@ export const storeModel: StoreModel = {
connectionHandleType: 'source', connectionHandleType: 'source',
connectionPosition: { x: 0, y: 0 }, connectionPosition: { x: 0, y: 0 },
snapGrid: [16, 16], snapGrid: [15, 15],
snapToGrid: false, snapToGrid: false,
nodesDraggable: true, nodesDraggable: true,
@@ -395,12 +388,19 @@ export const storeModel: StoreModel = {
state.d3Initialised = true; state.d3Initialised = true;
}), }),
setMinMaxZoom: action((state, { minZoom, maxZoom }) => { setMinZoom: action((state, minZoom) => {
state.minZoom = minZoom; state.minZoom = minZoom;
state.maxZoom = maxZoom;
if (state.d3Zoom) { if (state.d3Zoom) {
state.d3Zoom.scaleExtent([minZoom, maxZoom]); state.d3Zoom.scaleExtent([minZoom, state.maxZoom]);
}
}),
setMaxZoom: action((state, maxZoom) => {
state.minZoom = maxZoom;
if (state.d3Zoom) {
state.d3Zoom.scaleExtent([state.minZoom, maxZoom]);
} }
}), }),
@@ -421,9 +421,13 @@ export const storeModel: StoreModel = {
state.connectionHandleType = connectionHandleType; state.connectionHandleType = connectionHandleType;
}), }),
setSnapGrid: action((state, { snapToGrid, snapGrid }) => { setSnapToGrid: action((state, snapToGrid) => {
state.snapToGrid = snapToGrid; state.snapToGrid = snapToGrid;
state.snapGrid = snapGrid; }),
setSnapGrid: action((state, snapGrid) => {
state.snapGrid[0] = snapGrid[0];
state.snapGrid[1] = snapGrid[1];
}), }),
setInteractive: action((state, isInteractive) => { setInteractive: action((state, isInteractive) => {
+3 -1
View File
@@ -32,6 +32,8 @@ export interface Box extends XYPosition {
y2: number; y2: number;
} }
export type SnapGrid = [number, number];
export interface Node { export interface Node {
id: ElementId; id: ElementId;
position: XYPosition; position: XYPosition;
@@ -214,7 +216,7 @@ export interface WrapNodeProps {
isHidden?: boolean; isHidden?: boolean;
isInitialized?: boolean; isInitialized?: boolean;
snapToGrid?: boolean; snapToGrid?: boolean;
snapGrid?: [number, number]; snapGrid?: SnapGrid;
isDragging?: boolean; isDragging?: boolean;
} }