diff --git a/examples/vite-app/src/examples/EasyConnect/CustomNode.tsx b/examples/vite-app/src/examples/EasyConnect/CustomNode.tsx
index 989df5fa..bd107c93 100644
--- a/examples/vite-app/src/examples/EasyConnect/CustomNode.tsx
+++ b/examples/vite-app/src/examples/EasyConnect/CustomNode.tsx
@@ -2,8 +2,9 @@ import { Handle, NodeProps, Position, ReactFlowState, useStore } from 'reactflow
const connectionNodeIdSelector = (state: ReactFlowState) => state.connectionNodeId;
-export default function CustomNode({ id, isConnectable }: NodeProps) {
+export default function CustomNode({ id }: NodeProps) {
const connectionNodeId = useStore(connectionNodeIdSelector);
+ const isConnecting = !!connectionNodeId;
const isTarget = connectionNodeId && connectionNodeId !== id;
const targetHandleStyle = { zIndex: isTarget ? 3 : 1 };
@@ -18,19 +19,16 @@ export default function CustomNode({ id, isConnectable }: NodeProps) {
backgroundColor: isTarget ? '#ffcce3' : '#ccd9f6',
}}
>
+ {!isConnecting && (
+
+ )}
+
-
{label}
diff --git a/examples/vite-app/src/examples/EasyConnect/style.css b/examples/vite-app/src/examples/EasyConnect/style.css
index c2ebc0a2..8e06c4ea 100644
--- a/examples/vite-app/src/examples/EasyConnect/style.css
+++ b/examples/vite-app/src/examples/EasyConnect/style.css
@@ -28,19 +28,7 @@
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 {
+div.customHandle {
width: 100%;
height: 100%;
background: blue;
diff --git a/examples/vite-app/src/examples/Edges/CustomEdge.tsx b/examples/vite-app/src/examples/Edges/CustomEdge.tsx
index ec7dfb74..ff700413 100644
--- a/examples/vite-app/src/examples/Edges/CustomEdge.tsx
+++ b/examples/vite-app/src/examples/Edges/CustomEdge.tsx
@@ -1,5 +1,5 @@
import { FC } from 'react';
-import { EdgeProps, getBezierPath } from 'reactflow';
+import { BaseEdge, EdgeProps, getBezierPath } from 'reactflow';
const CustomEdge: FC = ({
id,
@@ -22,7 +22,7 @@ const CustomEdge: FC = ({
return (
<>
-
+
{data.text}
diff --git a/examples/vite-app/src/examples/Edges/CustomEdge2.tsx b/examples/vite-app/src/examples/Edges/CustomEdge2.tsx
index 0ad41920..b40f12cb 100644
--- a/examples/vite-app/src/examples/Edges/CustomEdge2.tsx
+++ b/examples/vite-app/src/examples/Edges/CustomEdge2.tsx
@@ -1,5 +1,5 @@
import { FC } from 'react';
-import { EdgeProps, getBezierPath, EdgeText } from 'reactflow';
+import { EdgeProps, getBezierPath, EdgeText, BaseEdge } from 'reactflow';
const CustomEdge: FC = ({
id,
@@ -22,7 +22,7 @@ const CustomEdge: FC = ({
return (
<>
-
+
= ({
labelBgBorderRadius={2}
onClick={() => console.log(data)}
/>
- ;
>
);
};
diff --git a/examples/vite-app/src/examples/NodeToolbar/CustomNode.tsx b/examples/vite-app/src/examples/NodeToolbar/CustomNode.tsx
index ca2ac0b7..7d179b7e 100644
--- a/examples/vite-app/src/examples/NodeToolbar/CustomNode.tsx
+++ b/examples/vite-app/src/examples/NodeToolbar/CustomNode.tsx
@@ -4,7 +4,7 @@ import { Handle, Position, NodeProps, NodeToolbar } from 'reactflow';
const CustomNode: FC = ({ id, data }) => {
return (
<>
-
+
diff --git a/examples/vite-app/src/examples/NodeToolbar/index.tsx b/examples/vite-app/src/examples/NodeToolbar/index.tsx
index 601d8618..b4d3d1c5 100644
--- a/examples/vite-app/src/examples/NodeToolbar/index.tsx
+++ b/examples/vite-app/src/examples/NodeToolbar/index.tsx
@@ -17,49 +17,38 @@ const nodeTypes: NodeTypes = {
custom: CustomNode,
};
+const positions = ['top', 'right', 'bottom', 'left'];
+const alignments = ['start', 'center', 'end'];
+
const initialNodes: Node[] = [
- {
- id: '1',
- type: 'custom',
- data: { label: 'toolbar top', toolbarPosition: Position.Top },
- position: { x: 0, y: 50 },
- className: 'react-flow__node-default',
- },
- {
- id: '2',
- type: 'custom',
- data: { label: 'toolbar right', toolbarPosition: Position.Right },
- position: { x: 300, y: 0 },
- className: 'react-flow__node-default',
- },
- {
- id: '3',
- type: 'custom',
- data: { label: 'toolbar bottom', toolbarPosition: Position.Bottom },
- position: { x: 400, y: 100 },
- className: 'react-flow__node-default',
- },
{
id: '4',
type: 'custom',
- data: { label: 'toolbar left', toolbarPosition: Position.Left },
- position: { x: 400, y: 200 },
- className: 'react-flow__node-default',
- },
- {
- id: '5',
- type: 'custom',
- data: { label: 'toolbar always open', toolbarPosition: Position.Top, toolbarVisible: true },
- position: { x: 0, y: 200 },
+ data: { label: 'toolbar top', toolbarPosition: Position.Top },
+ position: { x: 0, y: -200 },
className: 'react-flow__node-default',
},
];
-const initialEdges: Edge[] = [
- { id: 'e1-2', source: '1', target: '2' },
- { id: 'e1-3', source: '1', target: '3' },
- { id: 'e1-4', source: '1', target: '4' },
-];
+positions.forEach((position, posIndex) => {
+ alignments.forEach((align, alignIndex) => {
+ const id = `node-${align}-${position}`;
+ initialNodes.push({
+ id,
+ type: 'custom',
+ data: {
+ label: `toolbar ${position} ${align}`,
+ toolbarPosition: position as Position,
+ toolbarAlign: align,
+ toolbarVisible: true,
+ },
+ className: 'react-flow__node-default',
+ position: { x: posIndex * 300, y: alignIndex * 100 },
+ });
+ });
+});
+
+const initialEdges: Edge[] = [];
const defaultEdgeOptions = { zIndex: 0 };
const nodeOrigin: NodeOrigin = [0.5, 0.5];
diff --git a/packages/background/CHANGELOG.md b/packages/background/CHANGELOG.md
index 60978e3d..d5b1691f 100644
--- a/packages/background/CHANGELOG.md
+++ b/packages/background/CHANGELOG.md
@@ -1,5 +1,12 @@
# @reactflow/background
+## 11.2.1
+
+### Patch Changes
+
+- Updated dependencies [[`cf7a7d3d`](https://github.com/wbkd/react-flow/commit/cf7a7d3dad1e73215a72a5dc72e21fd50208cdbb), [`07b975bb`](https://github.com/wbkd/react-flow/commit/07b975bbee3580249e36a19582213b250f78093c), [`c80d269b`](https://github.com/wbkd/react-flow/commit/c80d269b85a0054221f4639c328fc36a3befbe70), [`a3fa164c`](https://github.com/wbkd/react-flow/commit/a3fa164c34cc820c79bb031c9fd97b72a3546614)]:
+ - @reactflow/core@11.7.1
+
## 11.2.0
### Minor Changes
diff --git a/packages/background/package.json b/packages/background/package.json
index 6f378c30..3f2bb0a2 100644
--- a/packages/background/package.json
+++ b/packages/background/package.json
@@ -1,6 +1,6 @@
{
"name": "@reactflow/background",
- "version": "11.2.0",
+ "version": "11.2.1",
"description": "Background component with different variants for React Flow",
"keywords": [
"react",
diff --git a/packages/controls/CHANGELOG.md b/packages/controls/CHANGELOG.md
index e4815ed6..31a54565 100644
--- a/packages/controls/CHANGELOG.md
+++ b/packages/controls/CHANGELOG.md
@@ -1,5 +1,14 @@
# @reactflow/controls
+## 11.1.12
+
+### Patch Changes
+
+- [#3054](https://github.com/wbkd/react-flow/pull/3054) [`46526b4e`](https://github.com/wbkd/react-flow/commit/46526b4e02b83d74726701e3ba73d0be8cf80787) - fix(icons): show correct lock icon
+
+- Updated dependencies [[`cf7a7d3d`](https://github.com/wbkd/react-flow/commit/cf7a7d3dad1e73215a72a5dc72e21fd50208cdbb), [`07b975bb`](https://github.com/wbkd/react-flow/commit/07b975bbee3580249e36a19582213b250f78093c), [`c80d269b`](https://github.com/wbkd/react-flow/commit/c80d269b85a0054221f4639c328fc36a3befbe70), [`a3fa164c`](https://github.com/wbkd/react-flow/commit/a3fa164c34cc820c79bb031c9fd97b72a3546614)]:
+ - @reactflow/core@11.7.1
+
## 11.1.11
### Patch Changes
diff --git a/packages/controls/package.json b/packages/controls/package.json
index 777fbd6c..271d2967 100644
--- a/packages/controls/package.json
+++ b/packages/controls/package.json
@@ -1,6 +1,6 @@
{
"name": "@reactflow/controls",
- "version": "11.1.11",
+ "version": "11.1.12",
"description": "Component to control the viewport of a React Flow instance",
"keywords": [
"react",
diff --git a/packages/controls/src/Controls.tsx b/packages/controls/src/Controls.tsx
index 73234606..7c529a9e 100644
--- a/packages/controls/src/Controls.tsx
+++ b/packages/controls/src/Controls.tsx
@@ -1,8 +1,6 @@
-import { memo, useEffect, useState } from 'react';
-import type { FC, PropsWithChildren } from 'react';
+import { memo, useEffect, useState, type FC, type PropsWithChildren } from 'react';
import cc from 'classcat';
-import { useStore, useStoreApi, useReactFlow, Panel } from '@reactflow/core';
-import type { ReactFlowState } from '@reactflow/core';
+import { useStore, useStoreApi, useReactFlow, Panel, type ReactFlowState } from '@reactflow/core';
import PlusIcon from './Icons/Plus';
import MinusIcon from './Icons/Minus';
@@ -13,7 +11,7 @@ import ControlButton from './ControlButton';
import type { ControlProps } from './types';
-const isInteractiveSelector = (s: ReactFlowState) => s.nodesDraggable && s.nodesConnectable && s.elementsSelectable;
+const isInteractiveSelector = (s: ReactFlowState) => s.nodesDraggable || s.nodesConnectable || s.elementsSelectable;
const Controls: FC> = ({
style,
diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md
index 576d20ab..6c1b6932 100644
--- a/packages/core/CHANGELOG.md
+++ b/packages/core/CHANGELOG.md
@@ -1,12 +1,21 @@
# @reactflow/core
+## 11.7.1
+
+### Patch Changes
+
+- [#3043](https://github.com/wbkd/react-flow/pull/3043) [`cf7a7d3d`](https://github.com/wbkd/react-flow/commit/cf7a7d3dad1e73215a72a5dc72e21fd50208cdbb) - handles: handles on top of each other, reduce re-renderings
+- [#3046](https://github.com/wbkd/react-flow/pull/3046) [`07b975bb`](https://github.com/wbkd/react-flow/commit/07b975bbee3580249e36a19582213b250f78093c) - base-edge: pass id to base edge path
+- [#3007](https://github.com/wbkd/react-flow/pull/3007) [`c80d269b`](https://github.com/wbkd/react-flow/commit/c80d269b85a0054221f4639c328fc36a3befbe70) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - allow array of ids as updateNodeInternals arg
+- [#3029](https://github.com/wbkd/react-flow/pull/3029) [`a3fa164c`](https://github.com/wbkd/react-flow/commit/a3fa164c34cc820c79bb031c9fd97b72a3546614) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - autopan: only update nodes when transform change happen
+
## 11.7.0
Most notable updates:
- Handles: `isConnectableStart` and `isConnectableEnd` props to configure if you can start or end a connection at a certain handle
- Edges: `updatable` option to enable updates for specific edges
-- useNodesInitialized: options to configure if hidden nodes should be included (false by default)
+- useNodesInitialized: options to configure if hidden nodes should be included (false by default)
### Minor Changes
@@ -20,7 +29,6 @@ Most notable updates:
- [#2933](https://github.com/wbkd/react-flow/pull/2933) [`fe8cac0a`](https://github.com/wbkd/react-flow/commit/fe8cac0adb359109e0e9eafe8b9261ba354076bb) - prefix error keys with "error"
- [#2939](https://github.com/wbkd/react-flow/pull/2939) [`4a4ca171`](https://github.com/wbkd/react-flow/commit/4a4ca171955f5c8d58b23e3ad48406f1a21dc402) - add connection result to store
-
## 11.6.1
### Patch Changes
diff --git a/packages/core/package.json b/packages/core/package.json
index bc4e0b59..632b2cee 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@reactflow/core",
- "version": "11.7.0",
+ "version": "11.7.1",
"description": "Core components and util functions of React Flow.",
"keywords": [
"react",
diff --git a/packages/core/src/components/Edges/BaseEdge.tsx b/packages/core/src/components/Edges/BaseEdge.tsx
index dc60493c..a9202820 100644
--- a/packages/core/src/components/Edges/BaseEdge.tsx
+++ b/packages/core/src/components/Edges/BaseEdge.tsx
@@ -3,6 +3,7 @@ import { isNumeric } from '../../utils';
import type { BaseEdgeProps } from '../../types';
const BaseEdge = ({
+ id,
path,
labelX,
labelY,
@@ -20,6 +21,7 @@ const BaseEdge = ({
return (
<>
(
const store = useStoreApi();
const nodeId = useNodeId();
const { connectOnClick, noPanClassName } = useStore(selector, shallow);
- const { connecting, clickConnecting } = useStore(connectingSelector(nodeId, handleId, type));
+ const { connecting, clickConnecting } = useStore(connectingSelector(nodeId, handleId, type), shallow);
if (!nodeId) {
store.getState().onError?.('010', errorMessages['error010']());
diff --git a/packages/core/src/components/Handle/utils.ts b/packages/core/src/components/Handle/utils.ts
index b8e8cf6a..353b249a 100644
--- a/packages/core/src/components/Handle/utils.ts
+++ b/packages/core/src/components/Handle/utils.ts
@@ -41,18 +41,30 @@ export function getClosestHandle(
connectionRadius: number,
handles: ConnectionHandle[]
): ConnectionHandle | null {
- let closestHandle: ConnectionHandle | null = null;
+ let closestHandles: ConnectionHandle[] = [];
let minDistance = Infinity;
handles.forEach((handle) => {
const distance = Math.sqrt(Math.pow(handle.x - pos.x, 2) + Math.pow(handle.y - pos.y, 2));
- if (distance <= connectionRadius && distance < minDistance) {
+ if (distance <= connectionRadius) {
+ if (distance < minDistance) {
+ closestHandles = [handle];
+ } else if (distance === minDistance) {
+ // when multiple handles are on the same distance we collect all of them
+ closestHandles.push(handle);
+ }
minDistance = distance;
- closestHandle = handle;
}
});
- return closestHandle;
+ if (!closestHandles.length) {
+ return null;
+ }
+
+ return closestHandles.length === 1
+ ? closestHandles[0]
+ : // if multiple handles are layouted on top of each other we take the one with type = target because it's more likely that the user wants to connect to this one
+ closestHandles.find((handle) => handle.type === 'target') || closestHandles[0];
}
type Result = {
@@ -81,6 +93,8 @@ export function isValidHandle(
);
const { x, y } = getEventPosition(event);
const handleBelow = doc.elementFromPoint(x, y);
+ // we always want to prioritize the handle below the mouse cursor over the closest distance handle,
+ // because it could be that the center of another handle is closer to the mouse pointer than the handle below the cursor
const handleToCheck = handleBelow?.classList.contains('react-flow__handle') ? handleBelow : handleDomNode;
const result: Result = {
diff --git a/packages/core/src/hooks/useDrag/index.ts b/packages/core/src/hooks/useDrag/index.ts
index 8821ab4a..346828fb 100644
--- a/packages/core/src/hooks/useDrag/index.ts
+++ b/packages/core/src/hooks/useDrag/index.ts
@@ -119,8 +119,9 @@ function useDrag({
lastPos.current.x = (lastPos.current.x ?? 0) - xMovement / transform[2];
lastPos.current.y = (lastPos.current.y ?? 0) - yMovement / transform[2];
- updateNodes(lastPos.current as XYPosition);
- panBy({ x: xMovement, y: yMovement });
+ if (panBy({ x: xMovement, y: yMovement })) {
+ updateNodes(lastPos.current as XYPosition);
+ }
}
autoPanId.current = requestAnimationFrame(autoPan);
};
diff --git a/packages/core/src/hooks/useUpdateNodeInternals.ts b/packages/core/src/hooks/useUpdateNodeInternals.ts
index 849d76b6..9786c65c 100644
--- a/packages/core/src/hooks/useUpdateNodeInternals.ts
+++ b/packages/core/src/hooks/useUpdateNodeInternals.ts
@@ -6,13 +6,20 @@ import type { UpdateNodeInternals } from '../types';
function useUpdateNodeInternals(): UpdateNodeInternals {
const store = useStoreApi();
- return useCallback((id: string) => {
+ return useCallback((id: string | string[]) => {
const { domNode, updateNodeDimensions } = store.getState();
- const nodeElement = domNode?.querySelector(`.react-flow__node[data-id="${id}"]`) as HTMLDivElement;
- if (nodeElement) {
- requestAnimationFrame(() => updateNodeDimensions([{ id, nodeElement, forceUpdate: true }]));
- }
+ const updateIds = Array.isArray(id) ? id : [id];
+
+ requestAnimationFrame(() => {
+ updateIds.forEach((updateId) => {
+ const nodeElement = domNode?.querySelector(`.react-flow__node[data-id="${updateId}"]`) as HTMLDivElement;
+
+ if (nodeElement) {
+ updateNodeDimensions([{ id: updateId, nodeElement, forceUpdate: true }]);
+ }
+ });
+ });
}, []);
}
diff --git a/packages/core/src/store/index.ts b/packages/core/src/store/index.ts
index f4365d45..5c152969 100644
--- a/packages/core/src/store/index.ts
+++ b/packages/core/src/store/index.ts
@@ -252,11 +252,11 @@ const createRFStore = () =>
nodeInternals: new Map(nodeInternals),
});
},
- panBy: (delta: XYPosition) => {
+ panBy: (delta: XYPosition): boolean => {
const { transform, width, height, d3Zoom, d3Selection, translateExtent } = get();
if (!d3Zoom || !d3Selection || (!delta.x && !delta.y)) {
- return;
+ return false;
}
const nextTransform = zoomIdentity.translate(transform[0] + delta.x, transform[1] + delta.y).scale(transform[2]);
@@ -268,6 +268,13 @@ const createRFStore = () =>
const constrainedTransform = d3Zoom?.constrain()(nextTransform, extent, translateExtent);
d3Zoom.transform(d3Selection, constrainedTransform);
+
+ const transformChanged =
+ transform[0] !== constrainedTransform.x ||
+ transform[1] !== constrainedTransform.y ||
+ transform[2] !== constrainedTransform.k;
+
+ return transformChanged;
},
cancelConnection: () =>
set({
diff --git a/packages/core/src/types/edges.ts b/packages/core/src/types/edges.ts
index 7358b0e8..1899dcc5 100644
--- a/packages/core/src/types/edges.ts
+++ b/packages/core/src/types/edges.ts
@@ -121,6 +121,7 @@ export type EdgeProps = Pick<
export type BaseEdgeProps = Pick &
EdgeLabelOptions & {
+ id?: string;
labelX?: number;
labelY?: number;
path: string;
diff --git a/packages/core/src/types/general.ts b/packages/core/src/types/general.ts
index f57a1ea7..9803d4a0 100644
--- a/packages/core/src/types/general.ts
+++ b/packages/core/src/types/general.ts
@@ -252,7 +252,7 @@ export type ReactFlowActions = {
cancelConnection: () => void;
reset: () => void;
triggerNodeChanges: (changes: NodeChange[]) => void;
- panBy: (delta: XYPosition) => void;
+ panBy: (delta: XYPosition) => boolean;
};
export type ReactFlowState = ReactFlowStore & ReactFlowActions;
diff --git a/packages/minimap/CHANGELOG.md b/packages/minimap/CHANGELOG.md
index 3b2f9d44..3a2ade73 100644
--- a/packages/minimap/CHANGELOG.md
+++ b/packages/minimap/CHANGELOG.md
@@ -1,5 +1,12 @@
# @reactflow/minimap
+## 11.5.1
+
+### Patch Changes
+
+- Updated dependencies [[`cf7a7d3d`](https://github.com/wbkd/react-flow/commit/cf7a7d3dad1e73215a72a5dc72e21fd50208cdbb), [`07b975bb`](https://github.com/wbkd/react-flow/commit/07b975bbee3580249e36a19582213b250f78093c), [`c80d269b`](https://github.com/wbkd/react-flow/commit/c80d269b85a0054221f4639c328fc36a3befbe70), [`a3fa164c`](https://github.com/wbkd/react-flow/commit/a3fa164c34cc820c79bb031c9fd97b72a3546614)]:
+ - @reactflow/core@11.7.1
+
## 11.5.0
### Minor Changes
diff --git a/packages/minimap/package.json b/packages/minimap/package.json
index e0766dab..db5861b6 100644
--- a/packages/minimap/package.json
+++ b/packages/minimap/package.json
@@ -1,6 +1,6 @@
{
"name": "@reactflow/minimap",
- "version": "11.5.0",
+ "version": "11.5.1",
"description": "Minimap component for React Flow.",
"keywords": [
"react",
diff --git a/packages/node-toolbar/CHANGELOG.md b/packages/node-toolbar/CHANGELOG.md
index e5fce14b..5298148d 100644
--- a/packages/node-toolbar/CHANGELOG.md
+++ b/packages/node-toolbar/CHANGELOG.md
@@ -1,5 +1,16 @@
# @reactflow/node-toolbar
+## 1.2.0
+
+### Minor Changes
+
+- [#3052](https://github.com/wbkd/react-flow/pull/3052) [`55e05cf7`](https://github.com/wbkd/react-flow/commit/55e05cf76ae21863691153e76dbd51d1eecd2c60) Thanks [@Noam3kCH](https://github.com/Noam3kCH)! - feat(align): add prop to align bar at start, center or end
+
+### Patch Changes
+
+- Updated dependencies [[`cf7a7d3d`](https://github.com/wbkd/react-flow/commit/cf7a7d3dad1e73215a72a5dc72e21fd50208cdbb), [`07b975bb`](https://github.com/wbkd/react-flow/commit/07b975bbee3580249e36a19582213b250f78093c), [`c80d269b`](https://github.com/wbkd/react-flow/commit/c80d269b85a0054221f4639c328fc36a3befbe70), [`a3fa164c`](https://github.com/wbkd/react-flow/commit/a3fa164c34cc820c79bb031c9fd97b72a3546614)]:
+ - @reactflow/core@11.7.1
+
## 1.1.11
### Patch Changes
diff --git a/packages/node-toolbar/package.json b/packages/node-toolbar/package.json
index 71dad7ca..b0e2d3f7 100644
--- a/packages/node-toolbar/package.json
+++ b/packages/node-toolbar/package.json
@@ -1,6 +1,6 @@
{
"name": "@reactflow/node-toolbar",
- "version": "1.1.11",
+ "version": "1.2.0",
"description": "A toolbar component for React Flow that can be attached to a node.",
"keywords": [
"react",
diff --git a/packages/node-toolbar/src/NodeToolbar.tsx b/packages/node-toolbar/src/NodeToolbar.tsx
index 428708da..3b02b8bf 100644
--- a/packages/node-toolbar/src/NodeToolbar.tsx
+++ b/packages/node-toolbar/src/NodeToolbar.tsx
@@ -14,7 +14,7 @@ import cc from 'classcat';
import { shallow } from 'zustand/shallow';
import NodeToolbarPortal from './NodeToolbarPortal';
-import { NodeToolbarProps } from './types';
+import { Align, NodeToolbarProps } from './types';
const nodeEqualityFn = (a: Node | undefined, b: Node | undefined) =>
a?.positionAbsolute?.x === b?.positionAbsolute?.x &&
@@ -34,33 +34,46 @@ const storeSelector = (state: ReactFlowState) => ({
selectedNodesCount: state.getNodes().filter((node) => node.selected).length,
});
-function getTransform(nodeRect: Rect, transform: Transform, position: Position, offset: number): string {
+function getTransform(nodeRect: Rect, transform: Transform, position: Position, offset: number, align: Align): string {
+ let alignmentOffset = 0.5;
+
+ if (align === 'start') {
+ alignmentOffset = 0;
+ } else if (align === 'end') {
+ alignmentOffset = 1;
+ }
+
// position === Position.Top
- let xPos = (nodeRect.x + nodeRect.width / 2) * transform[2] + transform[0];
- let yPos = nodeRect.y * transform[2] + transform[1] - offset;
- let xShift = -50;
- let yShift = -100;
+ // we set the x any y position of the toolbar based on the nodes position
+ let pos = [
+ (nodeRect.x + nodeRect.width * alignmentOffset) * transform[2] + transform[0],
+ nodeRect.y * transform[2] + transform[1] - offset,
+ ];
+ // and than shift it based on the alignment. The shift values are in %.
+ let shift = [-100 * alignmentOffset, -100];
switch (position) {
case Position.Right:
- xPos = (nodeRect.x + nodeRect.width) * transform[2] + transform[0] + offset;
- yPos = (nodeRect.y + nodeRect.height / 2) * transform[2] + transform[1];
- xShift = 0;
- yShift = -50;
+ pos = [
+ (nodeRect.x + nodeRect.width) * transform[2] + transform[0] + offset,
+ (nodeRect.y + nodeRect.height * alignmentOffset) * transform[2] + transform[1],
+ ];
+ shift = [0, -100 * alignmentOffset];
break;
case Position.Bottom:
- yPos = (nodeRect.y + nodeRect.height) * transform[2] + transform[1] + offset;
- yShift = 0;
+ pos[1] = (nodeRect.y + nodeRect.height) * transform[2] + transform[1] + offset;
+ shift[1] = 0;
break;
case Position.Left:
- xPos = nodeRect.x * transform[2] + transform[0] - offset;
- yPos = (nodeRect.y + nodeRect.height / 2) * transform[2] + transform[1];
- xShift = -100;
- yShift = -50;
+ pos = [
+ nodeRect.x * transform[2] + transform[0] - offset,
+ (nodeRect.y + nodeRect.height * alignmentOffset) * transform[2] + transform[1],
+ ];
+ shift = [-100, -100 * alignmentOffset];
break;
}
- return `translate(${xPos}px, ${yPos}px) translate(${xShift}%, ${yShift}%)`;
+ return `translate(${pos[0]}px, ${pos[1]}px) translate(${shift[0]}%, ${shift[1]}%)`;
}
function NodeToolbar({
@@ -71,6 +84,7 @@ function NodeToolbar({
isVisible,
position = Position.Top,
offset = 10,
+ align = 'center',
...rest
}: NodeToolbarProps) {
const contextNodeId = useNodeId();
@@ -103,7 +117,7 @@ function NodeToolbar({
const wrapperStyle: CSSProperties = {
position: 'absolute',
- transform: getTransform(nodeRect, transform, position, offset),
+ transform: getTransform(nodeRect, transform, position, offset, align),
zIndex,
...style,
};
diff --git a/packages/node-toolbar/src/types.ts b/packages/node-toolbar/src/types.ts
index e2b0d73c..7ff2087b 100644
--- a/packages/node-toolbar/src/types.ts
+++ b/packages/node-toolbar/src/types.ts
@@ -6,4 +6,7 @@ export type NodeToolbarProps = HTMLAttributes & {
isVisible?: boolean;
position?: Position;
offset?: number;
+ align?: Align;
};
+
+export type Align = 'center' | 'start' | 'end';
diff --git a/packages/reactflow/CHANGELOG.md b/packages/reactflow/CHANGELOG.md
index f5eebcf3..aa8a801b 100644
--- a/packages/reactflow/CHANGELOG.md
+++ b/packages/reactflow/CHANGELOG.md
@@ -1,5 +1,22 @@
# reactflow
+## 11.7.1
+
+### Patch Changes
+
+- [#3043](https://github.com/wbkd/react-flow/pull/3043) [`cf7a7d3d`](https://github.com/wbkd/react-flow/commit/cf7a7d3dad1e73215a72a5dc72e21fd50208cdbb) - handles: handles on top of each other, reduce re-renderings
+- [#3046](https://github.com/wbkd/react-flow/pull/3046) [`07b975bb`](https://github.com/wbkd/react-flow/commit/07b975bbee3580249e36a19582213b250f78093c) - base-edge: pass id to base edge path
+- [#3007](https://github.com/wbkd/react-flow/pull/3007) [`c80d269b`](https://github.com/wbkd/react-flow/commit/c80d269b85a0054221f4639c328fc36a3befbe70) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - allow array of ids as updateNodeInternals arg
+- [#3029](https://github.com/wbkd/react-flow/pull/3029) [`a3fa164c`](https://github.com/wbkd/react-flow/commit/a3fa164c34cc820c79bb031c9fd97b72a3546614) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - autopan: only update nodes when transform change happen
+- [#3052](https://github.com/wbkd/react-flow/pull/3052) [`55e05cf7`](https://github.com/wbkd/react-flow/commit/55e05cf76ae21863691153e76dbd51d1eecd2c60) Thanks [@Noam3kCH](https://github.com/Noam3kCH)! - node-toolbar: add prop to align bar at start, center or end
+
+- Updated dependencies [[`cf7a7d3d`](https://github.com/wbkd/react-flow/commit/cf7a7d3dad1e73215a72a5dc72e21fd50208cdbb), [`07b975bb`](https://github.com/wbkd/react-flow/commit/07b975bbee3580249e36a19582213b250f78093c), [`55e05cf7`](https://github.com/wbkd/react-flow/commit/55e05cf76ae21863691153e76dbd51d1eecd2c60), [`c80d269b`](https://github.com/wbkd/react-flow/commit/c80d269b85a0054221f4639c328fc36a3befbe70), [`46526b4e`](https://github.com/wbkd/react-flow/commit/46526b4e02b83d74726701e3ba73d0be8cf80787), [`a3fa164c`](https://github.com/wbkd/react-flow/commit/a3fa164c34cc820c79bb031c9fd97b72a3546614)]:
+ - @reactflow/core@11.7.1
+ - @reactflow/node-toolbar@1.2.0
+ - @reactflow/controls@11.1.12
+ - @reactflow/background@11.2.1
+ - @reactflow/minimap@11.5.1
+
## 11.7.0
Most notable updates:
@@ -9,7 +26,7 @@ Most notable updates:
- Edges: `updatable` option to enable updates for specific edges
- MiniMap: `inversePan` and `zoomStep` props
- Background: `id` and `offset` props - this enables you to combine different patterns (useful if you want a graph paper like background for example)
-- useNodesInitialized: options to configure if hidden nodes should be included (false by default)
+- useNodesInitialized: options to configure if hidden nodes should be included (false by default)
Big thanks to [@Elringus](https://github.com/Elringus) and [@bcakmakoglu](https://github.com/bcakmakoglu)!
@@ -22,14 +39,12 @@ Big thanks to [@Elringus](https://github.com/Elringus) and [@bcakmakoglu](https:
- [#2944](https://github.com/wbkd/react-flow/pull/2944) Thanks [@Elringus](https://github.com/Elringus)! - add `inversePan` and `zoomStep` props
- [#2941](https://github.com/wbkd/react-flow/pull/2941) Thanks [@Elringus](https://github.com/Elringus)! - background: add `id` and `offset` props
-
### Patch Changes
- [#2926](https://github.com/wbkd/react-flow/pull/2926) Thanks [@Elringus](https://github.com/Elringus)! - fix non-passive wheel event listener violation
- [#2933](https://github.com/wbkd/react-flow/pull/2933) [`fe8cac0a`](https://github.com/wbkd/react-flow/commit/fe8cac0adb359109e0e9eafe8b9261ba354076bb) - prefix error keys with "error"
- [#2939](https://github.com/wbkd/react-flow/pull/2939) [`4a4ca171`](https://github.com/wbkd/react-flow/commit/4a4ca171955f5c8d58b23e3ad48406f1a21dc402) - add connection result to store
-
### Patch Changes
- Updated dependencies [[`098eee3d`](https://github.com/wbkd/react-flow/commit/098eee3d41dabc870777b081796401ff13b5a776), [`fe8cac0a`](https://github.com/wbkd/react-flow/commit/fe8cac0adb359109e0e9eafe8b9261ba354076bb), [`4a4ca171`](https://github.com/wbkd/react-flow/commit/4a4ca171955f5c8d58b23e3ad48406f1a21dc402), [`c1448c2f`](https://github.com/wbkd/react-flow/commit/c1448c2f7415dd3b4b2c54e05404c5ab24e8978d), [`923a54c4`](https://github.com/wbkd/react-flow/commit/923a54c481b90954806202817ba844cfa7203a38), [`4d97a0ed`](https://github.com/wbkd/react-flow/commit/4d97a0ed168ce643fc0c99fa6b47cf1296d66065), [`771c7a5d`](https://github.com/wbkd/react-flow/commit/771c7a5d133ce96e9f7471394c15189e0657ce01), [`c22e1c28`](https://github.com/wbkd/react-flow/commit/c22e1c28c5555a638c2a8e82c3bfc986b3965d36)]:
diff --git a/packages/reactflow/package.json b/packages/reactflow/package.json
index ad4b8ed7..1cbab90d 100644
--- a/packages/reactflow/package.json
+++ b/packages/reactflow/package.json
@@ -1,6 +1,6 @@
{
"name": "reactflow",
- "version": "11.7.0",
+ "version": "11.7.1",
"description": "A highly customizable React library for building node-based editors and interactive flow charts",
"keywords": [
"react",