From 2adf37849b7164b8219a0205dc1afa5c18dbd75c Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Wed, 23 Nov 2022 13:15:10 +0100 Subject: [PATCH 01/19] ref: stop using try..catch as control flow in Wrapper Previously, Wrapper used try..catch around a call to useStoreApi to check whether there was an available StoreContext, instead of simply using useContext and checking the value. This leads to poor developer experience when using the devtools feature "pause on caught exceptions" as it causes the devtools to break on every render of a Wrapper that is not within a StoreContext provider. The catch is also universal, meaning that it could catch a completely unrelated error and happily keep going instead of crashing which is undesirable. This commit changes this try..catch into a simple call to useContext to check if a StoreContext is available. --- packages/core/src/container/ReactFlow/Wrapper.tsx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/core/src/container/ReactFlow/Wrapper.tsx b/packages/core/src/container/ReactFlow/Wrapper.tsx index 297e3b49..b6069948 100644 --- a/packages/core/src/container/ReactFlow/Wrapper.tsx +++ b/packages/core/src/container/ReactFlow/Wrapper.tsx @@ -1,18 +1,10 @@ -import type { FC, PropsWithChildren } from 'react'; +import { FC, PropsWithChildren, useContext } from 'react'; -import { useStoreApi } from '../../hooks/useStore'; +import StoreContext from '../../contexts/RFStoreContext'; import ReactFlowProvider from '../../components/ReactFlowProvider'; const Wrapper: FC = ({ children }) => { - let isWrapped = true; - - try { - useStoreApi(); - } catch (e) { - isWrapped = false; - } - - if (isWrapped) { + if (useContext(StoreContext)) { // we need to wrap it with a fragment because it's not allowed for children to be a ReactNode // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18051 return <>{children}; From d4b00452a0f4e4111868e2cf11a914aa3cd80f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20M=C3=B6ller?= Date: Thu, 24 Nov 2022 12:51:17 +0100 Subject: [PATCH 02/19] feat(node-toolbar): allow multiple nodeIds as property to enable multi selection --- .../NodeToolbar/SelectedNodesToolbar.tsx | 13 ++++++++ .../src/examples/NodeToolbar/index.tsx | 2 ++ packages/node-toolbar/src/NodeToolbar.tsx | 33 ++++++++++++++----- packages/node-toolbar/src/types.ts | 2 +- 4 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 examples/vite-app/src/examples/NodeToolbar/SelectedNodesToolbar.tsx diff --git a/examples/vite-app/src/examples/NodeToolbar/SelectedNodesToolbar.tsx b/examples/vite-app/src/examples/NodeToolbar/SelectedNodesToolbar.tsx new file mode 100644 index 00000000..9c0db9cc --- /dev/null +++ b/examples/vite-app/src/examples/NodeToolbar/SelectedNodesToolbar.tsx @@ -0,0 +1,13 @@ +import { NodeToolbar, useNodes } from 'reactflow'; + +export default function SelectedNodesToolbar() { + const nodes = useNodes(); + const selectedNodeIds = nodes.filter((node) => node.selected).map((node) => node.id); + const isVisible = selectedNodeIds.length > 1; + + return ( + + + + ); +} diff --git a/examples/vite-app/src/examples/NodeToolbar/index.tsx b/examples/vite-app/src/examples/NodeToolbar/index.tsx index 9a5815df..601d8618 100644 --- a/examples/vite-app/src/examples/NodeToolbar/index.tsx +++ b/examples/vite-app/src/examples/NodeToolbar/index.tsx @@ -11,6 +11,7 @@ import ReactFlow, { } from 'reactflow'; import CustomNode from './CustomNode'; +import SelectedNodesToolbar from './SelectedNodesToolbar'; const nodeTypes: NodeTypes = { custom: CustomNode, @@ -79,6 +80,7 @@ export default function NodeToolbarExample() { + ); } diff --git a/packages/node-toolbar/src/NodeToolbar.tsx b/packages/node-toolbar/src/NodeToolbar.tsx index caadf257..66ebd618 100644 --- a/packages/node-toolbar/src/NodeToolbar.tsx +++ b/packages/node-toolbar/src/NodeToolbar.tsx @@ -15,9 +15,7 @@ import shallow from 'zustand/shallow'; import NodeToolbarPortal from './NodeToolbarPortal'; import { NodeToolbarProps } from './types'; -type SelectedNode = Node | undefined; - -const nodeEqualityFn = (a: SelectedNode, b: SelectedNode) => +const nodeEqualityFn = (a: Node | undefined, b: Node | undefined) => a?.positionAbsolute?.x === b?.positionAbsolute?.x && a?.positionAbsolute?.y === b?.positionAbsolute?.y && a?.width === b?.width && @@ -25,6 +23,10 @@ const nodeEqualityFn = (a: SelectedNode, b: SelectedNode) => a?.selected === b?.selected && a?.[internalsSymbol]?.z === b?.[internalsSymbol]?.z; +const nodesEqualityFn = (a: Node[], b: Node[]) => { + return a.length === b.length && a.every((node, i) => nodeEqualityFn(node, b[i])); +}; + const storeSelector = (state: ReactFlowState) => ({ transform: state.transform, nodeOrigin: state.nodeOrigin, @@ -70,21 +72,34 @@ function NodeToolbar({ offset = 10, ...rest }: NodeToolbarProps) { - const nodeSelector = useCallback((state: ReactFlowState): SelectedNode => state.nodeInternals.get(nodeId), [nodeId]); - const node = useStore(nodeSelector, nodeEqualityFn); + const nodeIds: string[] = typeof nodeId === 'string' ? [nodeId] : nodeId; + const nodesSelector = useCallback( + (state: ReactFlowState): Node[] => + nodeIds.reduce((acc, id) => { + const node = state.nodeInternals.get(id); + if (node) { + acc.push(node); + } + return acc; + }, [] as Node[]), + [nodeIds] + ); + const nodes = useStore(nodesSelector, nodesEqualityFn); const { transform, nodeOrigin, selectedNodesCount } = useStore(storeSelector, shallow); - const isActive = typeof isVisible === 'boolean' ? isVisible : node?.selected && selectedNodesCount === 1; + const isActive = + typeof isVisible === 'boolean' ? isVisible : nodes.length === 1 && nodes[0].selected && selectedNodesCount === 1; - if (!isActive || !node) { + if (!isActive || !nodes.length) { return null; } - const nodeRect: Rect = getRectOfNodes([node], nodeOrigin); + const nodeRect: Rect = getRectOfNodes(nodes, nodeOrigin); + const zIndex: number = Math.max(...nodes.map((node) => (node[internalsSymbol]?.z || 1) + 1)); const wrapperStyle: CSSProperties = { position: 'absolute', transform: getTransform(nodeRect, transform, position, offset), - zIndex: (node[internalsSymbol]?.z || 1) + 1, + zIndex, ...style, }; diff --git a/packages/node-toolbar/src/types.ts b/packages/node-toolbar/src/types.ts index 1e6576b6..a9f547ad 100644 --- a/packages/node-toolbar/src/types.ts +++ b/packages/node-toolbar/src/types.ts @@ -2,7 +2,7 @@ import { Position } from '@reactflow/core'; import type { HTMLAttributes } from 'react'; export type NodeToolbarProps = HTMLAttributes & { - nodeId: string; + nodeId: string | string[]; isVisible?: boolean; position?: Position; offset?: number; From ec94d9ecdc964d6d66c04e9242f195614bbfdbbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20M=C3=B6ller?= Date: Thu, 24 Nov 2022 12:59:32 +0100 Subject: [PATCH 03/19] chore(node-toolbar): add changeset --- .changeset/six-dolls-search.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/six-dolls-search.md diff --git a/.changeset/six-dolls-search.md b/.changeset/six-dolls-search.md new file mode 100644 index 00000000..51992026 --- /dev/null +++ b/.changeset/six-dolls-search.md @@ -0,0 +1,5 @@ +--- +'@reactflow/node-toolbar': patch +--- + +Allow multiple node ids to be passed to the node toolbar for enabling multi selection toolbars From 3685420ebf0705a42ed8291d6bf44d6d29343be3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20M=C3=B6ller?= Date: Thu, 24 Nov 2022 16:55:51 +0100 Subject: [PATCH 04/19] fix(subflow-node-origin): use node origin in node position calculation --- .../vite-app/src/examples/Subflow/index.tsx | 5 +- packages/core/src/hooks/useDrag/index.ts | 3 +- packages/core/src/hooks/useDrag/utils.ts | 21 ++++---- packages/core/src/store/index.ts | 9 ++-- packages/core/src/store/utils.ts | 43 +++++++++++----- packages/core/src/utils/graph.ts | 51 +++++++++++++++---- packages/minimap/src/MiniMap.tsx | 1 + 7 files changed, 97 insertions(+), 36 deletions(-) diff --git a/examples/vite-app/src/examples/Subflow/index.tsx b/examples/vite-app/src/examples/Subflow/index.tsx index 84003c83..8d2945e0 100644 --- a/examples/vite-app/src/examples/Subflow/index.tsx +++ b/examples/vite-app/src/examples/Subflow/index.tsx @@ -11,6 +11,7 @@ import ReactFlow, { Controls, MiniMap, Background, + NodeOrigin, } from 'reactflow'; import DebugNode from './DebugNode'; @@ -21,6 +22,7 @@ const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node); const onEdgeClick = (_: MouseEvent, edge: Edge) => console.log('click', edge); const defaultViewport = { x: 0, y: 0, zoom: 1.5 }; +const nodeOrigin: NodeOrigin = [0.5, 0.5]; const initialNodes: Node[] = [ { @@ -90,7 +92,7 @@ const initialNodes: Node[] = [ { id: '5a', data: { label: 'Node 5a' }, - position: { x: 25, y: 50 }, + position: { x: 0, y: 0 }, className: 'light', parentNode: '5', extent: 'parent', @@ -205,6 +207,7 @@ const Subflow = () => { onlyRenderVisibleElements={false} nodeTypes={nodeTypes} fitView + nodeOrigin={nodeOrigin} > diff --git a/packages/core/src/hooks/useDrag/index.ts b/packages/core/src/hooks/useDrag/index.ts index 319c1993..47c2113a 100644 --- a/packages/core/src/hooks/useDrag/index.ts +++ b/packages/core/src/hooks/useDrag/index.ts @@ -114,6 +114,7 @@ function useDrag({ onSelectionDrag, snapGrid, snapToGrid, + nodeOrigin, } = store.getState(); const pointerPos = getPointerPosition(event); // skip events without movement @@ -133,7 +134,7 @@ function useDrag({ nextPosition.y = snapGrid[1] * Math.round(nextPosition.y / snapGrid[1]); } - const updatedPos = calcNextPosition(n, nextPosition, nodeInternals, nodeExtent); + const updatedPos = calcNextPosition(n, nextPosition, nodeInternals, nodeExtent, nodeOrigin); n.position = updatedPos.position; n.positionAbsolute = updatedPos.positionAbsolute; diff --git a/packages/core/src/hooks/useDrag/utils.ts b/packages/core/src/hooks/useDrag/utils.ts index be25f3c1..f9eb6ade 100644 --- a/packages/core/src/hooks/useDrag/utils.ts +++ b/packages/core/src/hooks/useDrag/utils.ts @@ -1,7 +1,8 @@ import type { RefObject } from 'react'; import { clampPosition, devWarn } from '../../utils'; -import type { CoordinateExtent, Node, NodeDragItem, NodeInternals, XYPosition } from '../../types'; +import type { CoordinateExtent, Node, NodeDragItem, NodeInternals, NodeOrigin, XYPosition } from '../../types'; +import { getNodePosition } from '../../utils/graph'; export function isParentSelected(node: Node, nodeInternals: NodeInternals): boolean { if (!node.parentNode) { @@ -60,20 +61,22 @@ export function calcNextPosition( node: NodeDragItem | Node, nextPosition: XYPosition, nodeInternals: NodeInternals, - nodeExtent?: CoordinateExtent + nodeExtent?: CoordinateExtent, + nodeOrigin?: NodeOrigin ): { position: XYPosition; positionAbsolute: XYPosition } { let currentExtent = node.extent || nodeExtent; if (node.extent === 'parent') { if (node.parentNode && node.width && node.height) { const parent = nodeInternals.get(node.parentNode); + const parentPosition = getNodePosition(parent, nodeOrigin); currentExtent = - parent?.positionAbsolute && parent?.width && parent?.height + parentPosition.positionAbsolute && parent?.width && parent?.height ? [ - [parent.positionAbsolute.x, parent.positionAbsolute.y], + [parentPosition.positionAbsolute.x, parentPosition.positionAbsolute.y], [ - parent.positionAbsolute.x + parent.width - node.width, - parent.positionAbsolute.y + parent.height - node.height, + parentPosition.positionAbsolute.x + parent.width - node.width, + parentPosition.positionAbsolute.y + parent.height - node.height, ], ] : currentExtent; @@ -84,8 +87,8 @@ export function calcNextPosition( } } else if (node.extent && node.parentNode) { const parent = nodeInternals.get(node.parentNode); - const parentX = parent?.positionAbsolute?.x ?? 0; - const parentY = parent?.positionAbsolute?.y ?? 0; + const parentPosition = getNodePosition(parent, nodeOrigin); + const { x: parentX, y: parentY } = parentPosition.positionAbsolute; currentExtent = [ [node.extent[0][0] + parentX, node.extent[0][1] + parentY], [node.extent[1][0] + parentX, node.extent[1][1] + parentY], @@ -96,7 +99,7 @@ export function calcNextPosition( if (node.parentNode) { const parentNode = nodeInternals.get(node.parentNode); - parentPosition = { x: parentNode?.positionAbsolute?.x ?? 0, y: parentNode?.positionAbsolute?.y ?? 0 }; + parentPosition = getNodePosition(parentNode, nodeOrigin).positionAbsolute; } const positionAbsolute = currentExtent diff --git a/packages/core/src/store/index.ts b/packages/core/src/store/index.ts index e09abbd7..5ffd64c3 100644 --- a/packages/core/src/store/index.ts +++ b/packages/core/src/store/index.ts @@ -23,7 +23,8 @@ const createRFStore = () => createStore((set, get) => ({ ...initialState, setNodes: (nodes: Node[]) => { - set({ nodeInternals: createNodeInternals(nodes, get().nodeInternals) }); + const { nodeInternals, nodeOrigin } = get(); + set({ nodeInternals: createNodeInternals(nodes, nodeInternals, nodeOrigin) }); }, setEdges: (edges: Edge[]) => { const { defaultEdgeOptions = {} } = get(); @@ -33,7 +34,7 @@ const createRFStore = () => const hasDefaultNodes = typeof nodes !== 'undefined'; const hasDefaultEdges = typeof edges !== 'undefined'; - const nodeInternals = hasDefaultNodes ? createNodeInternals(nodes, new Map()) : new Map(); + const nodeInternals = hasDefaultNodes ? createNodeInternals(nodes, new Map(), get().nodeOrigin) : new Map(); const nextEdges = hasDefaultEdges ? edges : []; set({ nodeInternals, edges: nextEdges, hasDefaultNodes, hasDefaultEdges }); @@ -102,7 +103,7 @@ const createRFStore = () => } }, updateNodePositions: (nodeDragItems: NodeDragItem[] | Node[], positionChanged = true, dragging = false) => { - const { onNodesChange, nodeInternals, hasDefaultNodes } = get(); + const { onNodesChange, nodeInternals, hasDefaultNodes, nodeOrigin } = get(); if (hasDefaultNodes || onNodesChange) { const changes = nodeDragItems.map((node) => { @@ -123,7 +124,7 @@ const createRFStore = () => if (changes?.length) { if (hasDefaultNodes) { const nodes = applyNodeChanges(changes, Array.from(nodeInternals.values())); - const nextNodeInternals = createNodeInternals(nodes, nodeInternals); + const nextNodeInternals = createNodeInternals(nodes, nodeInternals, nodeOrigin); set({ nodeInternals: nextNodeInternals }); } diff --git a/packages/core/src/store/utils.ts b/packages/core/src/store/utils.ts index 2af09d46..c1b4fd7e 100644 --- a/packages/core/src/store/utils.ts +++ b/packages/core/src/store/utils.ts @@ -2,7 +2,7 @@ import { zoomIdentity } from 'd3-zoom'; import type { StoreApi } from 'zustand'; import { internalsSymbol, isNumeric } from '../utils'; -import { getD3Transition, getRectOfNodes, getTransformForBounds } from '../utils/graph'; +import { getD3Transition, getRectOfNodes, getTransformForBounds, getNodePosition } from '../utils/graph'; import type { Edge, EdgeSelectionChange, @@ -12,6 +12,7 @@ import type { ReactFlowState, XYZPosition, FitViewOptions, + NodeOrigin, } from '../types'; type ParentNodes = Record; @@ -20,21 +21,33 @@ function calculateXYZPosition( node: Node, nodeInternals: NodeInternals, parentNodes: ParentNodes, - result: XYZPosition + result: XYZPosition, + nodeOrigin: NodeOrigin ): XYZPosition { if (!node.parentNode) { return result; } const parentNode = nodeInternals.get(node.parentNode)!; + const parentNodePosition = getNodePosition(parentNode, nodeOrigin); - return calculateXYZPosition(parentNode, nodeInternals, parentNodes, { - x: (result.x ?? 0) + (parentNode.position?.x ?? 0), - y: (result.y ?? 0) + (parentNode.position?.y ?? 0), - z: (parentNode[internalsSymbol]?.z ?? 0) > (result.z ?? 0) ? parentNode[internalsSymbol]?.z ?? 0 : result.z ?? 0, - }); + return calculateXYZPosition( + parentNode, + nodeInternals, + parentNodes, + { + x: (result.x ?? 0) + parentNodePosition.x, + y: (result.y ?? 0) + parentNodePosition.y, + z: (parentNode[internalsSymbol]?.z ?? 0) > (result.z ?? 0) ? parentNode[internalsSymbol]?.z ?? 0 : result.z ?? 0, + }, + nodeOrigin + ); } -export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals): NodeInternals { +export function createNodeInternals( + nodes: Node[], + nodeInternals: NodeInternals, + nodeOrigin: NodeOrigin +): NodeInternals { const nextNodeInternals = new Map(); const parentNodes: ParentNodes = {}; @@ -74,10 +87,16 @@ export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals) } if (node.parentNode || parentNodes[node.id]) { - const { x, y, z } = calculateXYZPosition(node, nextNodeInternals, parentNodes, { - ...node.position, - z: node[internalsSymbol]?.z ?? 0, - }); + const { x, y, z } = calculateXYZPosition( + node, + nextNodeInternals, + parentNodes, + { + ...node.position, + z: node[internalsSymbol]?.z ?? 0, + }, + nodeOrigin + ); node.positionAbsolute = { x, diff --git a/packages/core/src/utils/graph.ts b/packages/core/src/utils/graph.ts index 0408603f..d6a4d068 100644 --- a/packages/core/src/utils/graph.ts +++ b/packages/core/src/utils/graph.ts @@ -141,23 +141,55 @@ export const pointToRendererPoint = ( return position; }; +export const getNodePosition = ( + node: Node | undefined, + nodeOrigin: NodeOrigin = [0, 0] +): XYPosition & { positionAbsolute: XYPosition } => { + if (!node) { + return { + x: 0, + y: 0, + positionAbsolute: { + x: 0, + y: 0, + }, + }; + } + + const position: XYPosition = { + x: node.position.x - (node.width ?? 0) * nodeOrigin[0], + y: node.position.y - (node.height ?? 0) * nodeOrigin[1], + }; + + const positionAbsolute: XYPosition = { + x: (node.positionAbsolute?.x ?? 0) - (node.width ?? 0) * nodeOrigin[0], + y: (node.positionAbsolute?.y ?? 0) - (node.height ?? 0) * nodeOrigin[1], + }; + + return { + ...position, + positionAbsolute, + }; +}; + export const getRectOfNodes = (nodes: Node[], nodeOrigin: NodeOrigin = [0, 0]): Rect => { if (nodes.length === 0) { return { x: 0, y: 0, width: 0, height: 0 }; } const box = nodes.reduce( - (currBox, { positionAbsolute, position, width, height }) => { + (currBox, node) => { + const { positionAbsolute, ...position } = getNodePosition(node, nodeOrigin); const nodeX = positionAbsolute ? positionAbsolute.x : position.x; const nodeY = positionAbsolute ? positionAbsolute.y : position.y; return getBoundsOfBoxes( currBox, rectToBox({ - x: nodeX - nodeOrigin[0] * (width || 0), - y: nodeY - nodeOrigin[1] * (height || 0), - width: width || 0, - height: height || 0, + x: nodeX, + y: nodeY, + width: node.width || 0, + height: node.height || 0, }) ); }, @@ -186,15 +218,17 @@ export const getNodesInside = ( const visibleNodes: Node[] = []; nodeInternals.forEach((node) => { - const { width, height, selectable = true, positionAbsolute = { x: 0, y: 0 } } = node; + const { width, height, selectable = true } = node; if (excludeNonSelectableNodes && !selectable) { return false; } + const { positionAbsolute } = getNodePosition(node, nodeOrigin); + const nodeRect = { - x: positionAbsolute.x - nodeOrigin[0] * (width || 0), - y: positionAbsolute.y - nodeOrigin[1] * (height || 0), + x: positionAbsolute.x, + y: positionAbsolute.y, width: width || 0, height: height || 0, }; @@ -243,4 +277,3 @@ export const getTransformForBounds = ( export const getD3Transition = (selection: D3Selection, duration = 0) => { return selection.transition().duration(duration); }; - diff --git a/packages/minimap/src/MiniMap.tsx b/packages/minimap/src/MiniMap.tsx index 4764a987..8d804f4e 100644 --- a/packages/minimap/src/MiniMap.tsx +++ b/packages/minimap/src/MiniMap.tsx @@ -162,6 +162,7 @@ function MiniMap({ {nodes.map((node) => ( Date: Thu, 24 Nov 2022 22:36:00 +0100 Subject: [PATCH 05/19] fix(subflow-node-origin): use helper function in minimap, calculate extent corrrectly when using nodeOrigin and subflows --- .../vite-app/src/examples/Subflow/index.tsx | 2 - packages/core/src/hooks/useDrag/utils.ts | 19 ++++--- packages/core/src/index.ts | 1 + packages/core/src/store/utils.ts | 4 +- packages/core/src/utils/graph.ts | 6 +-- packages/minimap/src/MiniMap.tsx | 50 +++++++++++-------- 6 files changed, 47 insertions(+), 35 deletions(-) diff --git a/examples/vite-app/src/examples/Subflow/index.tsx b/examples/vite-app/src/examples/Subflow/index.tsx index 8d2945e0..55aea018 100644 --- a/examples/vite-app/src/examples/Subflow/index.tsx +++ b/examples/vite-app/src/examples/Subflow/index.tsx @@ -22,7 +22,6 @@ const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node); const onEdgeClick = (_: MouseEvent, edge: Edge) => console.log('click', edge); const defaultViewport = { x: 0, y: 0, zoom: 1.5 }; -const nodeOrigin: NodeOrigin = [0.5, 0.5]; const initialNodes: Node[] = [ { @@ -207,7 +206,6 @@ const Subflow = () => { onlyRenderVisibleElements={false} nodeTypes={nodeTypes} fitView - nodeOrigin={nodeOrigin} > diff --git a/packages/core/src/hooks/useDrag/utils.ts b/packages/core/src/hooks/useDrag/utils.ts index f9eb6ade..61b0d3f9 100644 --- a/packages/core/src/hooks/useDrag/utils.ts +++ b/packages/core/src/hooks/useDrag/utils.ts @@ -2,7 +2,7 @@ import type { RefObject } from 'react'; import { clampPosition, devWarn } from '../../utils'; import type { CoordinateExtent, Node, NodeDragItem, NodeInternals, NodeOrigin, XYPosition } from '../../types'; -import { getNodePosition } from '../../utils/graph'; +import { getNodePositionWithOrigin } from '../../utils/graph'; export function isParentSelected(node: Node, nodeInternals: NodeInternals): boolean { if (!node.parentNode) { @@ -62,21 +62,24 @@ export function calcNextPosition( nextPosition: XYPosition, nodeInternals: NodeInternals, nodeExtent?: CoordinateExtent, - nodeOrigin?: NodeOrigin + nodeOrigin: NodeOrigin = [0, 0] ): { position: XYPosition; positionAbsolute: XYPosition } { let currentExtent = node.extent || nodeExtent; if (node.extent === 'parent') { if (node.parentNode && node.width && node.height) { const parent = nodeInternals.get(node.parentNode); - const parentPosition = getNodePosition(parent, nodeOrigin); + const parentPosition = getNodePositionWithOrigin(parent, nodeOrigin); currentExtent = parentPosition.positionAbsolute && parent?.width && parent?.height ? [ - [parentPosition.positionAbsolute.x, parentPosition.positionAbsolute.y], [ - parentPosition.positionAbsolute.x + parent.width - node.width, - parentPosition.positionAbsolute.y + parent.height - node.height, + parentPosition.positionAbsolute.x + node.width * nodeOrigin[0], + parentPosition.positionAbsolute.y + node.height * nodeOrigin[1], + ], + [ + parentPosition.positionAbsolute.x + parent.width - node.width + node.width * nodeOrigin[0], + parentPosition.positionAbsolute.y + parent.height - node.height + node.height * nodeOrigin[1], ], ] : currentExtent; @@ -87,7 +90,7 @@ export function calcNextPosition( } } else if (node.extent && node.parentNode) { const parent = nodeInternals.get(node.parentNode); - const parentPosition = getNodePosition(parent, nodeOrigin); + const parentPosition = getNodePositionWithOrigin(parent, nodeOrigin); const { x: parentX, y: parentY } = parentPosition.positionAbsolute; currentExtent = [ [node.extent[0][0] + parentX, node.extent[0][1] + parentY], @@ -99,7 +102,7 @@ export function calcNextPosition( if (node.parentNode) { const parentNode = nodeInternals.get(node.parentNode); - parentPosition = getNodePosition(parentNode, nodeOrigin).positionAbsolute; + parentPosition = getNodePositionWithOrigin(parentNode, nodeOrigin).positionAbsolute; } const positionAbsolute = currentExtent diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index e2e077db..d51540e9 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -19,6 +19,7 @@ export { updateEdge, getTransformForBounds, getRectOfNodes, + getNodePositionWithOrigin, } from './utils/graph'; export { applyNodeChanges, applyEdgeChanges } from './utils/changes'; export { getMarkerEnd } from './components/Edges/utils'; diff --git a/packages/core/src/store/utils.ts b/packages/core/src/store/utils.ts index c1b4fd7e..02a4516b 100644 --- a/packages/core/src/store/utils.ts +++ b/packages/core/src/store/utils.ts @@ -2,7 +2,7 @@ import { zoomIdentity } from 'd3-zoom'; import type { StoreApi } from 'zustand'; import { internalsSymbol, isNumeric } from '../utils'; -import { getD3Transition, getRectOfNodes, getTransformForBounds, getNodePosition } from '../utils/graph'; +import { getD3Transition, getRectOfNodes, getTransformForBounds, getNodePositionWithOrigin } from '../utils/graph'; import type { Edge, EdgeSelectionChange, @@ -28,7 +28,7 @@ function calculateXYZPosition( return result; } const parentNode = nodeInternals.get(node.parentNode)!; - const parentNodePosition = getNodePosition(parentNode, nodeOrigin); + const parentNodePosition = getNodePositionWithOrigin(parentNode, nodeOrigin); return calculateXYZPosition( parentNode, diff --git a/packages/core/src/utils/graph.ts b/packages/core/src/utils/graph.ts index d6a4d068..f07267a5 100644 --- a/packages/core/src/utils/graph.ts +++ b/packages/core/src/utils/graph.ts @@ -141,7 +141,7 @@ export const pointToRendererPoint = ( return position; }; -export const getNodePosition = ( +export const getNodePositionWithOrigin = ( node: Node | undefined, nodeOrigin: NodeOrigin = [0, 0] ): XYPosition & { positionAbsolute: XYPosition } => { @@ -179,7 +179,7 @@ export const getRectOfNodes = (nodes: Node[], nodeOrigin: NodeOrigin = [0, 0]): const box = nodes.reduce( (currBox, node) => { - const { positionAbsolute, ...position } = getNodePosition(node, nodeOrigin); + const { positionAbsolute, ...position } = getNodePositionWithOrigin(node, nodeOrigin); const nodeX = positionAbsolute ? positionAbsolute.x : position.x; const nodeY = positionAbsolute ? positionAbsolute.y : position.y; @@ -224,7 +224,7 @@ export const getNodesInside = ( return false; } - const { positionAbsolute } = getNodePosition(node, nodeOrigin); + const { positionAbsolute } = getNodePositionWithOrigin(node, nodeOrigin); const nodeRect = { x: positionAbsolute.x, diff --git a/packages/minimap/src/MiniMap.tsx b/packages/minimap/src/MiniMap.tsx index 8d804f4e..890df176 100644 --- a/packages/minimap/src/MiniMap.tsx +++ b/packages/minimap/src/MiniMap.tsx @@ -7,7 +7,14 @@ import shallow from 'zustand/shallow'; import { zoom, zoomIdentity } from 'd3-zoom'; import type { D3ZoomEvent } from 'd3-zoom'; import { select, pointer } from 'd3-selection'; -import { useStore, getRectOfNodes, Panel, getBoundsOfRects, useStoreApi } from '@reactflow/core'; +import { + useStore, + getRectOfNodes, + Panel, + getBoundsOfRects, + useStoreApi, + getNodePositionWithOrigin, +} from '@reactflow/core'; import type { ReactFlowState, Rect } from '@reactflow/core'; import MiniMapNode from './MiniMapNode'; @@ -159,25 +166,28 @@ function MiniMap({ onClick={onSvgClick} > {ariaLabel && {ariaLabel}} - {nodes.map((node) => ( - - ))} + {nodes.map((node) => { + const { positionAbsolute } = getNodePositionWithOrigin(node, nodeOrigin); + + return ( + + ); + })} Date: Thu, 24 Nov 2022 22:38:05 +0100 Subject: [PATCH 06/19] chore(subflow-node-origin): create changeset --- .changeset/neat-fishes-burn.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/neat-fishes-burn.md diff --git a/.changeset/neat-fishes-burn.md b/.changeset/neat-fishes-burn.md new file mode 100644 index 00000000..c771c907 --- /dev/null +++ b/.changeset/neat-fishes-burn.md @@ -0,0 +1,6 @@ +--- +'@reactflow/core': patch +'@reactflow/minimap': patch +--- + +Fix and improve the behaviour when using nodeOrigin in combination with subflows From a8d590a60be23437e1d0a87a5d7a6f6ba9d86be9 Mon Sep 17 00:00:00 2001 From: moklick Date: Fri, 25 Nov 2022 21:25:00 +0100 Subject: [PATCH 07/19] chore(nodeOriginHelper): cleanup --- packages/core/src/utils/graph.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/core/src/utils/graph.ts b/packages/core/src/utils/graph.ts index f07267a5..ea390967 100644 --- a/packages/core/src/utils/graph.ts +++ b/packages/core/src/utils/graph.ts @@ -156,19 +156,18 @@ export const getNodePositionWithOrigin = ( }; } - const position: XYPosition = { - x: node.position.x - (node.width ?? 0) * nodeOrigin[0], - y: node.position.y - (node.height ?? 0) * nodeOrigin[1], - }; - - const positionAbsolute: XYPosition = { - x: (node.positionAbsolute?.x ?? 0) - (node.width ?? 0) * nodeOrigin[0], - y: (node.positionAbsolute?.y ?? 0) - (node.height ?? 0) * nodeOrigin[1], + const offset: XYPosition = { + x: (node.width ?? 0) * nodeOrigin[0], + y: (node.height ?? 0) * nodeOrigin[1], }; return { - ...position, - positionAbsolute, + x: node.position.x - offset.x, + y: node.position.y - offset.y, + positionAbsolute: { + x: (node.positionAbsolute?.x ?? 0) - offset.x, + y: (node.positionAbsolute?.y ?? 0) - offset.y, + }, }; }; From 1363d1e398c37950ac097725715d14e98c884df3 Mon Sep 17 00:00:00 2001 From: moklick Date: Fri, 25 Nov 2022 21:35:39 +0100 Subject: [PATCH 08/19] chore(node-toolbar): cleanup --- .../examples/NodeToolbar/SelectedNodesToolbar.tsx | 12 ++++++++---- packages/node-toolbar/src/NodeToolbar.tsx | 12 +++++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/examples/vite-app/src/examples/NodeToolbar/SelectedNodesToolbar.tsx b/examples/vite-app/src/examples/NodeToolbar/SelectedNodesToolbar.tsx index 9c0db9cc..349db385 100644 --- a/examples/vite-app/src/examples/NodeToolbar/SelectedNodesToolbar.tsx +++ b/examples/vite-app/src/examples/NodeToolbar/SelectedNodesToolbar.tsx @@ -1,13 +1,17 @@ -import { NodeToolbar, useNodes } from 'reactflow'; +import { NodeToolbar, ReactFlowState, useStore } from 'reactflow'; + +const selectedNodesSelector = (state: ReactFlowState) => + Array.from(state.nodeInternals.values()) + .filter((node) => node.selected) + .map((node) => node.id); export default function SelectedNodesToolbar() { - const nodes = useNodes(); - const selectedNodeIds = nodes.filter((node) => node.selected).map((node) => node.id); + const selectedNodeIds = useStore(selectedNodesSelector); const isVisible = selectedNodeIds.length > 1; return ( - + ); } diff --git a/packages/node-toolbar/src/NodeToolbar.tsx b/packages/node-toolbar/src/NodeToolbar.tsx index 66ebd618..1dfd7669 100644 --- a/packages/node-toolbar/src/NodeToolbar.tsx +++ b/packages/node-toolbar/src/NodeToolbar.tsx @@ -72,17 +72,19 @@ function NodeToolbar({ offset = 10, ...rest }: NodeToolbarProps) { - const nodeIds: string[] = typeof nodeId === 'string' ? [nodeId] : nodeId; const nodesSelector = useCallback( - (state: ReactFlowState): Node[] => - nodeIds.reduce((acc, id) => { + (state: ReactFlowState): Node[] => { + const nodeIds: string[] = typeof nodeId === 'string' ? [nodeId] : nodeId; + + return nodeIds.reduce((acc, id) => { const node = state.nodeInternals.get(id); if (node) { acc.push(node); } return acc; - }, [] as Node[]), - [nodeIds] + }, [] as Node[]); + }, + [nodeId] ); const nodes = useStore(nodesSelector, nodesEqualityFn); const { transform, nodeOrigin, selectedNodesCount } = useStore(storeSelector, shallow); From d142725ecc02da577283812fc6e557b4711ad283 Mon Sep 17 00:00:00 2001 From: moklick Date: Fri, 25 Nov 2022 21:48:33 +0100 Subject: [PATCH 09/19] fix(isRectObj): repair test for rect closes #2597 --- packages/core/src/utils/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/src/utils/index.ts b/packages/core/src/utils/index.ts index 02cff5a0..d869a81a 100644 --- a/packages/core/src/utils/index.ts +++ b/packages/core/src/utils/index.ts @@ -53,7 +53,8 @@ export const getOverlappingArea = (rectA: Rect, rectB: Rect): number => { }; // eslint-disable-next-line @typescript-eslint/no-explicit-any -export const isRectObject = (obj: any): obj is Rect => !!obj.width && !!obj.height && !!obj.x && !!obj.y; +export const isRectObject = (obj: any): obj is Rect => + isNumeric(obj.width) && isNumeric(obj.height) && isNumeric(obj.x) && isNumeric(obj.y); /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ export const isNumeric = (n: any): n is number => !isNaN(n) && isFinite(n); From b2c728137d1b53e38883f044fa447585c377a6af Mon Sep 17 00:00:00 2001 From: moklick Date: Fri, 25 Nov 2022 21:50:15 +0100 Subject: [PATCH 10/19] chore(changest): add --- .changeset/silver-dots-try.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/silver-dots-try.md diff --git a/.changeset/silver-dots-try.md b/.changeset/silver-dots-try.md new file mode 100644 index 00000000..23994cc4 --- /dev/null +++ b/.changeset/silver-dots-try.md @@ -0,0 +1,5 @@ +--- +'@reactflow/core': patch +--- + +fix isRectObject function From 22db82c8b8ab7d9feeb20fdedc6b50bb7479af4c Mon Sep 17 00:00:00 2001 From: moklick Date: Fri, 25 Nov 2022 22:03:48 +0100 Subject: [PATCH 11/19] chore(wrapper): cleanup --- packages/core/src/container/ReactFlow/Wrapper.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/core/src/container/ReactFlow/Wrapper.tsx b/packages/core/src/container/ReactFlow/Wrapper.tsx index b6069948..f0f56d24 100644 --- a/packages/core/src/container/ReactFlow/Wrapper.tsx +++ b/packages/core/src/container/ReactFlow/Wrapper.tsx @@ -1,10 +1,13 @@ -import { FC, PropsWithChildren, useContext } from 'react'; +import { useContext } from 'react'; +import type { FC, PropsWithChildren } from 'react'; import StoreContext from '../../contexts/RFStoreContext'; import ReactFlowProvider from '../../components/ReactFlowProvider'; const Wrapper: FC = ({ children }) => { - if (useContext(StoreContext)) { + const isWrapped = useContext(StoreContext); + + if (isWrapped) { // we need to wrap it with a fragment because it's not allowed for children to be a ReactNode // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18051 return <>{children}; From b0302ce4261a992bee841bae84af347d03be690f Mon Sep 17 00:00:00 2001 From: moklick Date: Fri, 25 Nov 2022 22:05:51 +0100 Subject: [PATCH 12/19] chore(changeset): add --- .changeset/perfect-spiders-own.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/perfect-spiders-own.md diff --git a/.changeset/perfect-spiders-own.md b/.changeset/perfect-spiders-own.md new file mode 100644 index 00000000..d565e109 --- /dev/null +++ b/.changeset/perfect-spiders-own.md @@ -0,0 +1,5 @@ +--- +'@reactflow/core': patch +--- + +Wrapper: dont use try catch for checking if provider is available From 8b3d125115271dcd3e67cfafdc77fe9b0ba1710b Mon Sep 17 00:00:00 2001 From: moklick Date: Fri, 25 Nov 2022 22:17:29 +0100 Subject: [PATCH 13/19] chore(packages): bump --- .changeset/neat-fishes-burn.md | 6 ------ .changeset/perfect-spiders-own.md | 5 ----- .changeset/silver-dots-try.md | 5 ----- .changeset/six-dolls-search.md | 5 ----- examples/vite-app/package.json | 2 +- packages/background/CHANGELOG.md | 7 +++++++ packages/background/package.json | 2 +- packages/controls/CHANGELOG.md | 7 +++++++ packages/controls/package.json | 2 +- packages/core/CHANGELOG.md | 8 ++++++++ packages/core/package.json | 2 +- packages/minimap/CHANGELOG.md | 9 +++++++++ packages/minimap/package.json | 2 +- packages/node-toolbar/CHANGELOG.md | 9 +++++++++ packages/node-toolbar/package.json | 2 +- packages/reactflow/CHANGELOG.md | 16 ++++++++++++++++ packages/reactflow/package.json | 2 +- 17 files changed, 63 insertions(+), 28 deletions(-) delete mode 100644 .changeset/neat-fishes-burn.md delete mode 100644 .changeset/perfect-spiders-own.md delete mode 100644 .changeset/silver-dots-try.md delete mode 100644 .changeset/six-dolls-search.md diff --git a/.changeset/neat-fishes-burn.md b/.changeset/neat-fishes-burn.md deleted file mode 100644 index c771c907..00000000 --- a/.changeset/neat-fishes-burn.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@reactflow/core': patch -'@reactflow/minimap': patch ---- - -Fix and improve the behaviour when using nodeOrigin in combination with subflows diff --git a/.changeset/perfect-spiders-own.md b/.changeset/perfect-spiders-own.md deleted file mode 100644 index d565e109..00000000 --- a/.changeset/perfect-spiders-own.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@reactflow/core': patch ---- - -Wrapper: dont use try catch for checking if provider is available diff --git a/.changeset/silver-dots-try.md b/.changeset/silver-dots-try.md deleted file mode 100644 index 23994cc4..00000000 --- a/.changeset/silver-dots-try.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@reactflow/core': patch ---- - -fix isRectObject function diff --git a/.changeset/six-dolls-search.md b/.changeset/six-dolls-search.md deleted file mode 100644 index 51992026..00000000 --- a/.changeset/six-dolls-search.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@reactflow/node-toolbar': patch ---- - -Allow multiple node ids to be passed to the node toolbar for enabling multi selection toolbars diff --git a/examples/vite-app/package.json b/examples/vite-app/package.json index 677f7289..cf31055e 100644 --- a/examples/vite-app/package.json +++ b/examples/vite-app/package.json @@ -1,7 +1,7 @@ { "name": "@reactflow/examples", "private": true, - "version": "0.0.0", + "version": "0.0.1", "type": "module", "scripts": { "dev": "vite --port 3000 --open", diff --git a/packages/background/CHANGELOG.md b/packages/background/CHANGELOG.md index eff5abc5..1713e819 100644 --- a/packages/background/CHANGELOG.md +++ b/packages/background/CHANGELOG.md @@ -1,5 +1,12 @@ # @reactflow/background +## 11.0.6 + +### Patch Changes + +- Updated dependencies [[`c828bfda`](https://github.com/wbkd/react-flow/commit/c828bfda0a8c4774bc43588640c7cca0cfdcb3f4), [`b0302ce4`](https://github.com/wbkd/react-flow/commit/b0302ce4261a992bee841bae84af347d03be690f), [`b2c72813`](https://github.com/wbkd/react-flow/commit/b2c728137d1b53e38883f044fa447585c377a6af)]: + - @reactflow/core@11.3.1 + ## 11.0.5 ### Patch Changes diff --git a/packages/background/package.json b/packages/background/package.json index b821f6b8..7df6af43 100644 --- a/packages/background/package.json +++ b/packages/background/package.json @@ -1,6 +1,6 @@ { "name": "@reactflow/background", - "version": "11.0.5", + "version": "11.0.6", "description": "Background component with different variants for React Flow", "keywords": [ "react", diff --git a/packages/controls/CHANGELOG.md b/packages/controls/CHANGELOG.md index 729e65b7..40de22b6 100644 --- a/packages/controls/CHANGELOG.md +++ b/packages/controls/CHANGELOG.md @@ -1,5 +1,12 @@ # @reactflow/controls +## 11.0.6 + +### Patch Changes + +- Updated dependencies [[`c828bfda`](https://github.com/wbkd/react-flow/commit/c828bfda0a8c4774bc43588640c7cca0cfdcb3f4), [`b0302ce4`](https://github.com/wbkd/react-flow/commit/b0302ce4261a992bee841bae84af347d03be690f), [`b2c72813`](https://github.com/wbkd/react-flow/commit/b2c728137d1b53e38883f044fa447585c377a6af)]: + - @reactflow/core@11.3.1 + ## 11.0.5 ### Patch Changes diff --git a/packages/controls/package.json b/packages/controls/package.json index 3084073e..91d19ade 100644 --- a/packages/controls/package.json +++ b/packages/controls/package.json @@ -1,6 +1,6 @@ { "name": "@reactflow/controls", - "version": "11.0.5", + "version": "11.0.6", "description": "Component to control the viewport of a React Flow instance", "keywords": [ "react", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 89c25608..59a8cfca 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,13 @@ # @reactflow/core +## 11.3.1 + +### Patch Changes + +- [#2595](https://github.com/wbkd/react-flow/pull/2595) [`c828bfda`](https://github.com/wbkd/react-flow/commit/c828bfda0a8c4774bc43588640c7cca0cfdcb3f4) Thanks [@chrtze](https://github.com/chrtze)! - Fix and improve the behaviour when using nodeOrigin in combination with subflows +- [#2602](https://github.com/wbkd/react-flow/pull/2602) [`b0302ce4`](https://github.com/wbkd/react-flow/commit/b0302ce4261a992bee841bae84af347d03be690f) Thanks [@sdegueldre](https://github.com/sdegueldre)! - Don't use try catch in wrapper for checking if provider is available +- [#2601](https://github.com/wbkd/react-flow/pull/2601) [`b2c72813`](https://github.com/wbkd/react-flow/commit/b2c728137d1b53e38883f044fa447585c377a6af) Thanks [@hoondeveloper](https://github.com/hoondeveloper)! - fix isRectObject function + ## 11.3.0 ### Minor Changes diff --git a/packages/core/package.json b/packages/core/package.json index 3f112b18..58f31d51 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@reactflow/core", - "version": "11.3.0", + "version": "11.3.1", "description": "Core components and util functions of React Flow.", "keywords": [ "react", diff --git a/packages/minimap/CHANGELOG.md b/packages/minimap/CHANGELOG.md index e23e9f1d..36a8f029 100644 --- a/packages/minimap/CHANGELOG.md +++ b/packages/minimap/CHANGELOG.md @@ -1,5 +1,14 @@ # @reactflow/minimap +## 11.2.1 + +### Patch Changes + +- [#2595](https://github.com/wbkd/react-flow/pull/2595) [`c828bfda`](https://github.com/wbkd/react-flow/commit/c828bfda0a8c4774bc43588640c7cca0cfdcb3f4) Thanks [@chrtze](https://github.com/chrtze)! - Fix and improve the behaviour when using nodeOrigin in combination with subflows + +- Updated dependencies [[`c828bfda`](https://github.com/wbkd/react-flow/commit/c828bfda0a8c4774bc43588640c7cca0cfdcb3f4), [`b0302ce4`](https://github.com/wbkd/react-flow/commit/b0302ce4261a992bee841bae84af347d03be690f), [`b2c72813`](https://github.com/wbkd/react-flow/commit/b2c728137d1b53e38883f044fa447585c377a6af)]: + - @reactflow/core@11.3.1 + ## 11.2.0 ### Minor Changes diff --git a/packages/minimap/package.json b/packages/minimap/package.json index f2fc7d20..e2b66d07 100644 --- a/packages/minimap/package.json +++ b/packages/minimap/package.json @@ -1,6 +1,6 @@ { "name": "@reactflow/minimap", - "version": "11.2.0", + "version": "11.2.1", "description": "Minimap component for React Flow.", "keywords": [ "react", diff --git a/packages/node-toolbar/CHANGELOG.md b/packages/node-toolbar/CHANGELOG.md index 9854f032..7bad5ebf 100644 --- a/packages/node-toolbar/CHANGELOG.md +++ b/packages/node-toolbar/CHANGELOG.md @@ -1,5 +1,14 @@ # @reactflow/node-toolbar +## 1.0.1 + +### Patch Changes + +- [#2594](https://github.com/wbkd/react-flow/pull/2594) [`ec94d9ec`](https://github.com/wbkd/react-flow/commit/ec94d9ecdc964d6d66c04e9242f195614bbfdbbe) Thanks [@chrtze](https://github.com/chrtze)! - Allow multiple node ids to be passed for enabling multi selection toolbars + +- Updated dependencies [[`c828bfda`](https://github.com/wbkd/react-flow/commit/c828bfda0a8c4774bc43588640c7cca0cfdcb3f4), [`b0302ce4`](https://github.com/wbkd/react-flow/commit/b0302ce4261a992bee841bae84af347d03be690f), [`b2c72813`](https://github.com/wbkd/react-flow/commit/b2c728137d1b53e38883f044fa447585c377a6af)]: + - @reactflow/core@11.3.1 + ## 1.0.0 ### Major Changes diff --git a/packages/node-toolbar/package.json b/packages/node-toolbar/package.json index ad15e213..18f05350 100644 --- a/packages/node-toolbar/package.json +++ b/packages/node-toolbar/package.json @@ -1,6 +1,6 @@ { "name": "@reactflow/node-toolbar", - "version": "1.0.0", + "version": "1.0.1", "description": "A toolbar component for React Flow that can be attached to a node.", "keywords": [ "react", diff --git a/packages/reactflow/CHANGELOG.md b/packages/reactflow/CHANGELOG.md index 10c2affd..ea6e9a15 100644 --- a/packages/reactflow/CHANGELOG.md +++ b/packages/reactflow/CHANGELOG.md @@ -1,5 +1,21 @@ # reactflow +## 11.3.1 + +### Patch Changes + +- [#2595](https://github.com/wbkd/react-flow/pull/2595) [`c828bfda`](https://github.com/wbkd/react-flow/commit/c828bfda0a8c4774bc43588640c7cca0cfdcb3f4) Thanks [@chrtze](https://github.com/chrtze)! - Fix and improve the behaviour when using nodeOrigin in combination with subflows +- [#2602](https://github.com/wbkd/react-flow/pull/2602) [`b0302ce4`](https://github.com/wbkd/react-flow/commit/b0302ce4261a992bee841bae84af347d03be690f) Thanks [@sdegueldre](https://github.com/sdegueldre)! - Don't use try catch in wrapper for checking if provider is available +- [#2601](https://github.com/wbkd/react-flow/pull/2601) [`b2c72813`](https://github.com/wbkd/react-flow/commit/b2c728137d1b53e38883f044fa447585c377a6af) Thanks [@hoondeveloper](https://github.com/hoondeveloper)! - fix isRectObject function +- [#2594](https://github.com/wbkd/react-flow/pull/2594) [`ec94d9ec`](https://github.com/wbkd/react-flow/commit/ec94d9ecdc964d6d66c04e9242f195614bbfdbbe) Thanks [@chrtze](https://github.com/chrtze)! - Allow multiple node ids to be passed for enabling multi selection toolbars + +- Updated dependencies [[`c828bfda`](https://github.com/wbkd/react-flow/commit/c828bfda0a8c4774bc43588640c7cca0cfdcb3f4), [`b0302ce4`](https://github.com/wbkd/react-flow/commit/b0302ce4261a992bee841bae84af347d03be690f), [`b2c72813`](https://github.com/wbkd/react-flow/commit/b2c728137d1b53e38883f044fa447585c377a6af), [`ec94d9ec`](https://github.com/wbkd/react-flow/commit/ec94d9ecdc964d6d66c04e9242f195614bbfdbbe)]: + - @reactflow/core@11.3.1 + - @reactflow/minimap@11.2.1 + - @reactflow/node-toolbar@1.0.1 + - @reactflow/background@11.0.6 + - @reactflow/controls@11.0.6 + ## 11.3.0 ### Minor Changes diff --git a/packages/reactflow/package.json b/packages/reactflow/package.json index 1178425d..9449f8ba 100644 --- a/packages/reactflow/package.json +++ b/packages/reactflow/package.json @@ -1,6 +1,6 @@ { "name": "reactflow", - "version": "11.3.0", + "version": "11.3.1", "description": "A highly customizable React library for building node-based editors and interactive flow charts", "keywords": [ "react", From 686fb87b35b407b9880b02b8c60f41e302f9f61f Mon Sep 17 00:00:00 2001 From: David Lounsbrough Date: Mon, 28 Nov 2022 13:05:27 -0600 Subject: [PATCH 14/19] Fix y position on minimap --- packages/minimap/src/MiniMap.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/minimap/src/MiniMap.tsx b/packages/minimap/src/MiniMap.tsx index 890df176..722f1423 100644 --- a/packages/minimap/src/MiniMap.tsx +++ b/packages/minimap/src/MiniMap.tsx @@ -173,7 +173,7 @@ function MiniMap({ Date: Mon, 28 Nov 2022 13:58:28 -0600 Subject: [PATCH 15/19] Add assertion to cover path that I fixed --- examples/vite-app/cypress/e2e/minimap.cy.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/vite-app/cypress/e2e/minimap.cy.ts b/examples/vite-app/cypress/e2e/minimap.cy.ts index d6cb7d46..46a5a819 100644 --- a/examples/vite-app/cypress/e2e/minimap.cy.ts +++ b/examples/vite-app/cypress/e2e/minimap.cy.ts @@ -35,17 +35,20 @@ describe('Minimap Testing', () => { }); it('changes node position', () => { - const xPosBeforeDrag = Cypress.$('.react-flow__minimap-node:first').attr('x'); - const yPosBeforeDrag = Cypress.$('.react-flow__minimap-node:first').attr('y'); + const minimapNode = Cypress.$('.react-flow__minimap-node:first'); + + const xPosBeforeDrag = Number(minimapNode.attr('x')); + const yPosBeforeDrag = Number(minimapNode.attr('y')); cy.drag('.react-flow__node:first', { x: 500, y: 25 }) .wait(100) .then(() => { - const xPosAfterDrag = Cypress.$('.react-flow__minimap-node:first').attr('x'); - const yPosAfterDrag = Cypress.$('.react-flow__minimap-node:first').attr('y'); + const xPosAfterDrag = Number(minimapNode.attr('x')); + const yPosAfterDrag = Number(minimapNode.attr('y')); - expect(xPosBeforeDrag).to.not.equal(xPosAfterDrag); - expect(yPosBeforeDrag).to.not.equal(yPosAfterDrag); + expect(xPosAfterDrag).not.to.equal(xPosBeforeDrag); + expect(yPosAfterDrag).not.to.equal(yPosBeforeDrag); + expect(xPosAfterDrag - xPosBeforeDrag).to.be.greaterThan(yPosAfterDrag - yPosBeforeDrag); }); }); From 7ece618d94b76183c1ecd45b16f6ab168168351b Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 28 Nov 2022 21:13:27 +0100 Subject: [PATCH 16/19] chore(changeset): add --- .changeset/twelve-lamps-fix.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/twelve-lamps-fix.md diff --git a/.changeset/twelve-lamps-fix.md b/.changeset/twelve-lamps-fix.md new file mode 100644 index 00000000..3dc84a16 --- /dev/null +++ b/.changeset/twelve-lamps-fix.md @@ -0,0 +1,6 @@ +--- +'@reactflow/minimap': patch +'reactflow': patch +--- + +Fix minimap node position From 780710da24307346b31114475d124ebeba5929ff Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 28 Nov 2022 21:15:17 +0100 Subject: [PATCH 17/19] chore(packages): bump --- .changeset/twelve-lamps-fix.md | 6 ------ examples/vite-app/package.json | 2 +- packages/minimap/CHANGELOG.md | 6 ++++++ packages/minimap/package.json | 2 +- packages/reactflow/CHANGELOG.md | 9 +++++++++ packages/reactflow/package.json | 2 +- 6 files changed, 18 insertions(+), 9 deletions(-) delete mode 100644 .changeset/twelve-lamps-fix.md diff --git a/.changeset/twelve-lamps-fix.md b/.changeset/twelve-lamps-fix.md deleted file mode 100644 index 3dc84a16..00000000 --- a/.changeset/twelve-lamps-fix.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@reactflow/minimap': patch -'reactflow': patch ---- - -Fix minimap node position diff --git a/examples/vite-app/package.json b/examples/vite-app/package.json index cf31055e..677f7289 100644 --- a/examples/vite-app/package.json +++ b/examples/vite-app/package.json @@ -1,7 +1,7 @@ { "name": "@reactflow/examples", "private": true, - "version": "0.0.1", + "version": "0.0.0", "type": "module", "scripts": { "dev": "vite --port 3000 --open", diff --git a/packages/minimap/CHANGELOG.md b/packages/minimap/CHANGELOG.md index 36a8f029..bcefc201 100644 --- a/packages/minimap/CHANGELOG.md +++ b/packages/minimap/CHANGELOG.md @@ -1,5 +1,11 @@ # @reactflow/minimap +## 11.2.2 + +### Patch Changes + +- [`7ece618d`](https://github.com/wbkd/react-flow/commit/7ece618d94b76183c1ecd45b16f6ab168168351b) Thanks [@](https://github.com/lounsbrough)! - Fix minimap node position + ## 11.2.1 ### Patch Changes diff --git a/packages/minimap/package.json b/packages/minimap/package.json index e2b66d07..d6dc1331 100644 --- a/packages/minimap/package.json +++ b/packages/minimap/package.json @@ -1,6 +1,6 @@ { "name": "@reactflow/minimap", - "version": "11.2.1", + "version": "11.2.2", "description": "Minimap component for React Flow.", "keywords": [ "react", diff --git a/packages/reactflow/CHANGELOG.md b/packages/reactflow/CHANGELOG.md index ea6e9a15..165c85c6 100644 --- a/packages/reactflow/CHANGELOG.md +++ b/packages/reactflow/CHANGELOG.md @@ -1,5 +1,14 @@ # reactflow +## 11.3.2 + +### Patch Changes + +- [`7ece618d`](https://github.com/wbkd/react-flow/commit/7ece618d94b76183c1ecd45b16f6ab168168351b) Thanks [@](https://github.com/lounsbrough)! - Fix minimap node position + +- Updated dependencies [[`7ece618d`](https://github.com/wbkd/react-flow/commit/7ece618d94b76183c1ecd45b16f6ab168168351b)]: + - @reactflow/minimap@11.2.2 + ## 11.3.1 ### Patch Changes diff --git a/packages/reactflow/package.json b/packages/reactflow/package.json index 9449f8ba..f84f948a 100644 --- a/packages/reactflow/package.json +++ b/packages/reactflow/package.json @@ -1,6 +1,6 @@ { "name": "reactflow", - "version": "11.3.1", + "version": "11.3.2", "description": "A highly customizable React library for building node-based editors and interactive flow charts", "keywords": [ "react", From 983893b7f1d26bb9f92762f1045486dfc248eb4d Mon Sep 17 00:00:00 2001 From: Moritz Klack Date: Mon, 28 Nov 2022 21:21:51 +0100 Subject: [PATCH 18/19] Update CHANGELOG.md --- packages/reactflow/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/reactflow/CHANGELOG.md b/packages/reactflow/CHANGELOG.md index 165c85c6..f3141ce1 100644 --- a/packages/reactflow/CHANGELOG.md +++ b/packages/reactflow/CHANGELOG.md @@ -4,7 +4,7 @@ ### Patch Changes -- [`7ece618d`](https://github.com/wbkd/react-flow/commit/7ece618d94b76183c1ecd45b16f6ab168168351b) Thanks [@](https://github.com/lounsbrough)! - Fix minimap node position +- [`7ece618d`](https://github.com/wbkd/react-flow/commit/7ece618d94b76183c1ecd45b16f6ab168168351b) Thanks [@lounsbrough](https://github.com/lounsbrough)! - Fix minimap node position - Updated dependencies [[`7ece618d`](https://github.com/wbkd/react-flow/commit/7ece618d94b76183c1ecd45b16f6ab168168351b)]: - @reactflow/minimap@11.2.2 From 6526e3297e67c57c2e9be0654be3792c6cc04483 Mon Sep 17 00:00:00 2001 From: Moritz Klack Date: Mon, 28 Nov 2022 21:22:09 +0100 Subject: [PATCH 19/19] Update CHANGELOG.md --- packages/minimap/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/minimap/CHANGELOG.md b/packages/minimap/CHANGELOG.md index bcefc201..b9cbb0be 100644 --- a/packages/minimap/CHANGELOG.md +++ b/packages/minimap/CHANGELOG.md @@ -4,7 +4,7 @@ ### Patch Changes -- [`7ece618d`](https://github.com/wbkd/react-flow/commit/7ece618d94b76183c1ecd45b16f6ab168168351b) Thanks [@](https://github.com/lounsbrough)! - Fix minimap node position +- [`7ece618d`](https://github.com/wbkd/react-flow/commit/7ece618d94b76183c1ecd45b16f6ab168168351b) Thanks [@lounsbrough](https://github.com/lounsbrough)! - Fix minimap node position ## 11.2.1