From 98b212f0d505ce2fbe91bb20b07636ea863ee9cb Mon Sep 17 00:00:00 2001 From: peterkogo Date: Mon, 20 Jan 2025 11:20:33 +0100 Subject: [PATCH 1/7] Narrow NodeProps type properties selected, selectable, draggable and deletable required --- .../react/src/components/NodeWrapper/index.tsx | 2 +- .../lib/components/NodeWrapper/NodeWrapper.svelte | 12 +++++++----- packages/system/src/types/nodes.ts | 15 ++------------- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/packages/react/src/components/NodeWrapper/index.tsx b/packages/react/src/components/NodeWrapper/index.tsx index a54a4993..4b0295e9 100644 --- a/packages/react/src/components/NodeWrapper/index.tsx +++ b/packages/react/src/components/NodeWrapper/index.tsx @@ -202,7 +202,7 @@ export function NodeWrapper({ type={nodeType} positionAbsoluteX={internals.positionAbsolute.x} positionAbsoluteY={internals.positionAbsolute.y} - selected={node.selected} + selected={node.selected ?? false} selectable={isSelectable} draggable={isDraggable} deletable={node.deletable ?? true} diff --git a/packages/svelte/src/lib/components/NodeWrapper/NodeWrapper.svelte b/packages/svelte/src/lib/components/NodeWrapper/NodeWrapper.svelte index dc571ec2..ed30d5b2 100644 --- a/packages/svelte/src/lib/components/NodeWrapper/NodeWrapper.svelte +++ b/packages/svelte/src/lib/components/NodeWrapper/NodeWrapper.svelte @@ -54,7 +54,9 @@ nodeDragThreshold, selectNodesOnDrag, handleNodeSelection, - updateNodeInternals + updateNodeInternals, + elementsSelectable, + nodesDraggable } = store; let nodeRef: HTMLDivElement; @@ -194,14 +196,14 @@ this={nodeComponent} {data} {id} - {selected} - {selectable} - {deletable} + selected={selected ?? false} + selectable={selectable ?? $elementsSelectable ?? true} + deletable={deletable ?? true} {sourcePosition} {targetPosition} {zIndex} {dragging} - {draggable} + draggable={draggable ?? $nodesDraggable ?? true} {dragHandle} {parentId} type={nodeType} diff --git a/packages/system/src/types/nodes.ts b/packages/system/src/types/nodes.ts index b405b5ba..92261205 100644 --- a/packages/system/src/types/nodes.ts +++ b/packages/system/src/types/nodes.ts @@ -88,20 +88,9 @@ export type InternalNodeBase = NodeType & */ export type NodeProps = Pick< NodeType, - | 'id' - | 'data' - | 'width' - | 'height' - | 'sourcePosition' - | 'targetPosition' - | 'selected' - | 'dragHandle' - | 'selectable' - | 'deletable' - | 'draggable' - | 'parentId' + 'id' | 'data' | 'width' | 'height' | 'sourcePosition' | 'targetPosition' | 'dragHandle' | 'parentId' > & - Required> & { + Required> & { /** whether a node is connectable or not */ isConnectable: boolean; /** position absolute x value */ From fe843982bfc7d7579d54772b201426b4c3f549c6 Mon Sep 17 00:00:00 2001 From: peterkogo Date: Mon, 20 Jan 2025 11:23:26 +0100 Subject: [PATCH 2/7] chore(changeset) add --- .changeset/rotten-moons-roll.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/rotten-moons-roll.md diff --git a/.changeset/rotten-moons-roll.md b/.changeset/rotten-moons-roll.md new file mode 100644 index 00000000..c0b4d678 --- /dev/null +++ b/.changeset/rotten-moons-roll.md @@ -0,0 +1,7 @@ +--- +'@xyflow/react': minor +'@xyflow/svelte': minor +'@xyflow/system': patch +--- + +Narrow properties selected, selectable, deletable, draggable of NodeProps type to be required. From de156baa7878f5af11d85c59c36938cfadaaae3d Mon Sep 17 00:00:00 2001 From: peterkogo Date: Mon, 20 Jan 2025 12:14:40 +0100 Subject: [PATCH 3/7] change to patch release --- .changeset/rotten-moons-roll.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/rotten-moons-roll.md b/.changeset/rotten-moons-roll.md index c0b4d678..66e6cdd3 100644 --- a/.changeset/rotten-moons-roll.md +++ b/.changeset/rotten-moons-roll.md @@ -1,6 +1,6 @@ --- -'@xyflow/react': minor -'@xyflow/svelte': minor +'@xyflow/react': patch +'@xyflow/svelte': patch '@xyflow/system': patch --- From 7cb9a8686ddf932c7fdbc36e919a78e25dee649b Mon Sep 17 00:00:00 2001 From: peterkogo Date: Tue, 21 Jan 2025 15:45:08 +0100 Subject: [PATCH 4/7] Make internal nodes immutable --- packages/system/src/utils/store.ts | 105 ++++++++++++++++------------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/packages/system/src/utils/store.ts b/packages/system/src/utils/store.ts index 7eb7ccdb..77c5b369 100644 --- a/packages/system/src/utils/store.ts +++ b/packages/system/src/utils/store.ts @@ -87,6 +87,7 @@ export function adoptUserNodes( options?: UpdateNodesOptions ) { const _options = mergeObjects(adoptUserNodesDefaultOptions, options); + const tmpLookup = new Map(nodeLookup); const selectedNodeZ: number = _options?.elevateNodesOnSelect ? 1000 : 0; @@ -173,11 +174,15 @@ function updateChildNode( const positionChanged = x !== positionAbsolute.x || y !== positionAbsolute.y; if (positionChanged || z !== node.internals.z) { - node.internals = { - ...node.internals, - positionAbsolute: positionChanged ? { x, y } : positionAbsolute, - z, - }; + // we create a new object to mark the node as updated + nodeLookup.set(node.id, { + ...node, + internals: { + ...node.internals, + positionAbsolute: positionChanged ? { x, y } : positionAbsolute, + z, + }, + }); } } @@ -333,60 +338,70 @@ export function updateNodeInternals( } if (node.hidden) { - node.internals = { - ...node.internals, - handleBounds: undefined, - }; + nodeLookup.set(node.id, { + ...node, + internals: { + ...node.internals, + handleBounds: undefined, + }, + }); updatedInternals = true; - } else { - const dimensions = getDimensions(update.nodeElement); - const dimensionChanged = node.measured.width !== dimensions.width || node.measured.height !== dimensions.height; - const doUpdate = !!( - dimensions.width && - dimensions.height && - (dimensionChanged || !node.internals.handleBounds || update.force) - ); + continue; + } - if (doUpdate) { - const nodeBounds = update.nodeElement.getBoundingClientRect(); - const extent = isCoordinateExtent(node.extent) ? node.extent : nodeExtent; - let { positionAbsolute } = node.internals; + const dimensions = getDimensions(update.nodeElement); + const dimensionChanged = node.measured.width !== dimensions.width || node.measured.height !== dimensions.height; + const doUpdate = !!( + dimensions.width && + dimensions.height && + (dimensionChanged || !node.internals.handleBounds || update.force) + ); - if (node.parentId && node.extent === 'parent') { - positionAbsolute = clampPositionToParent(positionAbsolute, dimensions, nodeLookup.get(node.parentId)!); - } else if (extent) { - positionAbsolute = clampPosition(positionAbsolute, extent, dimensions); - } + if (doUpdate) { + const nodeBounds = update.nodeElement.getBoundingClientRect(); + const extent = isCoordinateExtent(node.extent) ? node.extent : nodeExtent; + let { positionAbsolute } = node.internals; - node.measured = dimensions; - node.internals = { + if (node.parentId && node.extent === 'parent') { + positionAbsolute = clampPositionToParent(positionAbsolute, dimensions, nodeLookup.get(node.parentId)!); + } else if (extent) { + positionAbsolute = clampPosition(positionAbsolute, extent, dimensions); + } + + const newNode = { + ...node, + measured: dimensions, + internals: { ...node.internals, positionAbsolute, handleBounds: { source: getHandleBounds('source', update.nodeElement, nodeBounds, zoom, node.id), target: getHandleBounds('target', update.nodeElement, nodeBounds, zoom, node.id), }, - }; - if (node.parentId) { - updateChildNode(node, nodeLookup, parentLookup, { nodeOrigin }); - } + }, + }; - updatedInternals = true; + nodeLookup.set(node.id, newNode); - if (dimensionChanged) { - changes.push({ + if (node.parentId) { + updateChildNode(newNode, nodeLookup, parentLookup, { nodeOrigin }); + } + + updatedInternals = true; + + if (dimensionChanged) { + changes.push({ + id: node.id, + type: 'dimensions', + dimensions, + }); + + if (node.expandParent && node.parentId) { + parentExpandChildren.push({ id: node.id, - type: 'dimensions', - dimensions, + parentId: node.parentId, + rect: nodeToRect(newNode, nodeOrigin), }); - - if (node.expandParent && node.parentId) { - parentExpandChildren.push({ - id: node.id, - parentId: node.parentId, - rect: nodeToRect(node, nodeOrigin), - }); - } } } } From c12fa5c178d7df55e54676a739995d48ffe9b911 Mon Sep 17 00:00:00 2001 From: peterkogo Date: Tue, 21 Jan 2025 15:45:35 +0100 Subject: [PATCH 5/7] Allow handle id to be null --- packages/system/src/types/handles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/system/src/types/handles.ts b/packages/system/src/types/handles.ts index f9828dd5..9cf2a1dd 100644 --- a/packages/system/src/types/handles.ts +++ b/packages/system/src/types/handles.ts @@ -36,5 +36,5 @@ export type HandleProps = { /** Id of the handle * @remarks optional if there is only one handle of this type */ - id?: string; + id?: string | null; }; From e73ef09fbc8d872b46cf52c9d6a32dbb388c220b Mon Sep 17 00:00:00 2001 From: peterkogo Date: Tue, 21 Jan 2025 15:46:28 +0100 Subject: [PATCH 6/7] chore(changeset) add --- .changeset/spotty-pots-rest.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/spotty-pots-rest.md diff --git a/.changeset/spotty-pots-rest.md b/.changeset/spotty-pots-rest.md new file mode 100644 index 00000000..42344e2f --- /dev/null +++ b/.changeset/spotty-pots-rest.md @@ -0,0 +1,5 @@ +--- +'@xyflow/system': patch +--- + +Make internal nodes immutable From 9ecb0bb6c7d415edb140ee225a9fd22795d19b53 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 21 Jan 2025 14:50:47 +0000 Subject: [PATCH 7/7] chore(packages): bump --- .changeset/rotten-moons-roll.md | 7 ------- .changeset/spotty-pots-rest.md | 5 ----- packages/react/CHANGELOG.md | 9 +++++++++ packages/react/package.json | 2 +- packages/svelte/CHANGELOG.md | 9 +++++++++ packages/svelte/package.json | 2 +- packages/system/CHANGELOG.md | 8 ++++++++ packages/system/package.json | 2 +- 8 files changed, 29 insertions(+), 15 deletions(-) delete mode 100644 .changeset/rotten-moons-roll.md delete mode 100644 .changeset/spotty-pots-rest.md diff --git a/.changeset/rotten-moons-roll.md b/.changeset/rotten-moons-roll.md deleted file mode 100644 index 66e6cdd3..00000000 --- a/.changeset/rotten-moons-roll.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@xyflow/react': patch -'@xyflow/svelte': patch -'@xyflow/system': patch ---- - -Narrow properties selected, selectable, deletable, draggable of NodeProps type to be required. diff --git a/.changeset/spotty-pots-rest.md b/.changeset/spotty-pots-rest.md deleted file mode 100644 index 42344e2f..00000000 --- a/.changeset/spotty-pots-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@xyflow/system': patch ---- - -Make internal nodes immutable diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index abddf7b8..3f3b6e31 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,14 @@ # @xyflow/react +## 12.4.2 + +### Patch Changes + +- [#4957](https://github.com/xyflow/xyflow/pull/4957) [`fe843982`](https://github.com/xyflow/xyflow/commit/fe843982bfc7d7579d54772b201426b4c3f549c6) Thanks [@peterkogo](https://github.com/peterkogo)! - Narrow properties selected, selectable, deletable, draggable of NodeProps type to be required. + +- Updated dependencies [[`fe843982`](https://github.com/xyflow/xyflow/commit/fe843982bfc7d7579d54772b201426b4c3f549c6), [`e73ef09f`](https://github.com/xyflow/xyflow/commit/e73ef09fbc8d872b46cf52c9d6a32dbb388c220b)]: + - @xyflow/system@0.0.50 + ## 12.4.1 ### Patch Changes diff --git a/packages/react/package.json b/packages/react/package.json index 18f629bc..fb572c1a 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@xyflow/react", - "version": "12.4.1", + "version": "12.4.2", "description": "React Flow - A highly customizable React library for building node-based editors and interactive flow charts.", "keywords": [ "react", diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 736fbc04..0a0e8306 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,14 @@ # @xyflow/svelte +## 0.1.29 + +### Patch Changes + +- [#4957](https://github.com/xyflow/xyflow/pull/4957) [`fe843982`](https://github.com/xyflow/xyflow/commit/fe843982bfc7d7579d54772b201426b4c3f549c6) Thanks [@peterkogo](https://github.com/peterkogo)! - Narrow properties selected, selectable, deletable, draggable of NodeProps type to be required. + +- Updated dependencies [[`fe843982`](https://github.com/xyflow/xyflow/commit/fe843982bfc7d7579d54772b201426b4c3f549c6), [`e73ef09f`](https://github.com/xyflow/xyflow/commit/e73ef09fbc8d872b46cf52c9d6a32dbb388c220b)]: + - @xyflow/system@0.0.50 + ## 0.1.28 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 20533a76..ab0542d7 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@xyflow/svelte", - "version": "0.1.28", + "version": "0.1.29", "description": "Svelte Flow - A highly customizable Svelte library for building node-based editors, workflow systems, diagrams and more.", "keywords": [ "svelte", diff --git a/packages/system/CHANGELOG.md b/packages/system/CHANGELOG.md index faeb5e48..a1613ca3 100644 --- a/packages/system/CHANGELOG.md +++ b/packages/system/CHANGELOG.md @@ -1,5 +1,13 @@ # @xyflow/system +## 0.0.50 + +### Patch Changes + +- [#4957](https://github.com/xyflow/xyflow/pull/4957) [`fe843982`](https://github.com/xyflow/xyflow/commit/fe843982bfc7d7579d54772b201426b4c3f549c6) Thanks [@peterkogo](https://github.com/peterkogo)! - Narrow properties selected, selectable, deletable, draggable of NodeProps type to be required. + +- [#4968](https://github.com/xyflow/xyflow/pull/4968) [`e73ef09f`](https://github.com/xyflow/xyflow/commit/e73ef09fbc8d872b46cf52c9d6a32dbb388c220b) Thanks [@peterkogo](https://github.com/peterkogo)! - Make internal nodes immutable + ## 0.0.49 ### Patch Changes diff --git a/packages/system/package.json b/packages/system/package.json index 6169c271..c7b1ee03 100644 --- a/packages/system/package.json +++ b/packages/system/package.json @@ -1,6 +1,6 @@ { "name": "@xyflow/system", - "version": "0.0.49", + "version": "0.0.50", "description": "xyflow core system that powers React Flow and Svelte Flow.", "keywords": [ "node-based UI",