From f9f9e6f16834bb894eedb2a72e90f94351361897 Mon Sep 17 00:00:00 2001 From: moklick Date: Tue, 15 Apr 2025 08:25:01 +0200 Subject: [PATCH 1/2] chore(react): avoid deselection on pane click if elementsSelectable=false --- .../examples/UseOnSelectionChange/index.tsx | 33 +++++++++---------- .../components/SelectionListener/index.tsx | 4 +-- packages/react/src/store/index.ts | 6 +++- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/examples/react/src/examples/UseOnSelectionChange/index.tsx b/examples/react/src/examples/UseOnSelectionChange/index.tsx index fdbe124a..460ee9c3 100644 --- a/examples/react/src/examples/UseOnSelectionChange/index.tsx +++ b/examples/react/src/examples/UseOnSelectionChange/index.tsx @@ -10,6 +10,7 @@ import { useEdgesState, useOnSelectionChange, OnSelectionChangeParams, + Panel, } from '@xyflow/react'; const initialNodes: Node[] = [ @@ -51,6 +52,12 @@ const Flow = () => { const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); const onConnect = useCallback((params: Edge | Connection) => setEdges((els) => addEdge(params, els)), [setEdges]); + const [elementsSelectable, setElementsSelectable] = useState(true); + const [secondLoggerActive, setSecondLoggerActive] = useState(true); + + const toggleSecondLogger = () => { + setSecondLoggerActive(!secondLoggerActive); + }; return ( { onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} - /> - ); -}; + elementsSelectable={elementsSelectable} + > + + + + -const WrappedFlow = () => { - const [secondLoggerActive, setSecondLoggerActive] = useState(true); - - const toggleSecondLogger = () => { - setSecondLoggerActive(!secondLoggerActive); - }; - - return ( - - {secondLoggerActive && } -
- -
-
+
); }; -export default WrappedFlow; +export default Flow; diff --git a/packages/react/src/components/SelectionListener/index.tsx b/packages/react/src/components/SelectionListener/index.tsx index 04c46416..89ed2c26 100644 --- a/packages/react/src/components/SelectionListener/index.tsx +++ b/packages/react/src/components/SelectionListener/index.tsx @@ -19,13 +19,13 @@ const selector = (s: ReactFlowState) => { const selectedEdges = []; for (const [, node] of s.nodeLookup) { - if (node.selected && (s.elementsSelectable || node.selectable)) { + if (node.selected) { selectedNodes.push(node.internals.userNode); } } for (const [, edge] of s.edgeLookup) { - if (edge.selected && (s.elementsSelectable || edge.selectable)) { + if (edge.selected) { selectedEdges.push(edge); } } diff --git a/packages/react/src/store/index.ts b/packages/react/src/store/index.ts index 7682dc90..e2fedee3 100644 --- a/packages/react/src/store/index.ts +++ b/packages/react/src/store/index.ts @@ -297,7 +297,11 @@ const createStore = ({ get().panZoom?.setClickDistance(clickDistance); }, resetSelectedElements: () => { - const { edges, nodes, triggerNodeChanges, triggerEdgeChanges } = get(); + const { edges, nodes, triggerNodeChanges, triggerEdgeChanges, elementsSelectable } = get(); + + if (!elementsSelectable) { + return; + } const nodeChanges = nodes.reduce( (res, node) => (node.selected ? [...res, createSelectionChange(node.id, false)] : res), From bce74e8811a98c967b5bd06c3e5aecde24c8b679 Mon Sep 17 00:00:00 2001 From: moklick Date: Tue, 15 Apr 2025 08:25:55 +0200 Subject: [PATCH 2/2] chore(changeset): add --- .changeset/flat-crabs-attack.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/flat-crabs-attack.md diff --git a/.changeset/flat-crabs-attack.md b/.changeset/flat-crabs-attack.md new file mode 100644 index 00000000..2d23f9cb --- /dev/null +++ b/.changeset/flat-crabs-attack.md @@ -0,0 +1,5 @@ +--- +'@xyflow/react': patch +--- + +Keep node seleciton on pane click if elementsSelectable=false