Merge pull request #3031 from wbkd/next-release

Next release
This commit is contained in:
Moritz Klack
2023-05-15 16:36:20 +02:00
committed by GitHub
30 changed files with 201 additions and 123 deletions
@@ -2,8 +2,9 @@ import { Handle, NodeProps, Position, ReactFlowState, useStore } from 'reactflow
const connectionNodeIdSelector = (state: ReactFlowState) => state.connectionNodeId; const connectionNodeIdSelector = (state: ReactFlowState) => state.connectionNodeId;
export default function CustomNode({ id, isConnectable }: NodeProps) { export default function CustomNode({ id }: NodeProps) {
const connectionNodeId = useStore(connectionNodeIdSelector); const connectionNodeId = useStore(connectionNodeIdSelector);
const isConnecting = !!connectionNodeId;
const isTarget = connectionNodeId && connectionNodeId !== id; const isTarget = connectionNodeId && connectionNodeId !== id;
const targetHandleStyle = { zIndex: isTarget ? 3 : 1 }; const targetHandleStyle = { zIndex: isTarget ? 3 : 1 };
@@ -18,19 +19,16 @@ export default function CustomNode({ id, isConnectable }: NodeProps) {
backgroundColor: isTarget ? '#ffcce3' : '#ccd9f6', backgroundColor: isTarget ? '#ffcce3' : '#ccd9f6',
}} }}
> >
{!isConnecting && (
<Handle className="customHandle" style={{ zIndex: 2 }} position={Position.Right} type="source" />
)}
<Handle <Handle
className="targetHandle" className="customHandle"
style={{ zIndex: 2 }}
position={Position.Right}
type="source"
isConnectable={isConnectable}
/>
<Handle
className="targetHandle"
style={targetHandleStyle} style={targetHandleStyle}
position={Position.Left} position={Position.Left}
type="target" type="target"
isConnectable={isConnectable} isConnectableStart={false}
/> />
{label} {label}
</div> </div>
@@ -28,19 +28,7 @@
border: 2px solid #222138; border: 2px solid #222138;
} }
div.sourceHandle { div.customHandle {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
border-radius: 0;
transform: none;
border: none;
opacity: 0;
}
div.targetHandle {
width: 100%; width: 100%;
height: 100%; height: 100%;
background: blue; background: blue;
@@ -1,5 +1,5 @@
import { FC } from 'react'; import { FC } from 'react';
import { EdgeProps, getBezierPath } from 'reactflow'; import { BaseEdge, EdgeProps, getBezierPath } from 'reactflow';
const CustomEdge: FC<EdgeProps> = ({ const CustomEdge: FC<EdgeProps> = ({
id, id,
@@ -22,7 +22,7 @@ const CustomEdge: FC<EdgeProps> = ({
return ( return (
<> <>
<path id={id} className="react-flow__edge-path" d={edgePath} /> <BaseEdge path={edgePath} id={id} />
<text> <text>
<textPath href={`#${id}`} style={{ fontSize: '12px' }} startOffset="50%" textAnchor="middle"> <textPath href={`#${id}`} style={{ fontSize: '12px' }} startOffset="50%" textAnchor="middle">
{data.text} {data.text}
@@ -1,5 +1,5 @@
import { FC } from 'react'; import { FC } from 'react';
import { EdgeProps, getBezierPath, EdgeText } from 'reactflow'; import { EdgeProps, getBezierPath, EdgeText, BaseEdge } from 'reactflow';
const CustomEdge: FC<EdgeProps> = ({ const CustomEdge: FC<EdgeProps> = ({
id, id,
@@ -22,7 +22,7 @@ const CustomEdge: FC<EdgeProps> = ({
return ( return (
<> <>
<path id={id} className="react-flow__edge-path" d={edgePath} /> <BaseEdge id={id} path={edgePath} />
<EdgeText <EdgeText
x={labelX} x={labelX}
y={labelY} y={labelY}
@@ -34,7 +34,6 @@ const CustomEdge: FC<EdgeProps> = ({
labelBgBorderRadius={2} labelBgBorderRadius={2}
onClick={() => console.log(data)} onClick={() => console.log(data)}
/> />
;
</> </>
); );
}; };
@@ -4,7 +4,7 @@ import { Handle, Position, NodeProps, NodeToolbar } from 'reactflow';
const CustomNode: FC<NodeProps> = ({ id, data }) => { const CustomNode: FC<NodeProps> = ({ id, data }) => {
return ( return (
<> <>
<NodeToolbar isVisible={data.toolbarVisible} position={data.toolbarPosition}> <NodeToolbar isVisible={data.toolbarVisible} position={data.toolbarPosition} align={data.toolbarAlign}>
<button>delete</button> <button>delete</button>
<button>copy</button> <button>copy</button>
<button>expand</button> <button>expand</button>
@@ -17,49 +17,38 @@ const nodeTypes: NodeTypes = {
custom: CustomNode, custom: CustomNode,
}; };
const positions = ['top', 'right', 'bottom', 'left'];
const alignments = ['start', 'center', 'end'];
const initialNodes: Node[] = [ 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', id: '4',
type: 'custom', type: 'custom',
data: { label: 'toolbar left', toolbarPosition: Position.Left }, data: { label: 'toolbar top', toolbarPosition: Position.Top },
position: { x: 400, y: 200 }, position: { x: 0, 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 },
className: 'react-flow__node-default', className: 'react-flow__node-default',
}, },
]; ];
const initialEdges: Edge[] = [ positions.forEach((position, posIndex) => {
{ id: 'e1-2', source: '1', target: '2' }, alignments.forEach((align, alignIndex) => {
{ id: 'e1-3', source: '1', target: '3' }, const id = `node-${align}-${position}`;
{ id: 'e1-4', source: '1', target: '4' }, 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 defaultEdgeOptions = { zIndex: 0 };
const nodeOrigin: NodeOrigin = [0.5, 0.5]; const nodeOrigin: NodeOrigin = [0.5, 0.5];
+7
View File
@@ -1,5 +1,12 @@
# @reactflow/background # @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 ## 11.2.0
### Minor Changes ### Minor Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@reactflow/background", "name": "@reactflow/background",
"version": "11.2.0", "version": "11.2.1",
"description": "Background component with different variants for React Flow", "description": "Background component with different variants for React Flow",
"keywords": [ "keywords": [
"react", "react",
+9
View File
@@ -1,5 +1,14 @@
# @reactflow/controls # @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 ## 11.1.11
### Patch Changes ### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@reactflow/controls", "name": "@reactflow/controls",
"version": "11.1.11", "version": "11.1.12",
"description": "Component to control the viewport of a React Flow instance", "description": "Component to control the viewport of a React Flow instance",
"keywords": [ "keywords": [
"react", "react",
+3 -5
View File
@@ -1,8 +1,6 @@
import { memo, useEffect, useState } from 'react'; import { memo, useEffect, useState, type FC, type PropsWithChildren } from 'react';
import type { FC, PropsWithChildren } from 'react';
import cc from 'classcat'; import cc from 'classcat';
import { useStore, useStoreApi, useReactFlow, Panel } from '@reactflow/core'; import { useStore, useStoreApi, useReactFlow, Panel, type ReactFlowState } from '@reactflow/core';
import type { ReactFlowState } from '@reactflow/core';
import PlusIcon from './Icons/Plus'; import PlusIcon from './Icons/Plus';
import MinusIcon from './Icons/Minus'; import MinusIcon from './Icons/Minus';
@@ -13,7 +11,7 @@ import ControlButton from './ControlButton';
import type { ControlProps } from './types'; 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<PropsWithChildren<ControlProps>> = ({ const Controls: FC<PropsWithChildren<ControlProps>> = ({
style, style,
+10 -2
View File
@@ -1,12 +1,21 @@
# @reactflow/core # @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 ## 11.7.0
Most notable updates: Most notable updates:
- Handles: `isConnectableStart` and `isConnectableEnd` props to configure if you can start or end a connection at a certain handle - 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 - 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 ### 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" - [#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 - [#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 ## 11.6.1
### Patch Changes ### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@reactflow/core", "name": "@reactflow/core",
"version": "11.7.0", "version": "11.7.1",
"description": "Core components and util functions of React Flow.", "description": "Core components and util functions of React Flow.",
"keywords": [ "keywords": [
"react", "react",
@@ -3,6 +3,7 @@ import { isNumeric } from '../../utils';
import type { BaseEdgeProps } from '../../types'; import type { BaseEdgeProps } from '../../types';
const BaseEdge = ({ const BaseEdge = ({
id,
path, path,
labelX, labelX,
labelY, labelY,
@@ -20,6 +21,7 @@ const BaseEdge = ({
return ( return (
<> <>
<path <path
id={id}
style={style} style={style}
d={path} d={path}
fill="none" fill="none"
+10 -10
View File
@@ -51,7 +51,7 @@ export function handlePointerDown({
cancelConnection, cancelConnection,
} = getState(); } = getState();
let autoPanId = 0; let autoPanId = 0;
let prevClosestHandle: ConnectionHandle | null; let closestHandle: ConnectionHandle | null;
const { x, y } = getEventPosition(event); const { x, y } = getEventPosition(event);
const clickedHandle = doc?.elementFromPoint(x, y); const clickedHandle = doc?.elementFromPoint(x, y);
@@ -106,9 +106,9 @@ export function handlePointerDown({
function onPointerMove(event: MouseEvent | TouchEvent) { function onPointerMove(event: MouseEvent | TouchEvent) {
const { transform } = getState(); const { transform } = getState();
connectionPosition = getEventPosition(event, containerBounds);
prevClosestHandle = getClosestHandle( connectionPosition = getEventPosition(event, containerBounds);
closestHandle = getClosestHandle(
pointToRendererPoint(connectionPosition, transform, false, [1, 1]), pointToRendererPoint(connectionPosition, transform, false, [1, 1]),
connectionRadius, connectionRadius,
handleLookup handleLookup
@@ -121,7 +121,7 @@ export function handlePointerDown({
const result = isValidHandle( const result = isValidHandle(
event, event,
prevClosestHandle, closestHandle,
connectionMode, connectionMode,
nodeId, nodeId,
handleId, handleId,
@@ -136,20 +136,20 @@ export function handlePointerDown({
setState({ setState({
connectionPosition: connectionPosition:
prevClosestHandle && isValid closestHandle && isValid
? rendererPointToPoint( ? rendererPointToPoint(
{ {
x: prevClosestHandle.x, x: closestHandle.x,
y: prevClosestHandle.y, y: closestHandle.y,
}, },
transform transform
) )
: connectionPosition, : connectionPosition,
connectionStatus: getConnectionStatus(!!prevClosestHandle, isValid), connectionStatus: getConnectionStatus(!!closestHandle, isValid),
connectionEndHandle: result.endHandle, connectionEndHandle: result.endHandle,
}); });
if (!prevClosestHandle && !isValid && !handleDomNode) { if (!closestHandle && !isValid && !handleDomNode) {
return resetRecentHandle(prevActiveHandle); return resetRecentHandle(prevActiveHandle);
} }
@@ -164,7 +164,7 @@ export function handlePointerDown({
} }
function onPointerUp(event: MouseEvent | TouchEvent) { function onPointerUp(event: MouseEvent | TouchEvent) {
if ((prevClosestHandle || handleDomNode) && connection && isValid) { if ((closestHandle || handleDomNode) && connection && isValid) {
onConnect?.(connection); onConnect?.(connection);
} }
@@ -62,7 +62,7 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
const store = useStoreApi(); const store = useStoreApi();
const nodeId = useNodeId(); const nodeId = useNodeId();
const { connectOnClick, noPanClassName } = useStore(selector, shallow); 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) { if (!nodeId) {
store.getState().onError?.('010', errorMessages['error010']()); store.getState().onError?.('010', errorMessages['error010']());
+18 -4
View File
@@ -41,18 +41,30 @@ export function getClosestHandle(
connectionRadius: number, connectionRadius: number,
handles: ConnectionHandle[] handles: ConnectionHandle[]
): ConnectionHandle | null { ): ConnectionHandle | null {
let closestHandle: ConnectionHandle | null = null; let closestHandles: ConnectionHandle[] = [];
let minDistance = Infinity; let minDistance = Infinity;
handles.forEach((handle) => { handles.forEach((handle) => {
const distance = Math.sqrt(Math.pow(handle.x - pos.x, 2) + Math.pow(handle.y - pos.y, 2)); 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; 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 = { type Result = {
@@ -81,6 +93,8 @@ export function isValidHandle(
); );
const { x, y } = getEventPosition(event); const { x, y } = getEventPosition(event);
const handleBelow = doc.elementFromPoint(x, y); 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 handleToCheck = handleBelow?.classList.contains('react-flow__handle') ? handleBelow : handleDomNode;
const result: Result = { const result: Result = {
+3 -2
View File
@@ -119,8 +119,9 @@ function useDrag({
lastPos.current.x = (lastPos.current.x ?? 0) - xMovement / transform[2]; lastPos.current.x = (lastPos.current.x ?? 0) - xMovement / transform[2];
lastPos.current.y = (lastPos.current.y ?? 0) - yMovement / transform[2]; lastPos.current.y = (lastPos.current.y ?? 0) - yMovement / transform[2];
updateNodes(lastPos.current as XYPosition); if (panBy({ x: xMovement, y: yMovement })) {
panBy({ x: xMovement, y: yMovement }); updateNodes(lastPos.current as XYPosition);
}
} }
autoPanId.current = requestAnimationFrame(autoPan); autoPanId.current = requestAnimationFrame(autoPan);
}; };
@@ -6,13 +6,20 @@ import type { UpdateNodeInternals } from '../types';
function useUpdateNodeInternals(): UpdateNodeInternals { function useUpdateNodeInternals(): UpdateNodeInternals {
const store = useStoreApi(); const store = useStoreApi();
return useCallback<UpdateNodeInternals>((id: string) => { return useCallback<UpdateNodeInternals>((id: string | string[]) => {
const { domNode, updateNodeDimensions } = store.getState(); const { domNode, updateNodeDimensions } = store.getState();
const nodeElement = domNode?.querySelector(`.react-flow__node[data-id="${id}"]`) as HTMLDivElement;
if (nodeElement) { const updateIds = Array.isArray(id) ? id : [id];
requestAnimationFrame(() => updateNodeDimensions([{ id, nodeElement, forceUpdate: true }]));
} requestAnimationFrame(() => {
updateIds.forEach((updateId) => {
const nodeElement = domNode?.querySelector(`.react-flow__node[data-id="${updateId}"]`) as HTMLDivElement;
if (nodeElement) {
updateNodeDimensions([{ id: updateId, nodeElement, forceUpdate: true }]);
}
});
});
}, []); }, []);
} }
+9 -2
View File
@@ -252,11 +252,11 @@ const createRFStore = () =>
nodeInternals: new Map(nodeInternals), nodeInternals: new Map(nodeInternals),
}); });
}, },
panBy: (delta: XYPosition) => { panBy: (delta: XYPosition): boolean => {
const { transform, width, height, d3Zoom, d3Selection, translateExtent } = get(); const { transform, width, height, d3Zoom, d3Selection, translateExtent } = get();
if (!d3Zoom || !d3Selection || (!delta.x && !delta.y)) { 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]); 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); const constrainedTransform = d3Zoom?.constrain()(nextTransform, extent, translateExtent);
d3Zoom.transform(d3Selection, constrainedTransform); d3Zoom.transform(d3Selection, constrainedTransform);
const transformChanged =
transform[0] !== constrainedTransform.x ||
transform[1] !== constrainedTransform.y ||
transform[2] !== constrainedTransform.k;
return transformChanged;
}, },
cancelConnection: () => cancelConnection: () =>
set({ set({
+1
View File
@@ -121,6 +121,7 @@ export type EdgeProps<T = any> = Pick<
export type BaseEdgeProps = Pick<EdgeProps, 'style' | 'markerStart' | 'markerEnd' | 'interactionWidth'> & export type BaseEdgeProps = Pick<EdgeProps, 'style' | 'markerStart' | 'markerEnd' | 'interactionWidth'> &
EdgeLabelOptions & { EdgeLabelOptions & {
id?: string;
labelX?: number; labelX?: number;
labelY?: number; labelY?: number;
path: string; path: string;
+1 -1
View File
@@ -252,7 +252,7 @@ export type ReactFlowActions = {
cancelConnection: () => void; cancelConnection: () => void;
reset: () => void; reset: () => void;
triggerNodeChanges: (changes: NodeChange[]) => void; triggerNodeChanges: (changes: NodeChange[]) => void;
panBy: (delta: XYPosition) => void; panBy: (delta: XYPosition) => boolean;
}; };
export type ReactFlowState = ReactFlowStore & ReactFlowActions; export type ReactFlowState = ReactFlowStore & ReactFlowActions;
+7
View File
@@ -1,5 +1,12 @@
# @reactflow/minimap # @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 ## 11.5.0
### Minor Changes ### Minor Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@reactflow/minimap", "name": "@reactflow/minimap",
"version": "11.5.0", "version": "11.5.1",
"description": "Minimap component for React Flow.", "description": "Minimap component for React Flow.",
"keywords": [ "keywords": [
"react", "react",
+11
View File
@@ -1,5 +1,16 @@
# @reactflow/node-toolbar # @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 ## 1.1.11
### Patch Changes ### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@reactflow/node-toolbar", "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.", "description": "A toolbar component for React Flow that can be attached to a node.",
"keywords": [ "keywords": [
"react", "react",
+32 -18
View File
@@ -14,7 +14,7 @@ import cc from 'classcat';
import { shallow } from 'zustand/shallow'; import { shallow } from 'zustand/shallow';
import NodeToolbarPortal from './NodeToolbarPortal'; import NodeToolbarPortal from './NodeToolbarPortal';
import { NodeToolbarProps } from './types'; import { Align, NodeToolbarProps } from './types';
const nodeEqualityFn = (a: Node | undefined, b: Node | undefined) => const nodeEqualityFn = (a: Node | undefined, b: Node | undefined) =>
a?.positionAbsolute?.x === b?.positionAbsolute?.x && a?.positionAbsolute?.x === b?.positionAbsolute?.x &&
@@ -34,33 +34,46 @@ const storeSelector = (state: ReactFlowState) => ({
selectedNodesCount: state.getNodes().filter((node) => node.selected).length, 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 // position === Position.Top
let xPos = (nodeRect.x + nodeRect.width / 2) * transform[2] + transform[0]; // we set the x any y position of the toolbar based on the nodes position
let yPos = nodeRect.y * transform[2] + transform[1] - offset; let pos = [
let xShift = -50; (nodeRect.x + nodeRect.width * alignmentOffset) * transform[2] + transform[0],
let yShift = -100; 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) { switch (position) {
case Position.Right: case Position.Right:
xPos = (nodeRect.x + nodeRect.width) * transform[2] + transform[0] + offset; pos = [
yPos = (nodeRect.y + nodeRect.height / 2) * transform[2] + transform[1]; (nodeRect.x + nodeRect.width) * transform[2] + transform[0] + offset,
xShift = 0; (nodeRect.y + nodeRect.height * alignmentOffset) * transform[2] + transform[1],
yShift = -50; ];
shift = [0, -100 * alignmentOffset];
break; break;
case Position.Bottom: case Position.Bottom:
yPos = (nodeRect.y + nodeRect.height) * transform[2] + transform[1] + offset; pos[1] = (nodeRect.y + nodeRect.height) * transform[2] + transform[1] + offset;
yShift = 0; shift[1] = 0;
break; break;
case Position.Left: case Position.Left:
xPos = nodeRect.x * transform[2] + transform[0] - offset; pos = [
yPos = (nodeRect.y + nodeRect.height / 2) * transform[2] + transform[1]; nodeRect.x * transform[2] + transform[0] - offset,
xShift = -100; (nodeRect.y + nodeRect.height * alignmentOffset) * transform[2] + transform[1],
yShift = -50; ];
shift = [-100, -100 * alignmentOffset];
break; 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({ function NodeToolbar({
@@ -71,6 +84,7 @@ function NodeToolbar({
isVisible, isVisible,
position = Position.Top, position = Position.Top,
offset = 10, offset = 10,
align = 'center',
...rest ...rest
}: NodeToolbarProps) { }: NodeToolbarProps) {
const contextNodeId = useNodeId(); const contextNodeId = useNodeId();
@@ -103,7 +117,7 @@ function NodeToolbar({
const wrapperStyle: CSSProperties = { const wrapperStyle: CSSProperties = {
position: 'absolute', position: 'absolute',
transform: getTransform(nodeRect, transform, position, offset), transform: getTransform(nodeRect, transform, position, offset, align),
zIndex, zIndex,
...style, ...style,
}; };
+3
View File
@@ -6,4 +6,7 @@ export type NodeToolbarProps = HTMLAttributes<HTMLDivElement> & {
isVisible?: boolean; isVisible?: boolean;
position?: Position; position?: Position;
offset?: number; offset?: number;
align?: Align;
}; };
export type Align = 'center' | 'start' | 'end';
+18 -3
View File
@@ -1,5 +1,22 @@
# reactflow # 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 ## 11.7.0
Most notable updates: Most notable updates:
@@ -9,7 +26,7 @@ Most notable updates:
- Edges: `updatable` option to enable updates for specific edges - Edges: `updatable` option to enable updates for specific edges
- MiniMap: `inversePan` and `zoomStep` props - 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) - 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)! 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 - [#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 - [#2941](https://github.com/wbkd/react-flow/pull/2941) Thanks [@Elringus](https://github.com/Elringus)! - background: add `id` and `offset` props
### Patch Changes ### Patch Changes
- [#2926](https://github.com/wbkd/react-flow/pull/2926) Thanks [@Elringus](https://github.com/Elringus)! - fix non-passive wheel event listener violation - [#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" - [#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 - [#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 ### 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)]: - 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)]:
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "reactflow", "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", "description": "A highly customizable React library for building node-based editors and interactive flow charts",
"keywords": [ "keywords": [
"react", "react",