Merge branch 'main' into feat/svelte

This commit is contained in:
moklick
2023-02-13 17:35:04 +01:00
74 changed files with 1085 additions and 382 deletions
+1
View File
@@ -25,6 +25,7 @@
},
"devDependencies": {
"@cypress/skip-test": "^2.6.1",
"@types/dagre": "^0.7.48",
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^3.0.1",
+6
View File
@@ -9,6 +9,7 @@ import CustomNode from '../examples/CustomNode';
import DefaultNodes from '../examples/DefaultNodes';
import DragHandle from '../examples/DragHandle';
import DragNDrop from '../examples/DragNDrop';
import EasyConnect from '../examples/EasyConnect';
import Edges from '../examples/Edges';
import EdgeRenderer from '../examples/EdgeRenderer';
import EdgeTypes from '../examples/EdgeTypes';
@@ -96,6 +97,11 @@ const routes: IRoute[] = [
path: '/dragndrop',
component: DragNDrop,
},
{
name: 'EasyConnect',
path: '/easy-connect',
component: EasyConnect,
},
{
name: 'Edges',
path: '/edges',
@@ -1,4 +1,4 @@
import React, { FC } from 'react';
import { FC } from 'react';
import ReactFlow, {
Node,
+8 -16
View File
@@ -1,4 +1,4 @@
import React, { MouseEvent } from 'react';
import { MouseEvent } from 'react';
import ReactFlow, {
MiniMap,
Background,
@@ -8,7 +8,7 @@ import ReactFlow, {
Node,
Edge,
useReactFlow,
NodeOrigin,
Panel,
} from 'reactflow';
const onNodeDrag = (_: MouseEvent, node: Node) => console.log('drag', node);
@@ -99,20 +99,12 @@ const BasicFlow = () => {
<MiniMap />
<Controls />
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
<button onClick={resetTransform} style={{ marginRight: 5 }}>
reset transform
</button>
<button onClick={updatePos} style={{ marginRight: 5 }}>
change pos
</button>
<button onClick={toggleClassnames} style={{ marginRight: 5 }}>
toggle classnames
</button>
<button onClick={logToObject} style={{ marginRight: 5 }}>
toObject
</button>
</div>
<Panel position="top-right">
<button onClick={resetTransform}>reset transform</button>
<button onClick={updatePos}>change pos</button>
<button onClick={toggleClassnames}>toggle classnames</button>
<button onClick={logToObject}>toObject</button>
</Panel>
</ReactFlow>
);
};
@@ -1,4 +1,4 @@
import React, { useCallback } from 'react';
import { useCallback } from 'react';
import ReactFlow, {
Node,
addEdge,
@@ -1,4 +1,4 @@
import React, { useState, useEffect, MouseEvent, ChangeEvent, useCallback } from 'react';
import { useState, useEffect, MouseEvent, ChangeEvent, useCallback } from 'react';
import ReactFlow, {
MiniMap,
Controls,
@@ -1,4 +1,12 @@
import ReactFlow, { useReactFlow, Node, Edge, ReactFlowProvider, Background, BackgroundVariant } from 'reactflow';
import ReactFlow, {
useReactFlow,
Node,
Edge,
ReactFlowProvider,
Background,
BackgroundVariant,
Panel,
} from 'reactflow';
const defaultNodes: Node[] = [
{
@@ -72,18 +80,12 @@ const DefaultNodes = () => {
<ReactFlow defaultNodes={defaultNodes} defaultEdges={defaultEdges} defaultEdgeOptions={defaultEdgeOptions} fitView>
<Background variant={BackgroundVariant.Lines} />
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
<button onClick={resetTransform} style={{ marginRight: 5 }}>
reset transform
</button>
<button onClick={updateNodePositions} style={{ marginRight: 5 }}>
change pos
</button>
<button onClick={updateEdgeColors} style={{ marginRight: 5 }}>
red edges
</button>
<Panel position="top-right">
<button onClick={resetTransform}>reset transform</button>
<button onClick={updateNodePositions}>change pos</button>
<button onClick={updateEdgeColors}>red edges</button>
<button onClick={logToObject}>toObject</button>
</div>
</Panel>
</ReactFlow>
);
};
@@ -1,4 +1,4 @@
import React, { MouseEvent } from 'react';
import { MouseEvent } from 'react';
import ReactFlow, { Node, Edge, useNodesState, useEdgesState } from 'reactflow';
import DragHandleNode from './DragHandleNode';
@@ -1,4 +1,5 @@
import React, { DragEvent } from 'react';
import { DragEvent } from 'react';
import styles from './dnd.module.css';
const onDragStart = (event: DragEvent, nodeType: string) => {
@@ -9,25 +10,19 @@ const onDragStart = (event: DragEvent, nodeType: string) => {
const Sidebar = () => {
return (
<aside className={styles.aside}>
<div className={styles.description}>
You can drag these nodes to the pane on the left.
</div>
<div
className='react-flow__node-input'
onDragStart={(event: DragEvent) => onDragStart(event, 'input')}
draggable
>
<div className={styles.description}>You can drag these nodes to the pane on the left.</div>
<div className="react-flow__node-input" onDragStart={(event: DragEvent) => onDragStart(event, 'input')} draggable>
Input Node
</div>
<div
className='react-flow__node-default'
className="react-flow__node-default"
onDragStart={(event: DragEvent) => onDragStart(event, 'default')}
draggable
>
Default Node
</div>
<div
className='react-flow__node-output'
className="react-flow__node-output"
onDragStart={(event: DragEvent) => onDragStart(event, 'output')}
draggable
>
@@ -1,4 +1,4 @@
import React, { useState, DragEvent } from 'react';
import { useState, DragEvent } from 'react';
import ReactFlow, {
ReactFlowProvider,
addEdge,
@@ -0,0 +1,19 @@
import { ConnectionLineComponentProps, getStraightPath } from 'reactflow';
function CustomConnectionLine({ fromX, fromY, toX, toY, connectionLineStyle }: ConnectionLineComponentProps) {
const [edgePath] = getStraightPath({
sourceX: fromX,
sourceY: fromY,
targetX: toX,
targetY: toY,
});
return (
<g>
<path style={connectionLineStyle} fill="none" d={edgePath} />
<circle cx={toX} cy={toY} fill="black" r={3} stroke="black" strokeWidth={1.5} />
</g>
);
}
export default CustomConnectionLine;
@@ -0,0 +1,39 @@
import { Handle, NodeProps, Position, ReactFlowState, useStore } from 'reactflow';
const connectionNodeIdSelector = (state: ReactFlowState) => state.connectionNodeId;
export default function CustomNode({ id, isConnectable }: NodeProps) {
const connectionNodeId = useStore(connectionNodeIdSelector);
const isTarget = connectionNodeId && connectionNodeId !== id;
const targetHandleStyle = { zIndex: isTarget ? 3 : 1 };
const label = isTarget ? 'Drop here' : 'Drag to connect';
return (
<div className="customNode">
<div
className="customNodeBody"
style={{
borderStyle: isTarget ? 'dashed' : 'solid',
backgroundColor: isTarget ? '#ffcce3' : '#ccd9f6',
}}
>
<Handle
className="targetHandle"
style={{ zIndex: 2 }}
position={Position.Right}
type="source"
isConnectable={isConnectable}
/>
<Handle
className="targetHandle"
style={targetHandleStyle}
position={Position.Left}
type="target"
isConnectable={isConnectable}
/>
{label}
</div>
</div>
);
}
@@ -0,0 +1,26 @@
import { useCallback } from 'react';
import { useStore, getStraightPath, EdgeProps } from 'reactflow';
import { getEdgeParams } from './utils.js';
function FloatingEdge({ id, source, target, markerEnd, style }: EdgeProps) {
const sourceNode = useStore(useCallback((store) => store.nodeInternals.get(source), [source]));
const targetNode = useStore(useCallback((store) => store.nodeInternals.get(target), [target]));
if (!sourceNode || !targetNode) {
return null;
}
const { sx, sy, tx, ty } = getEdgeParams(sourceNode, targetNode);
const [edgePath] = getStraightPath({
sourceX: sx,
sourceY: sy,
targetX: tx,
targetY: ty,
});
return <path id={id} className="react-flow__edge-path" d={edgePath} markerEnd={markerEnd} style={style} />;
}
export default FloatingEdge;
@@ -0,0 +1,85 @@
import { useCallback } from 'react';
import ReactFlow, { Node, Edge, addEdge, useNodesState, useEdgesState, MarkerType, OnConnect } from 'reactflow';
import CustomNode from './CustomNode';
import FloatingEdge from './FloatingEdge';
import CustomConnectionLine from './CustomConnectionLine';
import 'reactflow/dist/style.css';
import './style.css';
const initialNodes: Node[] = [
{
id: '1',
type: 'custom',
position: { x: 0, y: 0 },
data: {},
},
{
id: '2',
type: 'custom',
position: { x: 250, y: 320 },
data: {},
},
{
id: '3',
type: 'custom',
position: { x: 40, y: 300 },
data: {},
},
{
id: '4',
type: 'custom',
position: { x: 300, y: 0 },
data: {},
},
];
const initialEdges: Edge[] = [];
const connectionLineStyle = {
strokeWidth: 3,
stroke: 'black',
};
const nodeTypes = {
custom: CustomNode,
};
const edgeTypes = {
floating: FloatingEdge,
};
const defaultEdgeOptions = {
style: { strokeWidth: 3, stroke: 'black' },
type: 'floating',
markerEnd: {
type: MarkerType.ArrowClosed,
color: 'black',
},
};
const EasyConnectExample = () => {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect: OnConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)), [setEdges]);
return (
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
fitView
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
defaultEdgeOptions={defaultEdgeOptions}
connectionLineComponent={CustomConnectionLine}
connectionLineStyle={connectionLineStyle}
/>
);
};
export default EasyConnectExample;
@@ -0,0 +1,54 @@
.customNodeBody {
width: 150px;
height: 80px;
border: 3px solid black;
position: relative;
overflow: hidden;
border-radius: 10px;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
}
.customNode:before {
content: '';
position: absolute;
top: -10px;
left: 50%;
height: 20px;
width: 40px;
transform: translate(-50%, 0);
background: #d6d5e6;
z-index: 1000;
line-height: 1;
border-radius: 4px;
color: #fff;
font-size: 9px;
border: 2px solid #222138;
}
div.sourceHandle {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
border-radius: 0;
transform: none;
border: none;
opacity: 0;
}
div.targetHandle {
width: 100%;
height: 100%;
background: blue;
position: absolute;
top: 0;
left: 0;
border-radius: 0;
transform: none;
border: none;
opacity: 0;
}
@@ -0,0 +1,102 @@
import { Node, Position, MarkerType, XYPosition } from 'reactflow';
// this helper function returns the intersection point
// of the line between the center of the intersectionNode and the target node
function getNodeIntersection(intersectionNode: Node, targetNode: Node) {
// https://math.stackexchange.com/questions/1724792/an-algorithm-for-finding-the-intersection-point-between-a-center-of-vision-and-a
const {
width: intersectionNodeWidth,
height: intersectionNodeHeight,
positionAbsolute: intersectionNodePosition,
} = intersectionNode;
const targetPosition = targetNode.positionAbsolute!;
const w = intersectionNodeWidth! / 2;
const h = intersectionNodeHeight! / 2;
const x2 = intersectionNodePosition!.x + w;
const y2 = intersectionNodePosition!.y + h;
const x1 = targetPosition.x + w;
const y1 = targetPosition.y + h;
const xx1 = (x1 - x2) / (2 * w) - (y1 - y2) / (2 * h);
const yy1 = (x1 - x2) / (2 * w) + (y1 - y2) / (2 * h);
const a = 1 / (Math.abs(xx1) + Math.abs(yy1));
const xx3 = a * xx1;
const yy3 = a * yy1;
const x = w * (xx3 + yy3) + x2;
const y = h * (-xx3 + yy3) + y2;
return { x, y };
}
// returns the position (top,right,bottom or right) passed node compared to the intersection point
function getEdgePosition(node: Node, intersectionPoint: XYPosition) {
const n = { ...node.positionAbsolute, ...node };
const nx = Math.round(n.x!);
const ny = Math.round(n.y!);
const px = Math.round(intersectionPoint.x);
const py = Math.round(intersectionPoint.y);
if (px <= nx + 1) {
return Position.Left;
}
if (px >= nx + n.width! - 1) {
return Position.Right;
}
if (py <= ny + 1) {
return Position.Top;
}
if (py >= n.y! + n.height! - 1) {
return Position.Bottom;
}
return Position.Top;
}
// returns the parameters (sx, sy, tx, ty, sourcePos, targetPos) you need to create an edge
export function getEdgeParams(source: Node, target: Node) {
const sourceIntersectionPoint = getNodeIntersection(source, target);
const targetIntersectionPoint = getNodeIntersection(target, source);
const sourcePos = getEdgePosition(source, sourceIntersectionPoint);
const targetPos = getEdgePosition(target, targetIntersectionPoint);
return {
sx: sourceIntersectionPoint.x,
sy: sourceIntersectionPoint.y,
tx: targetIntersectionPoint.x,
ty: targetIntersectionPoint.y,
sourcePos,
targetPos,
};
}
export function createNodesAndEdges() {
const nodes = [];
const edges = [];
const center = { x: window.innerWidth / 2, y: window.innerHeight / 2 };
nodes.push({ id: 'target', data: { label: 'Target' }, position: center });
for (let i = 0; i < 8; i++) {
const degrees = i * (360 / 8);
const radians = degrees * (Math.PI / 180);
const x = 250 * Math.cos(radians) + center.x;
const y = 250 * Math.sin(radians) + center.y;
nodes.push({ id: `${i}`, data: { label: 'Source' }, position: { x, y } });
edges.push({
id: `edge-${i}`,
target: 'target',
source: `${i}`,
type: 'floating',
markerEnd: {
type: MarkerType.Arrow,
},
});
}
return { nodes, edges };
}
@@ -1,4 +1,4 @@
import React, { MouseEvent, useCallback } from 'react';
import { MouseEvent, useCallback } from 'react';
import ReactFlow, {
Controls,
Background,
@@ -1,7 +1,4 @@
/**
* Example for checking the different edge types and source and target positions
*/
import React, { useCallback } from 'react';
import { useCallback } from 'react';
import ReactFlow, {
Background,
@@ -1,4 +1,4 @@
import React, { MouseEvent, useCallback } from 'react';
import { MouseEvent, useCallback } from 'react';
import ReactFlow, {
Controls,
Background,
@@ -1,4 +1,4 @@
import React, { MouseEvent, CSSProperties, useCallback } from 'react';
import { MouseEvent, CSSProperties, useCallback } from 'react';
import ReactFlow, {
Background,
@@ -1,4 +1,4 @@
import React, { useCallback } from 'react';
import { useCallback } from 'react';
import ReactFlow, {
Background,
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback } from 'react';
import { useState, useEffect, useCallback } from 'react';
import ReactFlow, { addEdge, Connection, Edge, Node, useNodesState, useEdgesState, MiniMap, Controls } from 'reactflow';
@@ -1,4 +1,4 @@
import React, { useState, MouseEvent as ReactMouseEvent, WheelEvent } from 'react';
import { useState, MouseEvent as ReactMouseEvent, WheelEvent } from 'react';
import ReactFlow, {
addEdge,
Node,
@@ -1,4 +1,5 @@
import React, { useCallback } from 'react';
import { useCallback } from 'react';
import dagre from 'dagre';
import ReactFlow, {
Controls,
ReactFlowProvider,
@@ -10,10 +11,10 @@ import ReactFlow, {
useEdgesState,
MarkerType,
EdgeMarker,
Panel,
useReactFlow,
} from 'reactflow';
import dagre from 'dagre';
import initialItems from './initial-elements';
import styles from './layouting.module.css';
@@ -29,6 +30,7 @@ const nodeExtent: CoordinateExtent = [
const LayoutFlow = () => {
const [nodes, setNodes, onNodesChange] = useNodesState(initialItems.nodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialItems.edges);
const { fitView } = useReactFlow();
const onConnect = useCallback(
(connection: Connection) => {
@@ -85,31 +87,31 @@ const LayoutFlow = () => {
return (
<div className={styles.layoutflow}>
<ReactFlowProvider>
<ReactFlow
nodes={nodes}
edges={edges}
onConnect={onConnect}
nodeExtent={nodeExtent}
onInit={() => onLayout('TB')}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
>
<Controls />
</ReactFlow>
<div className={styles.controls}>
<button onClick={() => onLayout('TB')} style={{ marginRight: 10 }}>
vertical layout
</button>
<button onClick={() => onLayout('LR')} style={{ marginRight: 10 }}>
horizontal layout
</button>
<button onClick={() => unselect()}>unselect nodes</button>
<button onClick={() => changeMarker()}>change marker</button>
</div>
</ReactFlowProvider>
<ReactFlow
nodes={nodes}
edges={edges}
onConnect={onConnect}
nodeExtent={nodeExtent}
onInit={() => onLayout('TB')}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
>
<Controls />
</ReactFlow>
<Panel position="top-right">
<button onClick={() => onLayout('TB')}>vertical layout</button>
<button onClick={() => onLayout('LR')}>horizontal layout</button>
<button onClick={() => unselect()}>unselect nodes</button>
<button onClick={() => changeMarker()}>change marker</button>
<button onClick={() => fitView()}>fitView</button>
<button onClick={() => fitView({ nodes: nodes.slice(0, 2) })}>fitView partially</button>
</Panel>
</div>
);
};
export default LayoutFlow;
export default () => (
<ReactFlowProvider>
<LayoutFlow />
</ReactFlowProvider>
);
@@ -2,10 +2,3 @@
flex-grow: 1;
position: relative;
}
.controls {
position: absolute;
right: 10px;
top: 10px;
z-index: 10;
}
@@ -1,4 +1,4 @@
import React, { FC } from 'react';
import { FC } from 'react';
import ReactFlow, {
Background,
@@ -1,4 +1,4 @@
import React, { useState, MouseEvent, useCallback } from 'react';
import { useState, MouseEvent, useCallback } from 'react';
import ReactFlow, {
Controls,
MiniMap,
@@ -1,5 +1,4 @@
import React, { CSSProperties, useCallback } from 'react';
import { CSSProperties, useCallback } from 'react';
import ReactFlow, { addEdge, Node, Position, Connection, Edge, useNodesState, useEdgesState } from 'reactflow';
const initialNodes: Node[] = [
@@ -1,4 +1,4 @@
import React, { useState, CSSProperties, FC, useCallback } from 'react';
import { useState, CSSProperties, FC, useCallback } from 'react';
import ReactFlow, {
addEdge,
Node,
@@ -1,4 +1,4 @@
import React, { MouseEvent as ReactMouseEvent, CSSProperties, useCallback } from 'react';
import { MouseEvent as ReactMouseEvent, CSSProperties, useCallback } from 'react';
import ReactFlow, {
addEdge,
Node,
@@ -1,4 +1,4 @@
import React, { MouseEvent, useCallback } from 'react';
import { MouseEvent, useCallback } from 'react';
import ReactFlow, {
Controls,
ReactFlowProvider,
@@ -1,5 +1,6 @@
import React, { useCallback } from 'react';
import { useCallback } from 'react';
import ReactFlow, { ReactFlowProvider, Node, addEdge, Connection, Edge, useNodesState, useEdgesState } from 'reactflow';
import Controls from './Controls';
const initialNodes: Node[] = [
@@ -1,4 +1,4 @@
import React, { useState, CSSProperties, useCallback } from 'react';
import { useState, CSSProperties, useCallback } from 'react';
import ReactFlow, {
ReactFlowInstance,
Edge,
@@ -1,4 +1,4 @@
import React, { useState, MouseEvent, useCallback } from 'react';
import { useState, MouseEvent, useCallback } from 'react';
import ReactFlow, {
addEdge,
Node,
@@ -12,7 +12,6 @@ import ReactFlow, {
MiniMap,
Background,
Panel,
NodeOrigin,
} from 'reactflow';
import DebugNode from './DebugNode';
@@ -1,4 +1,4 @@
import React, { useCallback } from 'react';
import { useCallback } from 'react';
import ReactFlow, { Node, Edge, useNodesState, useEdgesState, Position, Connection, addEdge } from 'reactflow';
import styles from './touch-device.module.css';
@@ -182,12 +182,13 @@ const getId = () => `${id++}`;
const UpdateNodeInternalsFlow = () => {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = (params: Edge | Connection) => setEdges((els) => addEdge(params, els));
const { project } = useReactFlow();
const onEdgeUpdate = (oldEdge: Edge, newConnection: Connection) =>
setEdges((els) => updateEdge(oldEdge, newConnection, els));
const onConnect = useCallback((params: Edge | Connection) => setEdges((els) => addEdge(params, els)), [setEdges]);
const onEdgeUpdate = useCallback(
(oldEdge: Edge, newConnection: Connection) => setEdges((els) => updateEdge(oldEdge, newConnection, els)),
[]
);
const onPaneClick = useCallback(
(evt: MouseEvent) =>
@@ -1,4 +1,4 @@
import React, { useState, useCallback } from 'react';
import { useState, useCallback, MouseEvent as ReactMouseEvent } from 'react';
import ReactFlow, {
Controls,
updateEdge,
@@ -60,9 +60,9 @@ const initialNodes: Node[] = [
const initialEdges = [{ id: 'e1-2', source: '1', target: '2', label: 'This is a draggable edge' }];
const onInit = (reactFlowInstance: ReactFlowInstance) => reactFlowInstance.fitView();
const onEdgeUpdateStart = (_: React.MouseEvent, edge: Edge, handleType: HandleType) =>
const onEdgeUpdateStart = (_: ReactMouseEvent, edge: Edge, handleType: HandleType) =>
console.log(`start update ${handleType} handle`, edge);
const onEdgeUpdateEnd = (_: MouseEvent, edge: Edge, handleType: HandleType) =>
const onEdgeUpdateEnd = (_: MouseEvent | TouchEvent, edge: Edge, handleType: HandleType) =>
console.log(`end update ${handleType} handle`, edge);
const UpdatableEdge = () => {
@@ -91,8 +91,8 @@ const UpdatableEdge = () => {
snapToGrid={true}
onEdgeUpdate={onEdgeUpdate}
onConnect={onConnect}
// onEdgeUpdateStart={onEdgeUpdateStart}
// onEdgeUpdateEnd={onEdgeUpdateEnd}
onEdgeUpdateStart={onEdgeUpdateStart}
onEdgeUpdateEnd={onEdgeUpdateEnd}
>
<Controls />
</ReactFlow>
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import ReactFlow, { Node, Edge, useNodesState, useEdgesState } from 'reactflow';
import styles from './updatenode.module.css';
@@ -1,4 +1,4 @@
import React, { useCallback, MouseEvent, useEffect } from 'react';
import { useCallback, MouseEvent, useEffect } from 'react';
import ReactFlow, {
Background,
MiniMap,
@@ -10,6 +10,7 @@ import ReactFlow, {
Edge,
useNodesState,
useEdgesState,
Panel,
} from 'reactflow';
const initialNodes: Node[] = [
@@ -65,7 +66,7 @@ const UseZoomPanHelperFlow = () => {
addEdges,
getNodes,
getEdges,
deleteElements
deleteElements,
} = useReactFlow();
const onPaneClick = useCallback(
@@ -114,14 +115,14 @@ const UseZoomPanHelperFlow = () => {
}, [getNodes, getEdges]);
const deleteSelectedElements = useCallback(() => {
const selectedNodes = nodes.filter(node => node.selected);
const selectedEdges = edges.filter(edge => edge.selected);
const selectedNodes = nodes.filter((node) => node.selected);
const selectedEdges = edges.filter((edge) => edge.selected);
deleteElements({ nodes: selectedNodes, edges: selectedEdges });
}, [deleteElements, nodes, edges])
}, [deleteElements, nodes, edges]);
const deleteSomeElements = useCallback(() => {
deleteElements({ nodes: [{ id: '2' }], edges: [{ id: 'e1-3' }] })
}, [])
deleteElements({ nodes: [{ id: '2' }], edges: [{ id: 'e1-3' }] });
}, []);
useEffect(() => {
addEdges({ id: 'e3-4', source: '3', target: '4' });
@@ -142,7 +143,7 @@ const UseZoomPanHelperFlow = () => {
fitViewOptions={{ duration: 1200, padding: 0.2 }}
maxZoom={Infinity}
>
<div style={{ position: 'absolute', left: 0, top: 0, zIndex: 100 }}>
<Panel position="top-right">
<button onClick={() => zoomIn({ duration: 1200 })}>zoomIn</button>
<button onClick={() => zoomOut({ duration: 0 })}>zoomOut</button>
<button onClick={() => fitView({ duration: 1200, padding: 0.3 })}>fitView</button>
@@ -151,7 +152,7 @@ const UseZoomPanHelperFlow = () => {
<button onClick={logNodes}>useNodes</button>
<button onClick={deleteSelectedElements}>deleteSelectedElements</button>
<button onClick={deleteSomeElements}>deleteSomeElements</button>
</div>
</Panel>
<Background />
<MiniMap />
</ReactFlow>
@@ -1,16 +1,17 @@
import React, { FC, useCallback, useState } from 'react';
import { FC, useCallback, useState } from 'react';
import ReactFlow, {
addEdge,
Handle,
Connection,
Position,
Node,
Edge,
NodeProps,
NodeTypes,
useNodesState,
useEdgesState,
OnConnectStartParams,
OnConnectStart,
OnConnectEnd,
OnConnect,
} from 'reactflow';
import styles from './validation.module.css';
@@ -49,24 +50,24 @@ const ValidationFlow = () => {
const [nodes, , onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
const onConnectStart = useCallback(
(event: React.MouseEvent, params: OnConnectStartParams) => {
const onConnectStart: OnConnectStart = useCallback(
(event, params) => {
console.log('on connect start', params, event, value);
setValue(1);
},
[value]
);
const onConnect = useCallback(
(params: Connection | Edge) => {
const onConnect: OnConnect = useCallback(
(params) => {
console.log('on connect', params);
setEdges((eds) => addEdge(params, eds));
},
[setEdges]
);
const onConnectEnd = useCallback(
(event: MouseEvent) => {
const onConnectEnd: OnConnectEnd = useCallback(
(event) => {
console.log('on connect end', event, value);
setValue(0);
},
@@ -24,10 +24,18 @@
background: #fff;
}
.validationflow :global .react-flow__handle-connecting {
.validationflow :global .connecting {
background: #ff6060;
}
.validationflow :global .react-flow__handle-valid {
.validationflow :global .valid {
background: #55dd99;
}
.validationflow :global .valid .react-flow__connection-path {
stroke: #55dd99;
}
.validationflow :global .invalid .react-flow__connection-path {
stroke: #ff6060;
}
+37
View File
@@ -1,5 +1,42 @@
# @reactflow/background
## 11.1.8
### Patch Changes
- Updated dependencies [[`72216ff6`](https://github.com/wbkd/react-flow/commit/72216ff62014acd2d73999053c72bd7aeed351f6), [`959b1114`](https://github.com/wbkd/react-flow/commit/959b111448bba4686040473e46988be9e7befbe6), [`0d259b02`](https://github.com/wbkd/react-flow/commit/0d259b028558aab650546f3371a85f3bce45252f), [`f3de9335`](https://github.com/wbkd/react-flow/commit/f3de9335af6cd96cd77dc77f24a944eef85384e5), [`23424ea6`](https://github.com/wbkd/react-flow/commit/23424ea6750f092210f83df17a00c89adb910d96), [`021f5a92`](https://github.com/wbkd/react-flow/commit/021f5a9210f47a968e50446cd2f9dae1f97880a4)]:
- @reactflow/core@11.5.5
## 11.1.7
### Patch Changes
- Updated dependencies [[`383a074a`](https://github.com/wbkd/react-flow/commit/383a074aeae6dbec8437fa08c7c8d8240838a84e)]:
- @reactflow/core@11.5.4
## 11.1.6
### Patch Changes
- Updated dependencies [[`be8097ac`](https://github.com/wbkd/react-flow/commit/be8097acadca3054c3b236ce4296fc516010ef8c), [`1527795d`](https://github.com/wbkd/react-flow/commit/1527795d18c3af38c8ec7059436ea0fbf6c27bbd), [`3b6348a8`](https://github.com/wbkd/react-flow/commit/3b6348a8d1573afb39576327318bc172e33393c2)]:
- @reactflow/core@11.5.3
## 11.1.5
### Patch Changes
- [#2792](https://github.com/wbkd/react-flow/pull/2792) [`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a) - Accept React 17 types as dev dependency
- Updated dependencies [[`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a)]:
- @reactflow/core@11.5.2
## 11.1.4
### Patch Changes
- Updated dependencies [[`71153534`](https://github.com/wbkd/react-flow/commit/7115353418ebc7f7c81ab0e861200972bbf7dbd5)]:
- @reactflow/core@11.5.1
## 11.1.3
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@reactflow/background",
"version": "11.1.3",
"version": "11.1.8",
"description": "Background component with different variants for React Flow",
"keywords": [
"react",
@@ -46,7 +46,7 @@
"@reactflow/rollup-config": "workspace:*",
"@reactflow/tsconfig": "workspace:*",
"@types/node": "^18.7.16",
"@types/react": "^18.0.19",
"@types/react": ">=17",
"react": "^18.2.0",
"typescript": "^4.9.4"
},
+37
View File
@@ -1,5 +1,42 @@
# @reactflow/controls
## 11.1.8
### Patch Changes
- Updated dependencies [[`72216ff6`](https://github.com/wbkd/react-flow/commit/72216ff62014acd2d73999053c72bd7aeed351f6), [`959b1114`](https://github.com/wbkd/react-flow/commit/959b111448bba4686040473e46988be9e7befbe6), [`0d259b02`](https://github.com/wbkd/react-flow/commit/0d259b028558aab650546f3371a85f3bce45252f), [`f3de9335`](https://github.com/wbkd/react-flow/commit/f3de9335af6cd96cd77dc77f24a944eef85384e5), [`23424ea6`](https://github.com/wbkd/react-flow/commit/23424ea6750f092210f83df17a00c89adb910d96), [`021f5a92`](https://github.com/wbkd/react-flow/commit/021f5a9210f47a968e50446cd2f9dae1f97880a4)]:
- @reactflow/core@11.5.5
## 11.1.7
### Patch Changes
- Updated dependencies [[`383a074a`](https://github.com/wbkd/react-flow/commit/383a074aeae6dbec8437fa08c7c8d8240838a84e)]:
- @reactflow/core@11.5.4
## 11.1.6
### Patch Changes
- Updated dependencies [[`be8097ac`](https://github.com/wbkd/react-flow/commit/be8097acadca3054c3b236ce4296fc516010ef8c), [`1527795d`](https://github.com/wbkd/react-flow/commit/1527795d18c3af38c8ec7059436ea0fbf6c27bbd), [`3b6348a8`](https://github.com/wbkd/react-flow/commit/3b6348a8d1573afb39576327318bc172e33393c2)]:
- @reactflow/core@11.5.3
## 11.1.5
### Patch Changes
- [#2792](https://github.com/wbkd/react-flow/pull/2792) [`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a) - Accept React 17 types as dev dependency
- Updated dependencies [[`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a)]:
- @reactflow/core@11.5.2
## 11.1.4
### Patch Changes
- Updated dependencies [[`71153534`](https://github.com/wbkd/react-flow/commit/7115353418ebc7f7c81ab0e861200972bbf7dbd5)]:
- @reactflow/core@11.5.1
## 11.1.3
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@reactflow/controls",
"version": "11.1.3",
"version": "11.1.8",
"description": "Component to control the viewport of a React Flow instance",
"keywords": [
"react",
@@ -50,7 +50,7 @@
"@reactflow/rollup-config": "workspace:*",
"@reactflow/tsconfig": "workspace:*",
"@types/node": "^18.7.16",
"@types/react": "^18.0.19",
"@types/react": ">=17",
"typescript": "^4.9.4"
},
"rollup": {
+45 -5
View File
@@ -1,5 +1,44 @@
# @reactflow/core
## 11.5.5
### Patch Changes
- [#2834](https://github.com/wbkd/react-flow/pull/2834) [`23424ea6`](https://github.com/wbkd/react-flow/commit/23424ea6750f092210f83df17a00c89adb910d96) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - Add `nodes` to fit view options to allow fitting view only around specified set of nodes
- [#2836](https://github.com/wbkd/react-flow/pull/2836) [`959b1114`](https://github.com/wbkd/react-flow/commit/959b111448bba4686040473e46988be9e7befbe6) - Fix: connections for handles with bigger handles than connection radius
- [#2819](https://github.com/wbkd/react-flow/pull/2819) [`0d259b02`](https://github.com/wbkd/react-flow/commit/0d259b028558aab650546f3371a85f3bce45252f) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - Avoid triggering edge update if not using left mouse button
- [#2832](https://github.com/wbkd/react-flow/pull/2832) [`f3de9335`](https://github.com/wbkd/react-flow/commit/f3de9335af6cd96cd77dc77f24a944eef85384e5) - fitView: return type boolean
- [#2838](https://github.com/wbkd/react-flow/pull/2838) [`021f5a92`](https://github.com/wbkd/react-flow/commit/021f5a9210f47a968e50446cd2f9dae1f97880a4) - refactor: use key press handle modifier keys + input
- [#2839](https://github.com/wbkd/react-flow/pull/2839) [`72216ff6`](https://github.com/wbkd/react-flow/commit/72216ff62014acd2d73999053c72bd7aeed351f6) - fix PropsWithChildren: pass default generic for v17 types
## 11.5.4
### Patch Changes
- [`383a074a`](https://github.com/wbkd/react-flow/commit/383a074aeae6dbec8437fa08c7c8d8240838a84e) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - Check if prevClosestHandle exists in onPointerUp. Fixes connections getting stuck on last handle and connecting, even when out of connectionRadius
## 11.5.3
This release fixes some issues with the newly introduced connection radius feature. We are now not only checking the radius but the handle itself too (like in the old version). That means that you can connect to a handle that is bigger than the connection radius. We are also not snapping connections anymore when they are not valid and pass a status class to the connection line that says if the current connection is valid or not. More over we fixed a connection issue with iOS.
### Patch Changes
- [#2800](https://github.com/wbkd/react-flow/pull/2800) [`be8097ac`](https://github.com/wbkd/react-flow/commit/be8097acadca3054c3b236ce4296fc516010ef8c) - When node is not draggable, you can't move it with a selection either
- [#2803](https://github.com/wbkd/react-flow/pull/2803) [`1527795d`](https://github.com/wbkd/react-flow/commit/1527795d18c3af38c8ec7059436ea0fbf6c27bbd) - connection: add status class (valid or invalid) while in connection radius
- [#2801](https://github.com/wbkd/react-flow/pull/2801) [`3b6348a8`](https://github.com/wbkd/react-flow/commit/3b6348a8d1573afb39576327318bc172e33393c2) - fix(ios): connection error + dont snap invalid connection lines, check handle and connection radius
## 11.5.2
### Patch Changes
- [#2792](https://github.com/wbkd/react-flow/pull/2792) [`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a) - Accept React 17 types as dev dependency
## 11.5.1
### Patch Changes
- [#2783](https://github.com/wbkd/react-flow/pull/2783) [`71153534`](https://github.com/wbkd/react-flow/commit/7115353418ebc7f7c81ab0e861200972bbf7dbd5) - connections: check handle below mouse before using connection radius
## 11.5.0
Lot's of improvements are coming with this release!
@@ -8,23 +47,24 @@ Lot's of improvements are coming with this release!
- **Auto pan**: When you drag a node, a selection or the connection line to the border of the pane, it will pan into that direction. That makes it easier to connect far away nodes for example. If you don't like it you can set `autoPnaOnNodeDrag` and `autoPanOnConnect` to false.
- **Touch devices**: It's finally possibleto connect nodes with the connection line on touch devices. In combination with the new auto pan and connection radius the overall UX is way better.
- **Errors**: We added an `onError` prop to get notified when an error like "couldn't find source handle" happens. This is useful if you want to log errors for example.
- **Node type**: We added a second param to the generic `Node` type. You can not only pass `NodeData` but also the type as a second param:
- **Node type**: We added a second param to the generic `Node` type. You can not only pass `NodeData` but also the type as a second param:
```ts
type MyCustomNode = Node<MyCustomNodeData, 'custom-node-type'>
type MyCustomNode = Node<MyCustomNodeData, 'custom-node-type'>;
```
This makes it easier to work with different custom nodes and data types.
### Minor Changes
- [#2754](https://github.com/wbkd/react-flow/pull/2754) [`e96309b6`](https://github.com/wbkd/react-flow/commit/e96309b6a57b1071faeebf7b0547fef7fd418694) - Add auto pan for connecting and node dragging and `connectionRadius`
- [#2754](https://github.com/wbkd/react-flow/pull/2754) [`e96309b6`](https://github.com/wbkd/react-flow/commit/e96309b6a57b1071faeebf7b0547fef7fd418694) - Add auto pan for connecting and node dragging and `connectionRadius`
- [#2773](https://github.com/wbkd/react-flow/pull/2773) - Add `onError` prop to get notified when an error happens
### Patch Changes
- [#2763](https://github.com/wbkd/react-flow/pull/2763) [`85003b01`](https://github.com/wbkd/react-flow/commit/85003b01add71ea852bd5b0d2f1e7496050a6b52) - Connecting nodes: Enable connections on touch devices
- [#2763](https://github.com/wbkd/react-flow/pull/2763) [`85003b01`](https://github.com/wbkd/react-flow/commit/85003b01add71ea852bd5b0d2f1e7496050a6b52) - Connecting nodes: Enable connections on touch devices
- [#2620](https://github.com/wbkd/react-flow/pull/2620) - Thanks [RichSchulz](https://github.com/RichSchulz)! - Types: improve typing for node type
## 11.4.2
### Patch Changes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@reactflow/core",
"version": "11.5.0",
"version": "11.5.5",
"description": "Core components and util functions of React Flow.",
"keywords": [
"react",
@@ -57,8 +57,8 @@
"@reactflow/rollup-config": "workspace:*",
"@reactflow/tsconfig": "workspace:*",
"@types/node": "^18.7.16",
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@types/react": ">=17",
"@types/react-dom": ">=17",
"react": "^18.2.0",
"typescript": "^4.9.4"
},
@@ -1,12 +1,19 @@
import { CSSProperties, useCallback } from 'react';
import { shallow } from 'zustand/shallow';
import cc from 'classcat';
import { useStore } from '../../hooks/useStore';
import { getBezierPath } from '../Edges/BezierEdge';
import { getSmoothStepPath } from '../Edges/SmoothStepEdge';
import { getSimpleBezierPath } from '../Edges/SimpleBezierEdge';
import { internalsSymbol } from '../../utils';
import type { ConnectionLineComponent, HandleType, ReactFlowState, ReactFlowStore } from '../../types';
import type {
ConnectionLineComponent,
ConnectionStatus,
HandleType,
ReactFlowState,
ReactFlowStore,
} from '../../types';
import { Position, ConnectionLineType, ConnectionMode } from '../../types';
type ConnectionLineProps = {
@@ -15,6 +22,7 @@ type ConnectionLineProps = {
type: ConnectionLineType;
style?: CSSProperties;
CustomComponent?: ConnectionLineComponent;
connectionStatus: ConnectionStatus | null;
};
const oppositePosition = {
@@ -30,6 +38,7 @@ const ConnectionLine = ({
style,
type = ConnectionLineType.Bezier,
CustomComponent,
connectionStatus,
}: ConnectionLineProps) => {
const { fromNode, handleId, toX, toY, connectionMode } = useStore(
useCallback(
@@ -80,6 +89,7 @@ const ConnectionLine = ({
toY={toY}
fromPosition={fromPosition}
toPosition={toPosition}
connectionStatus={connectionStatus}
/>
);
}
@@ -127,12 +137,13 @@ const selector = (s: ReactFlowState) => ({
nodeId: s.connectionNodeId,
handleType: s.connectionHandleType,
nodesConnectable: s.nodesConnectable,
connectionStatus: s.connectionStatus,
width: s.width,
height: s.height,
});
function ConnectionLineWrapper({ containerStyle, style, type, component }: ConnectionLineWrapperProps) {
const { nodeId, handleType, nodesConnectable, width, height } = useStore(selector, shallow);
const { nodeId, handleType, nodesConnectable, width, height, connectionStatus } = useStore(selector, shallow);
const isValid = !!(nodeId && handleType && width && nodesConnectable);
if (!isValid) {
@@ -146,8 +157,15 @@ function ConnectionLineWrapper({ containerStyle, style, type, component }: Conne
height={height}
className="react-flow__edges react-flow__connectionline react-flow__container"
>
<g className="react-flow__connection">
<ConnectionLine nodeId={nodeId} handleType={handleType} style={style} type={type} CustomComponent={component} />
<g className={cc(['react-flow__connection', connectionStatus])}>
<ConnectionLine
nodeId={nodeId}
handleType={handleType}
style={style}
type={type}
CustomComponent={component}
connectionStatus={connectionStatus}
/>
</g>
</svg>
);
@@ -89,6 +89,11 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
const onEdgeMouseLeave = getMouseHandler(id, store.getState, onMouseLeave);
const handleEdgeUpdater = (event: React.MouseEvent<SVGGElement, MouseEvent>, isSourceHandle: boolean) => {
// avoid triggering edge updater if mouse btn is not left
if (event.button !== 0) {
return;
}
const nodeId = isSourceHandle ? target : source;
const handleId = (isSourceHandle ? targetHandleId : sourceHandleId) || null;
const handleType = isSourceHandle ? 'target' : 'source';
+43 -39
View File
@@ -2,11 +2,12 @@ import type { MouseEvent as ReactMouseEvent, TouchEvent as ReactTouchEvent } fro
import { StoreApi } from 'zustand';
import { getHostForElement, calcAutoPan, getEventPosition } from '../../utils';
import type { OnConnect, HandleType, ReactFlowState } from '../../types';
import type { OnConnect, HandleType, ReactFlowState, Connection } from '../../types';
import { pointToRendererPoint, rendererPointToPoint } from '../../utils/graph';
import {
ConnectionHandle,
getClosestHandle,
getConnectionStatus,
getHandleLookup,
getHandleType,
isValidHandle,
@@ -45,7 +46,6 @@ export function handlePointerDown({
autoPanOnConnect,
connectionRadius,
onConnectStart,
onConnectEnd,
panBy,
getNodes,
cancelConnection,
@@ -65,6 +65,9 @@ export function handlePointerDown({
let prevActiveHandle: Element;
let connectionPosition = getEventPosition(event, containerBounds);
let autoPanStarted = false;
let connection: Connection | null = null;
let isValid = false;
let handleDomNode: Element | null = null;
const handleLookup = getHandleLookup({
nodes: getNodes(),
@@ -89,6 +92,7 @@ export function handlePointerDown({
connectionNodeId: nodeId,
connectionHandleId: handleId,
connectionHandleType: handleType,
connectionStatus: null,
});
onConnectStart?.(event, { nodeId, handleId, handleType });
@@ -108,23 +112,8 @@ export function handlePointerDown({
autoPanStarted = true;
}
setState({
connectionPosition: prevClosestHandle
? rendererPointToPoint(
{
x: prevClosestHandle.x,
y: prevClosestHandle.y,
},
transform
)
: connectionPosition,
});
if (!prevClosestHandle) {
return resetRecentHandle(prevActiveHandle);
}
const { connection, handleDomNode, isValid } = isValidHandle(
const result = isValidHandle(
event,
prevClosestHandle,
connectionMode,
nodeId,
@@ -134,43 +123,58 @@ export function handlePointerDown({
doc
);
handleDomNode = result.handleDomNode;
connection = result.connection;
isValid = result.isValid;
setState({
connectionPosition:
prevClosestHandle && isValid
? rendererPointToPoint(
{
x: prevClosestHandle.x,
y: prevClosestHandle.y,
},
transform
)
: connectionPosition,
connectionStatus: getConnectionStatus(!!prevClosestHandle, isValid),
});
if (!prevClosestHandle && !isValid && !handleDomNode) {
return resetRecentHandle(prevActiveHandle);
}
if (connection.source !== connection.target && handleDomNode) {
resetRecentHandle(prevActiveHandle);
prevActiveHandle = handleDomNode;
handleDomNode.classList.add('react-flow__handle-connecting');
// @todo: remove the old class names "react-flow__handle-" in the next major version
handleDomNode.classList.add('connecting', 'react-flow__handle-connecting');
handleDomNode.classList.toggle('valid', isValid);
handleDomNode.classList.toggle('react-flow__handle-valid', isValid);
}
}
function onPointerUp(event: MouseEvent | TouchEvent) {
cancelAnimationFrame(autoPanId);
autoPanStarted = false;
if (prevClosestHandle) {
const { connection, isValid } = isValidHandle(
prevClosestHandle,
connectionMode,
nodeId,
handleId,
isTarget ? 'target' : 'source',
isValidConnection,
doc
);
if (isValid) {
onConnect?.(connection);
}
if ((prevClosestHandle || handleDomNode) && connection && isValid) {
onConnect?.(connection);
}
onConnectEnd?.(event);
// it's important to get a fresh reference from the store here
// in order to get the latest state of onConnectEnd
getState().onConnectEnd?.(event);
if (edgeUpdaterType) {
onEdgeUpdateEnd?.(event);
}
resetRecentHandle(prevActiveHandle);
cancelConnection();
cancelAnimationFrame(autoPanId);
autoPanStarted = false;
isValid = false;
connection = null;
handleDomNode = null;
doc.removeEventListener('mousemove', onPointerMove as EventListener);
doc.removeEventListener('mouseup', onPointerUp as EventListener);
@@ -102,6 +102,7 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
const doc = getHostForElement(event.target as HTMLElement);
const { connection, isValid } = isValidHandle(
event,
{
nodeId,
id: handleId,
+36 -17
View File
@@ -1,5 +1,7 @@
import { ConnectionMode } from '../../types';
import { internalsSymbol } from '../../utils';
import { MouseEvent as ReactMouseEvent, TouchEvent as ReactTouchEvent } from 'react';
import { ConnectionMode, ConnectionStatus } from '../../types';
import { getEventPosition, internalsSymbol } from '../../utils';
import type { Connection, HandleType, XYPosition, Node, NodeHandleBounds } from '../../types';
export type ConnectionHandle = {
@@ -59,9 +61,12 @@ type Result = {
connection: Connection;
};
const nullConnection: Connection = { source: null, target: null, sourceHandle: null, targetHandle: null };
// checks if and returns connection in fom of an object { source: 123, target: 312 }
export function isValidHandle(
handle: Pick<ConnectionHandle, 'nodeId' | 'id' | 'type'>,
event: MouseEvent | TouchEvent | ReactMouseEvent | ReactTouchEvent,
handle: Pick<ConnectionHandle, 'nodeId' | 'id' | 'type'> | null,
connectionMode: ConnectionMode,
fromNodeId: string,
fromHandleId: string | null,
@@ -73,23 +78,26 @@ export function isValidHandle(
const handleDomNode = doc.querySelector(
`.react-flow__handle[data-id="${handle?.nodeId}-${handle?.id}-${handle?.type}"]`
);
const { x, y } = getEventPosition(event);
const handleBelow = doc.elementFromPoint(x, y);
const handleToCheck = handleBelow?.classList.contains('react-flow__handle') ? handleBelow : handleDomNode;
const result: Result = {
handleDomNode,
handleDomNode: handleToCheck,
isValid: false,
connection: { source: null, target: null, sourceHandle: null, targetHandle: null },
connection: nullConnection,
};
if (handleDomNode) {
const handleIsTarget = handle.type === 'target';
const handleIsSource = handle.type === 'source';
const handleNodeId = handleDomNode.getAttribute('data-nodeid');
const handleId = handleDomNode.getAttribute('data-handleid');
if (handleToCheck) {
const handleType = getHandleType(undefined, handleToCheck);
const handleNodeId = handleToCheck.getAttribute('data-nodeid');
const handleId = handleToCheck.getAttribute('data-handleid');
const connection: Connection = {
source: isTarget ? handle.nodeId : fromNodeId,
sourceHandle: isTarget ? handle.id : fromHandleId,
target: isTarget ? fromNodeId : handle.nodeId,
targetHandle: isTarget ? fromHandleId : handle.id,
source: isTarget ? handleNodeId : fromNodeId,
sourceHandle: isTarget ? handleId : fromHandleId,
target: isTarget ? fromNodeId : handleNodeId,
targetHandle: isTarget ? fromHandleId : handleId,
};
result.connection = connection;
@@ -97,7 +105,7 @@ export function isValidHandle(
// in strict mode we don't allow target to target or source to source connections
const isValid =
connectionMode === ConnectionMode.Strict
? (isTarget && handleIsSource) || (!isTarget && handleIsTarget)
? (isTarget && handleType === 'source') || (!isTarget && handleType === 'target')
: handleNodeId !== fromNodeId || handleId !== fromHandleId;
if (isValid) {
@@ -149,6 +157,17 @@ export function getHandleType(
}
export function resetRecentHandle(handleDomNode: Element): void {
handleDomNode?.classList.remove('react-flow__handle-valid');
handleDomNode?.classList.remove('react-flow__handle-connecting');
handleDomNode?.classList.remove('valid', 'connecting', 'react-flow__handle-valid', 'react-flow__handle-connecting');
}
export function getConnectionStatus(isInsideConnectionRadius: boolean, isHandleValid: boolean) {
let connectionStatus = null;
if (isHandleValid) {
connectionStatus = 'valid';
} else if (isInsideConnectionRadius && !isHandleValid) {
connectionStatus = 'invalid';
}
return connectionStatus as ConnectionStatus;
}
@@ -6,7 +6,7 @@ import { Provider } from '../../contexts/RFStoreContext';
import { createRFStore } from '../../store';
import type { ReactFlowState } from '../../types';
const ReactFlowProvider: FC<PropsWithChildren> = ({ children }) => {
const ReactFlowProvider: FC<PropsWithChildren<unknown>> = ({ children }) => {
const storeRef = useRef<StoreApi<ReactFlowState> | null>(null);
if (!storeRef.current) {
@@ -4,7 +4,7 @@ import type { FC, PropsWithChildren } from 'react';
import StoreContext from '../../contexts/RFStoreContext';
import ReactFlowProvider from '../../components/ReactFlowProvider';
const Wrapper: FC<PropsWithChildren> = ({ children }) => {
const Wrapper: FC<PropsWithChildren<unknown>> = ({ children }) => {
const isWrapped = useContext(StoreContext);
if (isWrapped) {
+3 -2
View File
@@ -133,10 +133,11 @@ function useDrag({
const {
nodeInternals,
multiSelectionActive,
domNode,
nodesDraggable,
unselectNodesAndEdges,
onNodeDragStart,
onSelectionDragStart,
domNode,
} = store.getState();
const onStart = nodeId ? onNodeDragStart : wrapSelectionDragFunc(onSelectionDragStart);
@@ -157,7 +158,7 @@ function useDrag({
const pointerPos = getPointerPosition(event);
lastPos.current = pointerPos;
dragItems.current = getDragItems(nodeInternals, pointerPos, nodeId);
dragItems.current = getDragItems(nodeInternals, nodesDraggable, pointerPos, nodeId);
if (onStart && dragItems.current) {
const [currentNode, nodes] = getEventHandlerParams({
+12 -2
View File
@@ -36,9 +36,19 @@ export function hasSelector(target: Element, selector: string, nodeRef: RefObjec
}
// looks for all selected nodes and created a NodeDragItem for each of them
export function getDragItems(nodeInternals: NodeInternals, mousePos: XYPosition, nodeId?: string): NodeDragItem[] {
export function getDragItems(
nodeInternals: NodeInternals,
nodesDraggable: boolean,
mousePos: XYPosition,
nodeId?: string
): NodeDragItem[] {
return Array.from(nodeInternals.values())
.filter((n) => (n.selected || n.id === nodeId) && (!n.parentNode || !isParentSelected(n, nodeInternals)))
.filter(
(n) =>
(n.selected || n.id === nodeId) &&
(!n.parentNode || !isParentSelected(n, nodeInternals)) &&
(n.draggable || (nodesDraggable && typeof n.draggable === 'undefined'))
)
.map((n) => ({
id: n.id,
position: n.position || { x: 0, y: 0 },
@@ -7,9 +7,11 @@ function useUpdateNodePositions() {
const store = useStoreApi();
const updatePositions = useCallback((params: { x: number; y: number; isShiftPressed: boolean }) => {
const { nodeInternals, nodeExtent, updateNodePositions, getNodes, snapToGrid, snapGrid, onError } =
const { nodeInternals, nodeExtent, updateNodePositions, getNodes, snapToGrid, snapGrid, onError, nodesDraggable } =
store.getState();
const selectedNodes = getNodes().filter((n) => n.selected);
const selectedNodes = getNodes().filter(
(n) => n.selected && (n.draggable || (nodesDraggable && typeof n.draggable === 'undefined'))
);
// by default a node moves 5px on each key press, or 20px if shift is pressed
// if snap grid is enabled, we use that for the velocity.
const xVelo = snapToGrid ? snapGrid[0] : 5;
+3 -3
View File
@@ -4,7 +4,7 @@ import { shallow } from 'zustand/shallow';
import { useStoreApi, useStore } from '../hooks/useStore';
import { pointToRendererPoint, getTransformForBounds, getD3Transition } from '../utils/graph';
import { fitView as fitViewStore } from '../store/utils';
import { fitView } from '../store/utils';
import type { ViewportHelperFunctions, ReactFlowState, XYPosition } from '../types';
// eslint-disable-next-line @typescript-eslint/no-empty-function
@@ -17,7 +17,7 @@ const initialViewportHelper: ViewportHelperFunctions = {
getZoom: () => 1,
setViewport: noop,
getViewport: () => ({ x: 0, y: 0, zoom: 1 }),
fitView: noop,
fitView: () => false,
setCenter: noop,
fitBounds: noop,
project: (position: XYPosition) => position,
@@ -51,7 +51,7 @@ const useViewportHelper = (): ViewportHelperFunctions => {
const [x, y, zoom] = store.getState().transform;
return { x, y, zoom };
},
fitView: (options) => fitViewStore(store.getState, options),
fitView: (options) => fitView(store.getState, options),
setCenter: (x, y, options) => {
const { width, height, maxZoom } = store.getState();
const nextZoom = typeof options?.zoom !== 'undefined' ? options.zoom : maxZoom;
+1
View File
@@ -274,6 +274,7 @@ const createRFStore = () =>
connectionNodeId: initialState.connectionNodeId,
connectionHandleId: initialState.connectionHandleId,
connectionHandleType: initialState.connectionHandleType,
connectionStatus: initialState.connectionStatus,
}),
reset: () => set({ ...initialState }),
}));
+1
View File
@@ -32,6 +32,7 @@ const initialState: ReactFlowStore = {
connectionHandleId: null,
connectionHandleType: 'source',
connectionPosition: { x: 0, y: 0 },
connectionStatus: null,
connectionMode: ConnectionMode.Strict,
domNode: null,
paneDragging: false,
+34 -26
View File
@@ -138,35 +138,43 @@ export function fitView(get: StoreApi<ReactFlowState>['getState'], options: Inte
fitViewOnInit,
nodeOrigin,
} = get();
const isInitialFitView = options.initial && !fitViewOnInitDone && fitViewOnInit;
const d3initialized = d3Zoom && d3Selection;
if ((options.initial && !fitViewOnInitDone && fitViewOnInit) || !options.initial) {
if (d3Zoom && d3Selection) {
const nodes = getNodes().filter((n) => (options.includeHiddenNodes ? n.width && n.height : !n.hidden));
if (d3initialized && (isInitialFitView || !options.initial)) {
const nodes = getNodes().filter((n) => {
const isVisible = options.includeHiddenNodes ? n.width && n.height : !n.hidden;
const nodesInitialized = nodes.every((n) => n.width && n.height);
if (nodes.length > 0 && nodesInitialized) {
const bounds = getRectOfNodes(nodes, nodeOrigin);
const [x, y, zoom] = getTransformForBounds(
bounds,
width,
height,
options.minZoom ?? minZoom,
options.maxZoom ?? maxZoom,
options.padding ?? 0.1
);
const nextTransform = zoomIdentity.translate(x, y).scale(zoom);
if (typeof options.duration === 'number' && options.duration > 0) {
d3Zoom.transform(getD3Transition(d3Selection, options.duration), nextTransform);
} else {
d3Zoom.transform(d3Selection, nextTransform);
}
return true;
if (options.nodes?.length) {
return isVisible && options.nodes.some((optionNode) => optionNode.id === n.id);
}
return isVisible;
});
const nodesInitialized = nodes.every((n) => n.width && n.height);
if (nodes.length > 0 && nodesInitialized) {
const bounds = getRectOfNodes(nodes, nodeOrigin);
const [x, y, zoom] = getTransformForBounds(
bounds,
width,
height,
options.minZoom ?? minZoom,
options.maxZoom ?? maxZoom,
options.padding ?? 0.1
);
const nextTransform = zoomIdentity.translate(x, y).scale(zoom);
if (typeof options.duration === 'number' && options.duration > 0) {
d3Zoom.transform(getD3Transition(d3Selection, options.duration), nextTransform);
} else {
d3Zoom.transform(d3Selection, nextTransform);
}
return true;
}
}
+1
View File
@@ -230,4 +230,5 @@
width: 100%;
height: 100%;
pointer-events: none;
user-select: none;
}
+2 -1
View File
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { CSSProperties, ComponentType, HTMLAttributes, ReactNode, MouseEvent as ReactMouseEvent } from 'react';
import { Position } from '.';
import { ConnectionStatus, Position } from '.';
import type { Connection, HandleElement, HandleType, Node } from '.';
type EdgeLabelOptions = {
@@ -155,6 +155,7 @@ export type ConnectionLineComponentProps = {
toY: number;
fromPosition: Position;
toPosition: Position;
connectionStatus: ConnectionStatus | null;
};
export type ConnectionLineComponent = ComponentType<ConnectionLineComponentProps>;
+5 -1
View File
@@ -30,7 +30,7 @@ export type NodeTypesWrapped = { [key: string]: MemoExoticComponent<ComponentTyp
export type EdgeTypes = { [key: string]: ComponentType<EdgeProps> };
export type EdgeTypesWrapped = { [key: string]: MemoExoticComponent<ComponentType<WrapEdgeProps>> };
export type FitView = (fitViewOptions?: FitViewOptions) => void;
export type FitView = (fitViewOptions?: FitViewOptions) => boolean;
export type Project = (position: XYPosition) => XYPosition;
@@ -61,6 +61,8 @@ export interface Connection {
targetHandle: string | null;
}
export type ConnectionStatus = 'valid' | 'invalid';
export enum ConnectionMode {
Strict = 'strict',
Loose = 'loose',
@@ -74,6 +76,7 @@ export type FitViewOptions = {
minZoom?: number;
maxZoom?: number;
duration?: number;
nodes?: (Partial<Node> & { id: Node['id'] })[];
};
export type OnConnectStartParams = {
@@ -166,6 +169,7 @@ export type ReactFlowStore = {
connectionHandleId: string | null;
connectionHandleType: HandleType | null;
connectionPosition: XYPosition;
connectionStatus: ConnectionStatus | null;
connectionMode: ConnectionMode;
snapToGrid: boolean;
+3 -8
View File
@@ -103,17 +103,12 @@ export function isInputDOMNode(event: KeyboardEvent | ReactKeyboardEvent): boole
// using composed path for handling shadow dom
const target = (kbEvent.composedPath?.()?.[0] || event.target) as HTMLElement;
const isInput = ['INPUT', 'SELECT', 'TEXTAREA'].includes(target?.nodeName) || target?.hasAttribute('contenteditable');
// we want to be able to do a multi selection event if we are in an input field
if (event.ctrlKey || event.metaKey || event.shiftKey) {
return false;
}
const isModifierKey = event.ctrlKey || event.metaKey || event.shiftKey;
// when an input field is focused we don't want to trigger deletion or movement of nodes
return (
['INPUT', 'SELECT', 'TEXTAREA'].includes(target?.nodeName) ||
target?.hasAttribute('contenteditable') ||
!!target?.closest('.nokey')
);
return (isInput && !isModifierKey) || !!target?.closest('.nokey');
}
export const isMouseEvent = (
+37
View File
@@ -1,5 +1,42 @@
# @reactflow/minimap
## 11.3.8
### Patch Changes
- Updated dependencies [[`72216ff6`](https://github.com/wbkd/react-flow/commit/72216ff62014acd2d73999053c72bd7aeed351f6), [`959b1114`](https://github.com/wbkd/react-flow/commit/959b111448bba4686040473e46988be9e7befbe6), [`0d259b02`](https://github.com/wbkd/react-flow/commit/0d259b028558aab650546f3371a85f3bce45252f), [`f3de9335`](https://github.com/wbkd/react-flow/commit/f3de9335af6cd96cd77dc77f24a944eef85384e5), [`23424ea6`](https://github.com/wbkd/react-flow/commit/23424ea6750f092210f83df17a00c89adb910d96), [`021f5a92`](https://github.com/wbkd/react-flow/commit/021f5a9210f47a968e50446cd2f9dae1f97880a4)]:
- @reactflow/core@11.5.5
## 11.3.7
### Patch Changes
- Updated dependencies [[`383a074a`](https://github.com/wbkd/react-flow/commit/383a074aeae6dbec8437fa08c7c8d8240838a84e)]:
- @reactflow/core@11.5.4
## 11.3.6
### Patch Changes
- Updated dependencies [[`be8097ac`](https://github.com/wbkd/react-flow/commit/be8097acadca3054c3b236ce4296fc516010ef8c), [`1527795d`](https://github.com/wbkd/react-flow/commit/1527795d18c3af38c8ec7059436ea0fbf6c27bbd), [`3b6348a8`](https://github.com/wbkd/react-flow/commit/3b6348a8d1573afb39576327318bc172e33393c2)]:
- @reactflow/core@11.5.3
## 11.3.5
### Patch Changes
- [#2792](https://github.com/wbkd/react-flow/pull/2792) [`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a) - Accept React 17 types as dev dependency
- Updated dependencies [[`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a)]:
- @reactflow/core@11.5.2
## 11.3.4
### Patch Changes
- Updated dependencies [[`71153534`](https://github.com/wbkd/react-flow/commit/7115353418ebc7f7c81ab0e861200972bbf7dbd5)]:
- @reactflow/core@11.5.1
## 11.3.3
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@reactflow/minimap",
"version": "11.3.3",
"version": "11.3.8",
"description": "Minimap component for React Flow.",
"keywords": [
"react",
@@ -55,7 +55,7 @@
"@reactflow/rollup-config": "workspace:*",
"@reactflow/tsconfig": "workspace:*",
"@types/node": "^18.7.16",
"@types/react": "^18.0.19",
"@types/react": ">=17",
"react": "^18.2.0",
"typescript": "^4.9.4"
},
+9
View File
@@ -1,5 +1,14 @@
# @reactflow/node-resizer
## 2.0.1
### Patch Changes
- [#2792](https://github.com/wbkd/react-flow/pull/2792) [`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a) - Accept React 17 types as dev dependency
- Updated dependencies [[`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a)]:
- @reactflow/core@11.5.2
## 2.0.0
After this update it should be easier to update the node resizer (no need to update the reactflow package anymore).
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@reactflow/node-resizer",
"version": "2.0.0",
"version": "2.0.1",
"description": "A helper component for resizing nodes.",
"keywords": [
"react",
@@ -55,8 +55,8 @@
"@types/d3-drag": "^3.0.1",
"@types/d3-selection": "^3.0.3",
"@types/node": "^18.7.16",
"@types/react": "^18.0.19",
"@types/react-dom": "^18.0.6",
"@types/react": ">=17",
"@types/react-dom": ">=17",
"react": "^18.2.0",
"typescript": "^4.9.4"
},
+37
View File
@@ -1,5 +1,42 @@
# @reactflow/node-toolbar
## 1.1.8
### Patch Changes
- Updated dependencies [[`72216ff6`](https://github.com/wbkd/react-flow/commit/72216ff62014acd2d73999053c72bd7aeed351f6), [`959b1114`](https://github.com/wbkd/react-flow/commit/959b111448bba4686040473e46988be9e7befbe6), [`0d259b02`](https://github.com/wbkd/react-flow/commit/0d259b028558aab650546f3371a85f3bce45252f), [`f3de9335`](https://github.com/wbkd/react-flow/commit/f3de9335af6cd96cd77dc77f24a944eef85384e5), [`23424ea6`](https://github.com/wbkd/react-flow/commit/23424ea6750f092210f83df17a00c89adb910d96), [`021f5a92`](https://github.com/wbkd/react-flow/commit/021f5a9210f47a968e50446cd2f9dae1f97880a4)]:
- @reactflow/core@11.5.5
## 1.1.7
### Patch Changes
- Updated dependencies [[`383a074a`](https://github.com/wbkd/react-flow/commit/383a074aeae6dbec8437fa08c7c8d8240838a84e)]:
- @reactflow/core@11.5.4
## 1.1.6
### Patch Changes
- Updated dependencies [[`be8097ac`](https://github.com/wbkd/react-flow/commit/be8097acadca3054c3b236ce4296fc516010ef8c), [`1527795d`](https://github.com/wbkd/react-flow/commit/1527795d18c3af38c8ec7059436ea0fbf6c27bbd), [`3b6348a8`](https://github.com/wbkd/react-flow/commit/3b6348a8d1573afb39576327318bc172e33393c2)]:
- @reactflow/core@11.5.3
## 1.1.5
### Patch Changes
- [#2792](https://github.com/wbkd/react-flow/pull/2792) [`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a) - Accept React 17 types as dev dependency
- Updated dependencies [[`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a)]:
- @reactflow/core@11.5.2
## 1.1.4
### Patch Changes
- Updated dependencies [[`71153534`](https://github.com/wbkd/react-flow/commit/7115353418ebc7f7c81ab0e861200972bbf7dbd5)]:
- @reactflow/core@11.5.1
## 1.1.3
### Patch Changes
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@reactflow/node-toolbar",
"version": "1.1.3",
"version": "1.1.8",
"description": "A toolbar component for React Flow that can be attached to a node.",
"keywords": [
"react",
@@ -36,7 +36,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@reactflow/core": "workspace:^11.3.3",
"@reactflow/core": "workspace:*",
"classcat": "^5.0.3",
"zustand": "^4.3.1"
},
@@ -49,8 +49,8 @@
"@reactflow/rollup-config": "workspace:*",
"@reactflow/tsconfig": "workspace:*",
"@types/node": "^18.7.16",
"@types/react": "^18.0.19",
"@types/react-dom": "^18.0.6",
"@types/react": ">=17",
"@types/react-dom": ">=17",
"react": "^18.2.0",
"typescript": "^4.9.4"
},
+81 -5
View File
@@ -1,5 +1,79 @@
# reactflow
## 11.5.6
### Patch Changes
- [#2834](https://github.com/wbkd/react-flow/pull/2834) [`23424ea6`](https://github.com/wbkd/react-flow/commit/23424ea6750f092210f83df17a00c89adb910d96) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - Add `nodes` to fit view options to allow fitting view only around specified set of nodes
- [#2836](https://github.com/wbkd/react-flow/pull/2836) [`959b1114`](https://github.com/wbkd/react-flow/commit/959b111448bba4686040473e46988be9e7befbe6) - Fix: connections for handles with bigger handles than connection radius
- [#2819](https://github.com/wbkd/react-flow/pull/2819) [`0d259b02`](https://github.com/wbkd/react-flow/commit/0d259b028558aab650546f3371a85f3bce45252f) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - Avoid triggering edge update if not using left mouse button
- [#2832](https://github.com/wbkd/react-flow/pull/2832) [`f3de9335`](https://github.com/wbkd/react-flow/commit/f3de9335af6cd96cd77dc77f24a944eef85384e5) - fitView: return type boolean
- [#2838](https://github.com/wbkd/react-flow/pull/2838) [`021f5a92`](https://github.com/wbkd/react-flow/commit/021f5a9210f47a968e50446cd2f9dae1f97880a4) - refactor: use key press handle modifier keys + input
- [#2839](https://github.com/wbkd/react-flow/pull/2839) [`72216ff6`](https://github.com/wbkd/react-flow/commit/72216ff62014acd2d73999053c72bd7aeed351f6) - fix PropsWithChildren: pass default generic for v17 types
- Updated dependencies [[`72216ff6`](https://github.com/wbkd/react-flow/commit/72216ff62014acd2d73999053c72bd7aeed351f6), [`959b1114`](https://github.com/wbkd/react-flow/commit/959b111448bba4686040473e46988be9e7befbe6), [`0d259b02`](https://github.com/wbkd/react-flow/commit/0d259b028558aab650546f3371a85f3bce45252f), [`f3de9335`](https://github.com/wbkd/react-flow/commit/f3de9335af6cd96cd77dc77f24a944eef85384e5), [`23424ea6`](https://github.com/wbkd/react-flow/commit/23424ea6750f092210f83df17a00c89adb910d96), [`021f5a92`](https://github.com/wbkd/react-flow/commit/021f5a9210f47a968e50446cd2f9dae1f97880a4)]:
- @reactflow/core@11.5.5
- @reactflow/background@11.1.8
- @reactflow/controls@11.1.8
- @reactflow/minimap@11.3.8
- @reactflow/node-toolbar@1.1.8
## 11.5.5
### Patch Changes
- [`383a074a`](https://github.com/wbkd/react-flow/commit/383a074aeae6dbec8437fa08c7c8d8240838a84e) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - Check if prevClosestHandle exists in onPointerUp. Fixes connections getting stuck on last handle and connecting, even when out of connectionRadius
- Updated dependencies [[`383a074a`](https://github.com/wbkd/react-flow/commit/383a074aeae6dbec8437fa08c7c8d8240838a84e)]:
- @reactflow/core@11.5.4
- @reactflow/background@11.1.7
- @reactflow/controls@11.1.7
- @reactflow/minimap@11.3.7
- @reactflow/node-toolbar@1.1.7
## 11.5.4
This release fixes some issues with the newly introduced connection radius feature. We are now not only checking the radius but the handle itself too (like in the old version). That means that you can connect to a handle that is bigger than the connection radius. We are also not snapping connections anymore when they are not valid and pass a status class to the connection line that says if the current connection is valid or not. More over we fixed a connection issue with iOS.
### Patch Changes
- [#2800](https://github.com/wbkd/react-flow/pull/2800) [`be8097ac`](https://github.com/wbkd/react-flow/commit/be8097acadca3054c3b236ce4296fc516010ef8c) - When node is not draggable, you can't move it with a selection either
- [#2803](https://github.com/wbkd/react-flow/pull/2803) [`1527795d`](https://github.com/wbkd/react-flow/commit/1527795d18c3af38c8ec7059436ea0fbf6c27bbd) - connection: add status class (valid or invalid) while in connection radius
- [#2801](https://github.com/wbkd/react-flow/pull/2801) [`3b6348a8`](https://github.com/wbkd/react-flow/commit/3b6348a8d1573afb39576327318bc172e33393c2) - fix(ios): connection error + dont snap invalid connection lines, check handle and connection radius
- Updated dependencies [[`be8097ac`](https://github.com/wbkd/react-flow/commit/be8097acadca3054c3b236ce4296fc516010ef8c), [`1527795d`](https://github.com/wbkd/react-flow/commit/1527795d18c3af38c8ec7059436ea0fbf6c27bbd), [`3b6348a8`](https://github.com/wbkd/react-flow/commit/3b6348a8d1573afb39576327318bc172e33393c2)]:
- @reactflow/core@11.5.3
- @reactflow/background@11.1.6
- @reactflow/controls@11.1.6
- @reactflow/minimap@11.3.6
- @reactflow/node-toolbar@1.1.6
## 11.5.3
### Patch Changes
- [#2792](https://github.com/wbkd/react-flow/pull/2792) [`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a) - Accept React 17 types as dev dependency
- Updated dependencies [[`d8c679b4`](https://github.com/wbkd/react-flow/commit/d8c679b4c90c5b57d4b51e4aaa988243d6eaff5a)]:
- @reactflow/background@11.1.5
- @reactflow/controls@11.1.5
- @reactflow/core@11.5.2
- @reactflow/minimap@11.3.5
- @reactflow/node-toolbar@1.1.5
## 11.5.2
### Patch Changes
- [#2783](https://github.com/wbkd/react-flow/pull/2783) [`71153534`](https://github.com/wbkd/react-flow/commit/7115353418ebc7f7c81ab0e861200972bbf7dbd5) - connections: check handle below mouse before using connection radius
- Updated dependencies [[`71153534`](https://github.com/wbkd/react-flow/commit/7115353418ebc7f7c81ab0e861200972bbf7dbd5)]:
- @reactflow/core@11.5.1
- @reactflow/background@11.1.4
- @reactflow/controls@11.1.4
- @reactflow/minimap@11.3.4
- @reactflow/node-toolbar@1.1.4
## 11.5.1
### Minor Changes
@@ -8,26 +82,28 @@
## 11.5.0
Lot's of improvements are coming with this release!
Lot's of improvements are coming with this release!
- **Connecting radius**: No need to drop a connection line on top of handle anymore. You only need to be close to the handle. That radius can be configured with the `connectionRadius` prop.
- **Auto pan**: When you drag a node, a selection or the connection line to the border of the pane, it will pan into that direction. That makes it easier to connect far away nodes for example. If you don't like it you can set `autoPnaOnNodeDrag` and `autoPanOnConnect` to false.
- **Touch devices**: It's finally possibleto connect nodes with the connection line on touch devices. In combination with the new auto pan and connection radius the overall UX is way better.
- **Errors**: We added an `onError` prop to get notified when an error like "couldn't find source handle" happens. This is useful if you want to log errors for example.
- **Node type**: We added a second param to the generic `Node` type. You can not only pass `NodeData` but also the type as a second param:
- **Node type**: We added a second param to the generic `Node` type. You can not only pass `NodeData` but also the type as a second param:
```ts
type MyCustomNode = Node<MyCustomNodeData, 'custom-node-type'>
type MyCustomNode = Node<MyCustomNodeData, 'custom-node-type'>;
```
This makes it easier to work with different custom nodes and data types.
### Minor Changes
- [#2754](https://github.com/wbkd/react-flow/pull/2754) [`e96309b6`](https://github.com/wbkd/react-flow/commit/e96309b6a57b1071faeebf7b0547fef7fd418694) - Add auto pan for connecting and node dragging and `connectionRadius`
- [#2754](https://github.com/wbkd/react-flow/pull/2754) [`e96309b6`](https://github.com/wbkd/react-flow/commit/e96309b6a57b1071faeebf7b0547fef7fd418694) - Add auto pan for connecting and node dragging and `connectionRadius`
- [#2773](https://github.com/wbkd/react-flow/pull/2773) - Add `onError` prop to get notified when an error happens
### Patch Changes
- [#2763](https://github.com/wbkd/react-flow/pull/2763) [`85003b01`](https://github.com/wbkd/react-flow/commit/85003b01add71ea852bd5b0d2f1e7496050a6b52) - Connecting nodes: Enable connections on touch devices
- [#2763](https://github.com/wbkd/react-flow/pull/2763) [`85003b01`](https://github.com/wbkd/react-flow/commit/85003b01add71ea852bd5b0d2f1e7496050a6b52) - Connecting nodes: Enable connections on touch devices
- [#2620](https://github.com/wbkd/react-flow/pull/2620) - Thanks [RichSchulz](https://github.com/RichSchulz)! - Types: improve typing for node type
- Updated dependencies [[`e96309b6`](https://github.com/wbkd/react-flow/commit/e96309b6a57b1071faeebf7b0547fef7fd418694), [`85003b01`](https://github.com/wbkd/react-flow/commit/85003b01add71ea852bd5b0d2f1e7496050a6b52), [`4c516882`](https://github.com/wbkd/react-flow/commit/4c516882d2bbf426c1832a53ad40763cc1abef92)]:
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "reactflow",
"version": "11.5.1",
"version": "11.5.6",
"description": "A highly customizable React library for building node-based editors and interactive flow charts",
"keywords": [
"react",
@@ -50,7 +50,7 @@
"@reactflow/rollup-config": "workspace:*",
"@reactflow/tsconfig": "workspace:*",
"@types/node": "^18.7.16",
"@types/react": "^18.0.19",
"@types/react": ">=17",
"react": "^18.2.0",
"typescript": "^4.9.4"
},
+152 -116
View File
@@ -32,15 +32,15 @@ importers:
'@changesets/changelog-github': registry.npmjs.org/@changesets/changelog-github/0.4.7
'@changesets/cli': registry.npmjs.org/@changesets/cli/2.25.0
'@preconstruct/cli': registry.npmjs.org/@preconstruct/cli/2.2.1
'@typescript-eslint/eslint-plugin': registry.npmjs.org/@typescript-eslint/eslint-plugin/5.49.0_equgvmdpavr6nminvx2krii6h4
'@typescript-eslint/parser': registry.npmjs.org/@typescript-eslint/parser/5.49.0_id2eilsndvzhjjktb64trvy3gu
'@typescript-eslint/eslint-plugin': registry.npmjs.org/@typescript-eslint/eslint-plugin/5.51.0_bn63ywsy4d5iuct4ghawihpgsu
'@typescript-eslint/parser': registry.npmjs.org/@typescript-eslint/parser/5.51.0_id2eilsndvzhjjktb64trvy3gu
autoprefixer: registry.npmjs.org/autoprefixer/10.4.9_postcss@8.4.21
concurrently: registry.npmjs.org/concurrently/7.6.0
cypress: registry.npmjs.org/cypress/10.7.0
eslint: registry.npmjs.org/eslint/8.23.1
eslint-config-prettier: registry.npmjs.org/eslint-config-prettier/8.5.0_eslint@8.23.1
eslint-plugin-prettier: registry.npmjs.org/eslint-plugin-prettier/4.2.1_cabrci5exjdaojcvd6xoxgeowu
eslint-plugin-react: registry.npmjs.org/eslint-plugin-react/7.32.1_eslint@8.23.1
eslint-plugin-react: registry.npmjs.org/eslint-plugin-react/7.32.2_eslint@8.23.1
postcss: registry.npmjs.org/postcss/8.4.21
postcss-cli: registry.npmjs.org/postcss-cli/10.1.0_postcss@8.4.21
postcss-combine-duplicated-selectors: registry.npmjs.org/postcss-combine-duplicated-selectors/10.0.3_postcss@8.4.21
@@ -58,6 +58,7 @@ importers:
specifiers:
'@cypress/skip-test': ^2.6.1
'@reactflow/node-resizer': workspace:*
'@types/dagre': ^0.7.48
'@types/react': ^18.0.17
'@types/react-dom': ^18.0.6
'@vitejs/plugin-react': ^3.0.1
@@ -84,6 +85,7 @@ importers:
reactflow: link:../../packages/reactflow
devDependencies:
'@cypress/skip-test': registry.npmjs.org/@cypress/skip-test/2.6.1
'@types/dagre': registry.npmjs.org/@types/dagre/0.7.48
'@types/react': registry.npmjs.org/@types/react/18.0.19
'@types/react-dom': registry.npmjs.org/@types/react-dom/18.0.6
'@vitejs/plugin-react': registry.npmjs.org/@vitejs/plugin-react/3.0.1_vite@4.0.4
@@ -100,7 +102,7 @@ importers:
'@reactflow/rollup-config': workspace:*
'@reactflow/tsconfig': workspace:*
'@types/node': ^18.7.16
'@types/react': ^18.0.19
'@types/react': '>=17'
classcat: ^5.0.3
react: ^18.2.0
typescript: ^4.9.4
@@ -125,7 +127,7 @@ importers:
'@reactflow/rollup-config': workspace:*
'@reactflow/tsconfig': workspace:*
'@types/node': ^18.7.16
'@types/react': ^18.0.19
'@types/react': '>=17'
classcat: ^5.0.3
typescript: ^4.9.4
dependencies:
@@ -149,8 +151,8 @@ importers:
'@types/d3-selection': ^3.0.3
'@types/d3-zoom': ^3.0.1
'@types/node': ^18.7.16
'@types/react': ^18.0.17
'@types/react-dom': ^18.0.6
'@types/react': '>=17'
'@types/react-dom': '>=17'
classcat: ^5.0.3
d3-drag: ^3.0.0
d3-selection: ^3.0.0
@@ -187,7 +189,7 @@ importers:
'@types/d3-selection': ^3.0.3
'@types/d3-zoom': ^3.0.1
'@types/node': ^18.7.16
'@types/react': ^18.0.19
'@types/react': '>=17'
classcat: ^5.0.3
d3-selection: ^3.0.0
d3-zoom: ^3.0.0
@@ -220,8 +222,8 @@ importers:
'@types/d3-drag': ^3.0.1
'@types/d3-selection': ^3.0.3
'@types/node': ^18.7.16
'@types/react': ^18.0.19
'@types/react-dom': ^18.0.6
'@types/react': '>=17'
'@types/react-dom': '>=17'
classcat: ^5.0.4
d3-drag: ^3.0.0
d3-selection: ^3.0.0
@@ -248,13 +250,13 @@ importers:
packages/node-toolbar:
specifiers:
'@reactflow/core': workspace:^11.3.3
'@reactflow/core': workspace:*
'@reactflow/eslint-config': workspace:*
'@reactflow/rollup-config': workspace:*
'@reactflow/tsconfig': workspace:*
'@types/node': ^18.7.16
'@types/react': ^18.0.19
'@types/react-dom': ^18.0.6
'@types/react': '>=17'
'@types/react-dom': '>=17'
classcat: ^5.0.3
react: ^18.2.0
typescript: ^4.9.4
@@ -284,7 +286,7 @@ importers:
'@reactflow/rollup-config': workspace:*
'@reactflow/tsconfig': workspace:*
'@types/node': ^18.7.16
'@types/react': ^18.0.19
'@types/react': '>=17'
react: ^18.2.0
typescript: ^4.9.4
dependencies:
@@ -327,7 +329,7 @@ importers:
typescript: ^4.9.3
vite: ^4.0.0
dependencies:
'@reactflow/core': registry.npmjs.org/@reactflow/core/11.5.1_biqbaboplfbrettd7655fr4n2y
'@reactflow/core': link:../core
cc: registry.npmjs.org/cc/3.0.1
d3-drag: registry.npmjs.org/d3-drag/3.0.0
d3-selection: registry.npmjs.org/d3-selection/3.0.0
@@ -361,7 +363,7 @@ importers:
eslint: registry.npmjs.org/eslint/8.23.1
eslint-config-prettier: registry.npmjs.org/eslint-config-prettier/8.5.0_eslint@8.23.1
eslint-config-turbo: registry.npmjs.org/eslint-config-turbo/0.0.7_eslint@8.23.1
eslint-plugin-react: registry.npmjs.org/eslint-plugin-react/7.32.1_eslint@8.23.1
eslint-plugin-react: registry.npmjs.org/eslint-plugin-react/7.32.2_eslint@8.23.1
tooling/rollup-config:
specifiers:
@@ -1667,30 +1669,6 @@ packages:
- supports-color
dev: true
registry.npmjs.org/@reactflow/core/11.5.1_biqbaboplfbrettd7655fr4n2y:
resolution: {integrity: sha512-63pXpKNW5YHk8hOWpt7RaftSn7g92BvCCGpsUUaRDDuHvxmcqmMKPrAFkBPVc5JJ+Wubx4drThYJizgVP/j9/w==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@reactflow/core/-/core-11.5.1.tgz}
id: registry.npmjs.org/@reactflow/core/11.5.1
name: '@reactflow/core'
version: 11.5.1
peerDependencies:
react: '>=17'
react-dom: '>=17'
dependencies:
'@types/d3': registry.npmjs.org/@types/d3/7.4.0
'@types/d3-drag': registry.npmjs.org/@types/d3-drag/3.0.1
'@types/d3-selection': registry.npmjs.org/@types/d3-selection/3.0.3
'@types/d3-zoom': registry.npmjs.org/@types/d3-zoom/3.0.1
classcat: registry.npmjs.org/classcat/5.0.4
d3-drag: registry.npmjs.org/d3-drag/3.0.0
d3-selection: registry.npmjs.org/d3-selection/3.0.0
d3-zoom: registry.npmjs.org/d3-zoom/3.0.0
react: registry.npmjs.org/react/18.2.0
react-dom: registry.npmjs.org/react-dom/18.2.0_react@18.2.0
zustand: registry.npmjs.org/zustand/4.3.1_react@18.2.0
transitivePeerDependencies:
- immer
dev: false
registry.npmjs.org/@rollup/plugin-alias/3.1.9_rollup@2.79.1:
resolution: {integrity: sha512-QI5fsEvm9bDzt32k39wpOwZhVzRcL5ydcffUHMyLVaVaLeC70I8TJZ17F1z1eMoLu4E/UOcH9BWVkKpIKdrfiw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-3.1.9.tgz}
id: registry.npmjs.org/@rollup/plugin-alias/3.1.9
@@ -2247,6 +2225,12 @@ packages:
'@types/d3-zoom': registry.npmjs.org/@types/d3-zoom/3.0.1
dev: false
registry.npmjs.org/@types/dagre/0.7.48:
resolution: {integrity: sha512-rF3yXSwHIrDxEkN6edCE4TXknb5YSEpiXfLaspw1I08grC49ZFuAVGOQCmZGIuLUGoFgcqGlUFBL/XrpgYpQgw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@types/dagre/-/dagre-0.7.48.tgz}
name: '@types/dagre'
version: 0.7.48
dev: true
registry.npmjs.org/@types/estree/0.0.39:
resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz}
name: '@types/estree'
@@ -2401,36 +2385,6 @@ packages:
dev: true
optional: true
registry.npmjs.org/@typescript-eslint/eslint-plugin/5.49.0_equgvmdpavr6nminvx2krii6h4:
resolution: {integrity: sha512-IhxabIpcf++TBaBa1h7jtOWyon80SXPRLDq0dVz5SLFC/eW6tofkw/O7Ar3lkx5z5U6wzbKDrl2larprp5kk5Q==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.49.0.tgz}
id: registry.npmjs.org/@typescript-eslint/eslint-plugin/5.49.0
name: '@typescript-eslint/eslint-plugin'
version: 5.49.0
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
'@typescript-eslint/parser': ^5.0.0
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/parser': registry.npmjs.org/@typescript-eslint/parser/5.49.0_id2eilsndvzhjjktb64trvy3gu
'@typescript-eslint/scope-manager': registry.npmjs.org/@typescript-eslint/scope-manager/5.49.0
'@typescript-eslint/type-utils': registry.npmjs.org/@typescript-eslint/type-utils/5.49.0_id2eilsndvzhjjktb64trvy3gu
'@typescript-eslint/utils': registry.npmjs.org/@typescript-eslint/utils/5.49.0_id2eilsndvzhjjktb64trvy3gu
debug: registry.npmjs.org/debug/4.3.4
eslint: registry.npmjs.org/eslint/8.23.1
ignore: registry.npmjs.org/ignore/5.2.4
natural-compare-lite: registry.npmjs.org/natural-compare-lite/1.4.0
regexpp: registry.npmjs.org/regexpp/3.2.0
semver: registry.npmjs.org/semver/7.3.8
tsutils: registry.npmjs.org/tsutils/3.21.0_typescript@4.9.4
typescript: registry.npmjs.org/typescript/4.9.4
transitivePeerDependencies:
- supports-color
dev: true
registry.npmjs.org/@typescript-eslint/eslint-plugin/5.49.0_rsaczafy73x3xqauzesvzbsgzy:
resolution: {integrity: sha512-IhxabIpcf++TBaBa1h7jtOWyon80SXPRLDq0dVz5SLFC/eW6tofkw/O7Ar3lkx5z5U6wzbKDrl2larprp5kk5Q==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.49.0.tgz}
id: registry.npmjs.org/@typescript-eslint/eslint-plugin/5.49.0
@@ -2461,24 +2415,32 @@ packages:
- supports-color
dev: true
registry.npmjs.org/@typescript-eslint/parser/5.49.0_id2eilsndvzhjjktb64trvy3gu:
resolution: {integrity: sha512-veDlZN9mUhGqU31Qiv2qEp+XrJj5fgZpJ8PW30sHU+j/8/e5ruAhLaVDAeznS7A7i4ucb/s8IozpDtt9NqCkZg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.49.0.tgz}
id: registry.npmjs.org/@typescript-eslint/parser/5.49.0
name: '@typescript-eslint/parser'
version: 5.49.0
registry.npmjs.org/@typescript-eslint/eslint-plugin/5.51.0_bn63ywsy4d5iuct4ghawihpgsu:
resolution: {integrity: sha512-wcAwhEWm1RgNd7dxD/o+nnLW8oH+6RK1OGnmbmkj/GGoDPV1WWMVP0FXYQBivKHdwM1pwii3bt//RC62EriIUQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.51.0.tgz}
id: registry.npmjs.org/@typescript-eslint/eslint-plugin/5.51.0
name: '@typescript-eslint/eslint-plugin'
version: 5.51.0
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
'@typescript-eslint/parser': ^5.0.0
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/scope-manager': registry.npmjs.org/@typescript-eslint/scope-manager/5.49.0
'@typescript-eslint/types': registry.npmjs.org/@typescript-eslint/types/5.49.0
'@typescript-eslint/typescript-estree': registry.npmjs.org/@typescript-eslint/typescript-estree/5.49.0_typescript@4.9.4
'@typescript-eslint/parser': registry.npmjs.org/@typescript-eslint/parser/5.51.0_id2eilsndvzhjjktb64trvy3gu
'@typescript-eslint/scope-manager': registry.npmjs.org/@typescript-eslint/scope-manager/5.51.0
'@typescript-eslint/type-utils': registry.npmjs.org/@typescript-eslint/type-utils/5.51.0_id2eilsndvzhjjktb64trvy3gu
'@typescript-eslint/utils': registry.npmjs.org/@typescript-eslint/utils/5.51.0_id2eilsndvzhjjktb64trvy3gu
debug: registry.npmjs.org/debug/4.3.4
eslint: registry.npmjs.org/eslint/8.23.1
grapheme-splitter: registry.npmjs.org/grapheme-splitter/1.0.4
ignore: registry.npmjs.org/ignore/5.2.4
natural-compare-lite: registry.npmjs.org/natural-compare-lite/1.4.0
regexpp: registry.npmjs.org/regexpp/3.2.0
semver: registry.npmjs.org/semver/7.3.8
tsutils: registry.npmjs.org/tsutils/3.21.0_typescript@4.9.4
typescript: registry.npmjs.org/typescript/4.9.4
transitivePeerDependencies:
- supports-color
@@ -2507,6 +2469,29 @@ packages:
- supports-color
dev: true
registry.npmjs.org/@typescript-eslint/parser/5.51.0_id2eilsndvzhjjktb64trvy3gu:
resolution: {integrity: sha512-fEV0R9gGmfpDeRzJXn+fGQKcl0inIeYobmmUWijZh9zA7bxJ8clPhV9up2ZQzATxAiFAECqPQyMDB4o4B81AaA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.51.0.tgz}
id: registry.npmjs.org/@typescript-eslint/parser/5.51.0
name: '@typescript-eslint/parser'
version: 5.51.0
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/scope-manager': registry.npmjs.org/@typescript-eslint/scope-manager/5.51.0
'@typescript-eslint/types': registry.npmjs.org/@typescript-eslint/types/5.51.0
'@typescript-eslint/typescript-estree': registry.npmjs.org/@typescript-eslint/typescript-estree/5.51.0_typescript@4.9.4
debug: registry.npmjs.org/debug/4.3.4
eslint: registry.npmjs.org/eslint/8.23.1
typescript: registry.npmjs.org/typescript/4.9.4
transitivePeerDependencies:
- supports-color
dev: true
registry.npmjs.org/@typescript-eslint/scope-manager/5.49.0:
resolution: {integrity: sha512-clpROBOiMIzpbWNxCe1xDK14uPZh35u4QaZO1GddilEzoCLAEz4szb51rBpdgurs5k2YzPtJeTEN3qVbG+LRUQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.49.0.tgz}
name: '@typescript-eslint/scope-manager'
@@ -2517,27 +2502,14 @@ packages:
'@typescript-eslint/visitor-keys': registry.npmjs.org/@typescript-eslint/visitor-keys/5.49.0
dev: true
registry.npmjs.org/@typescript-eslint/type-utils/5.49.0_id2eilsndvzhjjktb64trvy3gu:
resolution: {integrity: sha512-eUgLTYq0tR0FGU5g1YHm4rt5H/+V2IPVkP0cBmbhRyEmyGe4XvJ2YJ6sYTmONfjmdMqyMLad7SB8GvblbeESZA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.49.0.tgz}
id: registry.npmjs.org/@typescript-eslint/type-utils/5.49.0
name: '@typescript-eslint/type-utils'
version: 5.49.0
registry.npmjs.org/@typescript-eslint/scope-manager/5.51.0:
resolution: {integrity: sha512-gNpxRdlx5qw3yaHA0SFuTjW4rxeYhpHxt491PEcKF8Z6zpq0kMhe0Tolxt0qjlojS+/wArSDlj/LtE69xUJphQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.51.0.tgz}
name: '@typescript-eslint/scope-manager'
version: 5.51.0
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: '*'
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': registry.npmjs.org/@typescript-eslint/typescript-estree/5.49.0_typescript@4.9.4
'@typescript-eslint/utils': registry.npmjs.org/@typescript-eslint/utils/5.49.0_id2eilsndvzhjjktb64trvy3gu
debug: registry.npmjs.org/debug/4.3.4
eslint: registry.npmjs.org/eslint/8.23.1
tsutils: registry.npmjs.org/tsutils/3.21.0_typescript@4.9.4
typescript: registry.npmjs.org/typescript/4.9.4
transitivePeerDependencies:
- supports-color
'@typescript-eslint/types': registry.npmjs.org/@typescript-eslint/types/5.51.0
'@typescript-eslint/visitor-keys': registry.npmjs.org/@typescript-eslint/visitor-keys/5.51.0
dev: true
registry.npmjs.org/@typescript-eslint/type-utils/5.49.0_zkdaqh7it7uc4cvz2haft7rc6u:
@@ -2563,6 +2535,29 @@ packages:
- supports-color
dev: true
registry.npmjs.org/@typescript-eslint/type-utils/5.51.0_id2eilsndvzhjjktb64trvy3gu:
resolution: {integrity: sha512-QHC5KKyfV8sNSyHqfNa0UbTbJ6caB8uhcx2hYcWVvJAZYJRBo5HyyZfzMdRx8nvS+GyMg56fugMzzWnojREuQQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.51.0.tgz}
id: registry.npmjs.org/@typescript-eslint/type-utils/5.51.0
name: '@typescript-eslint/type-utils'
version: 5.51.0
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: '*'
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': registry.npmjs.org/@typescript-eslint/typescript-estree/5.51.0_typescript@4.9.4
'@typescript-eslint/utils': registry.npmjs.org/@typescript-eslint/utils/5.51.0_id2eilsndvzhjjktb64trvy3gu
debug: registry.npmjs.org/debug/4.3.4
eslint: registry.npmjs.org/eslint/8.23.1
tsutils: registry.npmjs.org/tsutils/3.21.0_typescript@4.9.4
typescript: registry.npmjs.org/typescript/4.9.4
transitivePeerDependencies:
- supports-color
dev: true
registry.npmjs.org/@typescript-eslint/types/5.49.0:
resolution: {integrity: sha512-7If46kusG+sSnEpu0yOz2xFv5nRz158nzEXnJFCGVEHWnuzolXKwrH5Bsf9zsNlOQkyZuk0BZKKoJQI+1JPBBg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/types/-/types-5.49.0.tgz}
name: '@typescript-eslint/types'
@@ -2570,6 +2565,13 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
registry.npmjs.org/@typescript-eslint/types/5.51.0:
resolution: {integrity: sha512-SqOn0ANn/v6hFn0kjvLwiDi4AzR++CBZz0NV5AnusT2/3y32jdc0G4woXPWHCumWtUXZKPAS27/9vziSsC9jnw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/types/-/types-5.51.0.tgz}
name: '@typescript-eslint/types'
version: 5.51.0
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
registry.npmjs.org/@typescript-eslint/typescript-estree/5.49.0_typescript@4.9.4:
resolution: {integrity: sha512-PBdx+V7deZT/3GjNYPVQv1Nc0U46dAHbIuOG8AZ3on3vuEKiPDwFE/lG1snN2eUB9IhF7EyF7K1hmTcLztNIsA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.49.0.tgz}
id: registry.npmjs.org/@typescript-eslint/typescript-estree/5.49.0
@@ -2594,27 +2596,28 @@ packages:
- supports-color
dev: true
registry.npmjs.org/@typescript-eslint/utils/5.49.0_id2eilsndvzhjjktb64trvy3gu:
resolution: {integrity: sha512-cPJue/4Si25FViIb74sHCLtM4nTSBXtLx1d3/QT6mirQ/c65bV8arBEebBJJizfq8W2YyMoPI/WWPFWitmNqnQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.49.0.tgz}
id: registry.npmjs.org/@typescript-eslint/utils/5.49.0
name: '@typescript-eslint/utils'
version: 5.49.0
registry.npmjs.org/@typescript-eslint/typescript-estree/5.51.0_typescript@4.9.4:
resolution: {integrity: sha512-TSkNupHvNRkoH9FMA3w7TazVFcBPveAAmb7Sz+kArY6sLT86PA5Vx80cKlYmd8m3Ha2SwofM1KwraF24lM9FvA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.51.0.tgz}
id: registry.npmjs.org/@typescript-eslint/typescript-estree/5.51.0
name: '@typescript-eslint/typescript-estree'
version: 5.51.0
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@types/json-schema': registry.npmjs.org/@types/json-schema/7.0.11
'@types/semver': registry.npmjs.org/@types/semver/7.3.13
'@typescript-eslint/scope-manager': registry.npmjs.org/@typescript-eslint/scope-manager/5.49.0
'@typescript-eslint/types': registry.npmjs.org/@typescript-eslint/types/5.49.0
'@typescript-eslint/typescript-estree': registry.npmjs.org/@typescript-eslint/typescript-estree/5.49.0_typescript@4.9.4
eslint: registry.npmjs.org/eslint/8.23.1
eslint-scope: registry.npmjs.org/eslint-scope/5.1.1
eslint-utils: registry.npmjs.org/eslint-utils/3.0.0_eslint@8.23.1
'@typescript-eslint/types': registry.npmjs.org/@typescript-eslint/types/5.51.0
'@typescript-eslint/visitor-keys': registry.npmjs.org/@typescript-eslint/visitor-keys/5.51.0
debug: registry.npmjs.org/debug/4.3.4
globby: registry.npmjs.org/globby/11.1.0
is-glob: registry.npmjs.org/is-glob/4.0.3
semver: registry.npmjs.org/semver/7.3.8
tsutils: registry.npmjs.org/tsutils/3.21.0_typescript@4.9.4
typescript: registry.npmjs.org/typescript/4.9.4
transitivePeerDependencies:
- supports-color
- typescript
dev: true
registry.npmjs.org/@typescript-eslint/utils/5.49.0_zkdaqh7it7uc4cvz2haft7rc6u:
@@ -2640,6 +2643,29 @@ packages:
- typescript
dev: true
registry.npmjs.org/@typescript-eslint/utils/5.51.0_id2eilsndvzhjjktb64trvy3gu:
resolution: {integrity: sha512-76qs+5KWcaatmwtwsDJvBk4H76RJQBFe+Gext0EfJdC3Vd2kpY2Pf//OHHzHp84Ciw0/rYoGTDnIAr3uWhhJYw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.51.0.tgz}
id: registry.npmjs.org/@typescript-eslint/utils/5.51.0
name: '@typescript-eslint/utils'
version: 5.51.0
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
'@types/json-schema': registry.npmjs.org/@types/json-schema/7.0.11
'@types/semver': registry.npmjs.org/@types/semver/7.3.13
'@typescript-eslint/scope-manager': registry.npmjs.org/@typescript-eslint/scope-manager/5.51.0
'@typescript-eslint/types': registry.npmjs.org/@typescript-eslint/types/5.51.0
'@typescript-eslint/typescript-estree': registry.npmjs.org/@typescript-eslint/typescript-estree/5.51.0_typescript@4.9.4
eslint: registry.npmjs.org/eslint/8.23.1
eslint-scope: registry.npmjs.org/eslint-scope/5.1.1
eslint-utils: registry.npmjs.org/eslint-utils/3.0.0_eslint@8.23.1
semver: registry.npmjs.org/semver/7.3.8
transitivePeerDependencies:
- supports-color
- typescript
dev: true
registry.npmjs.org/@typescript-eslint/visitor-keys/5.49.0:
resolution: {integrity: sha512-v9jBMjpNWyn8B6k/Mjt6VbUS4J1GvUlR4x3Y+ibnP1z7y7V4n0WRz+50DY6+Myj0UaXVSuUlHohO+eZ8IJEnkg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.49.0.tgz}
name: '@typescript-eslint/visitor-keys'
@@ -2650,6 +2676,16 @@ packages:
eslint-visitor-keys: registry.npmjs.org/eslint-visitor-keys/3.3.0
dev: true
registry.npmjs.org/@typescript-eslint/visitor-keys/5.51.0:
resolution: {integrity: sha512-Oh2+eTdjHjOFjKA27sxESlA87YPSOJafGCR0md5oeMdh1ZcCfAGCIOL216uTBAkAIptvLIfKQhl7lHxMJet4GQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.51.0.tgz}
name: '@typescript-eslint/visitor-keys'
version: 5.51.0
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': registry.npmjs.org/@typescript-eslint/types/5.51.0
eslint-visitor-keys: registry.npmjs.org/eslint-visitor-keys/3.3.0
dev: true
registry.npmjs.org/@vitejs/plugin-react/3.0.1_vite@4.0.4:
resolution: {integrity: sha512-mx+QvYwIbbpOIJw+hypjnW1lAbKDHtWK5ibkF/V1/oMBu8HU/chb+SnqJDAsLq1+7rGqjktCEomMTM5KShzUKQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-3.0.1.tgz}
id: registry.npmjs.org/@vitejs/plugin-react/3.0.1
@@ -4110,11 +4146,11 @@ packages:
prettier-linter-helpers: registry.npmjs.org/prettier-linter-helpers/1.0.0
dev: true
registry.npmjs.org/eslint-plugin-react/7.32.1_eslint@8.23.1:
resolution: {integrity: sha512-vOjdgyd0ZHBXNsmvU+785xY8Bfe57EFbTYYk8XrROzWpr9QBvpjITvAXt9xqcE6+8cjR/g1+mfumPToxsl1www==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.1.tgz}
id: registry.npmjs.org/eslint-plugin-react/7.32.1
registry.npmjs.org/eslint-plugin-react/7.32.2_eslint@8.23.1:
resolution: {integrity: sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz}
id: registry.npmjs.org/eslint-plugin-react/7.32.2
name: eslint-plugin-react
version: 7.32.1
version: 7.32.2
engines: {node: '>=4'}
peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8