Skip to content

Commit

Permalink
Merge pull request #4083 from xyflow/next-v11
Browse files Browse the repository at this point in the history
React Flow 11.11.0
  • Loading branch information
moklick committed Apr 4, 2024
2 parents 00b3c16 + 11569bc commit 0238ba4
Show file tree
Hide file tree
Showing 27 changed files with 167 additions and 60 deletions.
12 changes: 6 additions & 6 deletions examples/vite-app/src/examples/NestedNodes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const initialNodes: Node[] = [
id: '2a',
data: { label: 'Node 2a' },
position: { x: 10, y: 50 },
parentNode: '2',
parentId: '2',
},
{
id: '3',
Expand All @@ -55,7 +55,7 @@ const initialNodes: Node[] = [
data: { label: 'Node 4a' },
position: { x: 15, y: 65 },
className: 'light',
parentNode: '4',
parentId: '4',
extent: 'parent',
},
{
Expand All @@ -68,21 +68,21 @@ const initialNodes: Node[] = [
height: 150,
width: 270,
},
parentNode: '4',
parentId: '4',
},
{
id: '4b1',
data: { label: 'Node 4b1' },
position: { x: 20, y: 40 },
className: 'light',
parentNode: '4b',
parentId: '4b',
},
{
id: '4b2',
data: { label: 'Node 4b2' },
position: { x: 100, y: 100 },
className: 'light',
parentNode: '4b',
parentId: '4b',
},
];

Expand Down Expand Up @@ -138,7 +138,7 @@ const NestedFlow = () => {
const toggleChildNodes = () => {
setNodes((nds) => {
return nds.map((n) => {
n.hidden = !!n.parentNode && !n.hidden;
n.hidden = !!n.parentId && !n.hidden;
return n;
});
});
Expand Down
35 changes: 21 additions & 14 deletions examples/vite-app/src/examples/Subflow/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const initialNodes: Node[] = [
data: { label: 'Node 4a' },
position: { x: 15, y: 15 },
className: 'light',
parentNode: '4',
parentId: '4',
extent: [
[0, 0],
[100, 100],
Expand All @@ -62,21 +62,21 @@ const initialNodes: Node[] = [
height: 200,
width: 300,
},
parentNode: '4',
parentId: '4',
},
{
id: '4b1',
data: { label: 'Node 4b1' },
position: { x: 40, y: 20 },
className: 'light',
parentNode: '4b',
parentId: '4b',
},
{
id: '4b2',
data: { label: 'Node 4b2' },
position: { x: 20, y: 100 },
className: 'light',
parentNode: '4b',
parentId: '4b',
},
{
id: '5',
Expand All @@ -92,15 +92,15 @@ const initialNodes: Node[] = [
data: { label: 'Node 5a' },
position: { x: 0, y: 0 },
className: 'light',
parentNode: '5',
parentId: '5',
extent: 'parent',
},
{
id: '5b',
data: { label: 'Node 5b' },
position: { x: 100, y: 100 },
className: 'light',
parentNode: '5',
parentId: '5',
expandParent: true,
},
{
Expand Down Expand Up @@ -153,10 +153,13 @@ const Subflow = () => {
const updatePos = () => {
setNodes((nds) => {
return nds.map((n) => {
if (!n.parentNode) {
n.position = {
x: Math.random() * 400,
y: Math.random() * 400,
if (!n.parentId) {
return {
...n,
position: {
x: Math.random() * 400,
y: Math.random() * 400,
},
};
}

Expand All @@ -171,17 +174,21 @@ const Subflow = () => {
const toggleClassnames = () => {
setNodes((nds) => {
return nds.map((n) => {
n.className = n.className === 'light' ? 'dark' : 'light';
return n;
return {
...n,
className: n.className === 'light' ? 'dark' : 'light',
};
});
});
};

const toggleChildNodes = () => {
setNodes((nds) => {
return nds.map((n) => {
n.hidden = !!n.parentNode && !n.hidden;
return n;
return {
...n,
hidden: !!n.parentId && !n.hidden,
};
});
});
};
Expand Down
7 changes: 7 additions & 0 deletions packages/background/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @reactflow/background

## 11.3.10

### Patch Changes

- Updated dependencies [[`c7a140bd`](https://github.com/xyflow/xyflow/commit/c7a140bd7bc4442bf4121b1bca936a05e19117a4), [`ba3809b1`](https://github.com/xyflow/xyflow/commit/ba3809b18413fa581a4e7098611ebcb9067c971f), [`6228d499`](https://github.com/xyflow/xyflow/commit/6228d499464408fc7bad0ce89b321a59ca5ecbe1)], [[`d80b9e7b`](https://github.com/xyflow/xyflow/commit/d80b9e7b18476f11d91a68cfcae0e3f5e5fcac36)]:
- @reactflow/core@11.11.0

## 11.3.9

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/background/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@reactflow/background",
"version": "11.3.9",
"version": "11.3.10",
"description": "Background component with different variants for React Flow",
"keywords": [
"react",
Expand Down
7 changes: 7 additions & 0 deletions packages/controls/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @reactflow/controls

## 11.2.10

### Patch Changes

- Updated dependencies [[`c7a140bd`](https://github.com/xyflow/xyflow/commit/c7a140bd7bc4442bf4121b1bca936a05e19117a4), [`ba3809b1`](https://github.com/xyflow/xyflow/commit/ba3809b18413fa581a4e7098611ebcb9067c971f), [`6228d499`](https://github.com/xyflow/xyflow/commit/6228d499464408fc7bad0ce89b321a59ca5ecbe1)], [[`d80b9e7b`](https://github.com/xyflow/xyflow/commit/d80b9e7b18476f11d91a68cfcae0e3f5e5fcac36)]:
- @reactflow/core@11.11.0

## 11.2.9

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/controls/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@reactflow/controls",
"version": "11.2.9",
"version": "11.2.10",
"description": "Component to control the viewport of a React Flow instance",
"keywords": [
"react",
Expand Down
12 changes: 12 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# @reactflow/core

## 11.11.0

### Minor Changes

- [#4110](https://github.com/xyflow/xyflow/pull/4110) [`d80b9e7b`](https://github.com/xyflow/xyflow/commit/d80b9e7b18476f11d91a68cfcae0e3f5e5fcac36) Thanks [@moklick](https://github.com/moklick)! - deprecate node.parentNode, rename to node.parentId

### Patch Changes

- [#3957](https://github.com/xyflow/xyflow/pull/3957) [`c7a140bd`](https://github.com/xyflow/xyflow/commit/c7a140bd7bc4442bf4121b1bca936a05e19117a4) - fixed smoothstep edge if center = 0
- [#4082](https://github.com/xyflow/xyflow/pull/4082) [`ba3809b1`](https://github.com/xyflow/xyflow/commit/ba3809b18413fa581a4e7098611ebcb9067c971f) - fix: re-observe nodes when hidden is toggled
- [#3935](https://github.com/xyflow/xyflow/pull/3935) [`6228d499`](https://github.com/xyflow/xyflow/commit/6228d499464408fc7bad0ce89b321a59ca5ecbe1) - disableKeyboardA11y now correctly prevents escape key presses

## 11.10.4

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@reactflow/core",
"version": "11.10.4",
"version": "11.11.0",
"description": "Core components and util functions of React Flow.",
"keywords": [
"react",
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/components/Edges/SmoothStepEdge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ function getPoints({

// opposite handle positions, default case
if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {
centerX = center.x || defaultCenterX;
centerY = center.y || defaultCenterY;
centerX = center.x ?? defaultCenterX;
centerY = center.y ?? defaultCenterY;
// --->
// |
// >---
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/components/Edges/wrapEdge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
isUpdatable,
pathOptions,
interactionWidth,
disableKeyboardA11y,
}: WrapEdgeProps): JSX.Element | null => {
const edgeRef = useRef<SVGGElement>(null);
const [updateHover, setUpdateHover] = useState<boolean>(false);
Expand Down Expand Up @@ -151,7 +152,7 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
const inactive = !elementsSelectable && !onClick;

const onKeyDown = (event: KeyboardEvent) => {
if (elementSelectionKeys.includes(event.key) && elementsSelectable) {
if (!disableKeyboardA11y && elementSelectionKeys.includes(event.key) && elementsSelectable) {
const { unselectNodesAndEdges, addSelectedEdges, edges } = store.getState();
const unselect = event.key === 'Escape';

Expand Down
23 changes: 13 additions & 10 deletions packages/core/src/components/Nodes/wrapNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
hasHandleBounds,
}: WrapNodeProps) => {
const store = useStoreApi();
const nodeRef = useRef<HTMLDivElement>(null);
const nodeRef = useRef<HTMLDivElement | null>(null);
const prevNodeRef = useRef<HTMLDivElement | null>(null);
const prevSourcePosition = useRef(sourcePosition);
const prevTargetPosition = useRef(targetPosition);
const prevType = useRef(type);
Expand Down Expand Up @@ -95,6 +96,10 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
return;
}

if (disableKeyboardA11y) {
return;
}

if (elementSelectionKeys.includes(event.key) && isSelectable) {
const unselect = event.key === 'Escape';

Expand All @@ -104,12 +109,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
unselect,
nodeRef,
});
} else if (
!disableKeyboardA11y &&
isDraggable &&
selected &&
Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)
) {
} else if (isDraggable && selected && Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)) {
store.setState({
ariaLiveMessage: `Moved selected node ${event.key
.replace('Arrow', '')
Expand All @@ -126,8 +126,8 @@ export default (NodeComponent: ComponentType<NodeProps>) => {

useEffect(() => {
return () => {
if (nodeRef.current) {
resizeObserver?.unobserve(nodeRef.current);
if (prevNodeRef.current) {
resizeObserver?.unobserve(prevNodeRef.current);
}
};
}, []);
Expand All @@ -139,8 +139,11 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
if (!initialized || !hasHandleBounds) {
// At this point we always want to make sure that the node gets re-measured / re-initialized.
// We need to unobserve it first in case it is still observed
resizeObserver?.unobserve(currNode);
if (prevNodeRef.current) {
resizeObserver?.unobserve(prevNodeRef.current);
}
resizeObserver?.observe(currNode);
prevNodeRef.current = currNode;
}
}
}, [hidden, initialized, hasHandleBounds]);
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/container/EdgeRenderer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const EdgeRenderer = ({
onEdgeUpdateStart,
onEdgeUpdateEnd,
children,
disableKeyboardA11y,
}: EdgeRendererProps) => {
const { edgesFocusable, edgesUpdatable, elementsSelectable, width, height, connectionMode, nodeInternals, onError } =
useStore(selector, shallow);
Expand Down Expand Up @@ -178,6 +179,7 @@ const EdgeRenderer = ({
isUpdatable={isUpdatable}
pathOptions={'pathOptions' in edge ? edge.pathOptions : undefined}
interactionWidth={edge.interactionWidth}
disableKeyboardA11y={disableKeyboardA11y}
/>
);
})}
Expand Down
23 changes: 13 additions & 10 deletions packages/core/src/hooks/useDrag/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import { getNodePositionWithOrigin } from '../../utils/graph';
import { errorMessages } from '../../contants';

export function isParentSelected(node: Node, nodeInternals: NodeInternals): boolean {
if (!node.parentNode) {
const parentId = node.parentNode || node.parentId;
if (!parentId) {
return false;
}

const parentNode = nodeInternals.get(node.parentNode);
const parentNode = nodeInternals.get(parentId);

if (!parentNode) {
return false;
Expand Down Expand Up @@ -46,7 +47,7 @@ export function getDragItems(
.filter(
(n) =>
(n.selected || n.id === nodeId) &&
(!n.parentNode || !isParentSelected(n, nodeInternals)) &&
(!n.parentNode || n.parentId || !isParentSelected(n, nodeInternals)) &&
(n.draggable || (nodesDraggable && typeof n.draggable === 'undefined'))
)
.map((n) => ({
Expand All @@ -62,7 +63,8 @@ export function getDragItems(
y: 0,
},
extent: n.extent,
parentNode: n.parentNode,
parentNode: n.parentNode || n.parentId,
parentId: n.parentNode || n.parentId,
width: n.width,
height: n.height,
expandParent: n.expandParent,
Expand All @@ -86,10 +88,11 @@ export function calcNextPosition(
): { position: XYPosition; positionAbsolute: XYPosition } {
const clampedNodeExtent = clampNodeExtent(node, node.extent || nodeExtent);
let currentExtent = clampedNodeExtent;
const parentId = node.parentNode || node.parentId;

if (node.extent === 'parent' && !node.expandParent) {
if (node.parentNode && node.width && node.height) {
const parent = nodeInternals.get(node.parentNode);
if (parentId && node.width && node.height) {
const parent = nodeInternals.get(parentId);
const { x: parentX, y: parentY } = getNodePositionWithOrigin(parent, nodeOrigin).positionAbsolute;
currentExtent =
parent && isNumeric(parentX) && isNumeric(parentY) && isNumeric(parent.width) && isNumeric(parent.height)
Expand All @@ -106,8 +109,8 @@ export function calcNextPosition(

currentExtent = clampedNodeExtent;
}
} else if (node.extent && node.parentNode && node.extent !== 'parent') {
const parent = nodeInternals.get(node.parentNode);
} else if (node.extent && parentId && node.extent !== 'parent') {
const parent = nodeInternals.get(parentId);
const { x: parentX, y: parentY } = getNodePositionWithOrigin(parent, nodeOrigin).positionAbsolute;
currentExtent = [
[node.extent[0][0] + parentX, node.extent[0][1] + parentY],
Expand All @@ -117,8 +120,8 @@ export function calcNextPosition(

let parentPosition = { x: 0, y: 0 };

if (node.parentNode) {
const parentNode = nodeInternals.get(node.parentNode);
if (parentId) {
const parentNode = nodeInternals.get(parentId);
parentPosition = getNodePositionWithOrigin(parentNode, nodeOrigin).positionAbsolute;
}

Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/hooks/useReactFlow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ export default function useReactFlow<NodeData = any, EdgeData = any>(): ReactFlo
const nodeIds = (nodesDeleted || []).map((node) => node.id);
const edgeIds = (edgesDeleted || []).map((edge) => edge.id);
const nodesToRemove = getNodes().reduce<Node[]>((res, node) => {
const parentHit = !nodeIds.includes(node.id) && node.parentNode && res.find((n) => n.id === node.parentNode);
const parentId = node.parentNode || node.parentId;
const parentHit = !nodeIds.includes(node.id) && parentId && res.find((n) => n.id === parentId);
const deletable = typeof node.deletable === 'boolean' ? node.deletable : true;
if (deletable && (nodeIds.includes(node.id) || parentHit)) {
res.push(node);
Expand Down
Loading

0 comments on commit 0238ba4

Please sign in to comment.