diff --git a/examples/react/cypress/components/hooks/useNodes.cy.tsx b/examples/react/cypress/components/hooks/useNodes.cy.tsx
index 9c10ad70..340b4b10 100644
--- a/examples/react/cypress/components/hooks/useNodes.cy.tsx
+++ b/examples/react/cypress/components/hooks/useNodes.cy.tsx
@@ -15,8 +15,7 @@ const initialNodes: Node[] = nodes.map((n) => ({
const expectedNodes: Node[] = initialNodes.map((n) => ({
...n,
- computed: {
- positionAbsolute: n.position,
+ measured: {
...nodeDimensions,
},
}));
diff --git a/examples/react/cypress/components/reactflow/on-nodes-change.cy.tsx b/examples/react/cypress/components/reactflow/on-nodes-change.cy.tsx
index a15fc67e..bceb4cbd 100644
--- a/examples/react/cypress/components/reactflow/on-nodes-change.cy.tsx
+++ b/examples/react/cypress/components/reactflow/on-nodes-change.cy.tsx
@@ -48,7 +48,7 @@ describe(': onNodesChange', () => {
id: '1',
item: {
...nodes[0],
- computed: { positionAbsolute: nodes[0].position, width: 200, height: 100 },
+ measured: { width: 200, height: 100 },
style: { width: 200, height: 100 },
},
},
diff --git a/examples/react/cypress/components/utils/apply-changes.cy.ts b/examples/react/cypress/components/utils/apply-changes.cy.ts
index 1548b7e9..0a75db7b 100644
--- a/examples/react/cypress/components/utils/apply-changes.cy.ts
+++ b/examples/react/cypress/components/utils/apply-changes.cy.ts
@@ -136,8 +136,8 @@ describe('applyChanges Testing', () => {
];
const nextNodes = applyNodeChanges(nodeChanges, nodes);
- expect(nodes[0].computed).to.be.undefined;
- expect(nextNodes[0].computed).to.be.deep.equal({ width: newWidth, height: newHeight });
+ expect(nodes[0].measured).to.be.undefined;
+ expect(nextNodes[0].measured).to.be.deep.equal({ width: newWidth, height: newHeight });
expect(nextNodes[0].width).to.be.undefined;
expect(nextNodes[0].height).to.be.undefined;
});
@@ -153,7 +153,7 @@ describe('applyChanges Testing', () => {
const nextNodes = applyNodeChanges(nodeChanges, nodes);
expect(nextNodes[0].position).to.be.deep.equal(newPosition);
- expect(nextNodes[0].computed).to.be.deep.equal({ width: newWidth, height: newHeight });
+ expect(nextNodes[0].measured).to.be.deep.equal({ width: newWidth, height: newHeight });
});
it('replaces nodes/edges', () => {
diff --git a/examples/react/src/examples/EasyConnect/utils.tsx b/examples/react/src/examples/EasyConnect/utils.tsx
index 6d87795b..c6693015 100644
--- a/examples/react/src/examples/EasyConnect/utils.tsx
+++ b/examples/react/src/examples/EasyConnect/utils.tsx
@@ -9,8 +9,8 @@ function getNodeIntersection(intersectionNode: Node, targetNode: Node) {
width: intersectionNodeWidth,
height: intersectionNodeHeight,
positionAbsolute: intersectionNodePosition,
- } = intersectionNode.computed || {};
- const targetPosition = targetNode.computed?.positionAbsolute!;
+ } = intersectionNode.measured || {};
+ const targetPosition = targetNode.measured?.positionAbsolute!;
const w = intersectionNodeWidth! / 2;
const h = intersectionNodeHeight! / 2;
@@ -33,7 +33,7 @@ function getNodeIntersection(intersectionNode: Node, targetNode: Node) {
// returns the position (top,right,bottom or right) passed node compared to the intersection point
function getEdgePosition(node: Node, intersectionPoint: XYPosition) {
- const n = { ...node.computed?.positionAbsolute, ...node };
+ const n = { ...node.measured?.positionAbsolute, ...node };
const nx = Math.round(n.x!);
const ny = Math.round(n.y!);
const px = Math.round(intersectionPoint.x);
@@ -42,13 +42,13 @@ function getEdgePosition(node: Node, intersectionPoint: XYPosition) {
if (px <= nx + 1) {
return Position.Left;
}
- if (px >= nx + n.computed?.width! - 1) {
+ if (px >= nx + n.measured?.width! - 1) {
return Position.Right;
}
if (py <= ny + 1) {
return Position.Top;
}
- if (py >= n.y! + n.computed?.height! - 1) {
+ if (py >= n.y! + n.measured?.height! - 1) {
return Position.Bottom;
}
diff --git a/examples/react/src/examples/FloatingEdges/utils.ts b/examples/react/src/examples/FloatingEdges/utils.ts
index a022207c..08593c5c 100644
--- a/examples/react/src/examples/FloatingEdges/utils.ts
+++ b/examples/react/src/examples/FloatingEdges/utils.ts
@@ -6,7 +6,7 @@ function getNodeIntersection(intersectionNode: Node, targetNode: Node): XYPositi
// https://math.stackexchange.com/questions/1724792/an-algorithm-for-finding-the-intersection-point-between-a-center-of-vision-and-a
const { position: intersectionNodePosition } = intersectionNode;
- const { width: intersectionNodeWidth, height: intersectionNodeHeight } = intersectionNode.computed ?? {
+ const { width: intersectionNodeWidth, height: intersectionNodeHeight } = intersectionNode.measured ?? {
width: 0,
height: 0,
};
@@ -42,13 +42,13 @@ function getEdgePosition(node: Node, intersectionPoint: XYPosition) {
if (px <= nx + 1) {
return Position.Left;
}
- if (px >= nx + (n.computed?.width ?? 0) - 1) {
+ if (px >= nx + (n.measured?.width ?? 0) - 1) {
return Position.Right;
}
if (py <= ny + 1) {
return Position.Top;
}
- if (py >= n.y + (n.computed?.height ?? 0) - 1) {
+ if (py >= n.y + (n.measured?.height ?? 0) - 1) {
return Position.Bottom;
}
diff --git a/packages/react/src/additional-components/MiniMap/MiniMapNodes.tsx b/packages/react/src/additional-components/MiniMap/MiniMapNodes.tsx
index 0abe3177..f2e7944c 100644
--- a/packages/react/src/additional-components/MiniMap/MiniMapNodes.tsx
+++ b/packages/react/src/additional-components/MiniMap/MiniMapNodes.tsx
@@ -6,7 +6,7 @@ import { shallow } from 'zustand/shallow';
import { useStore } from '../../hooks/useStore';
import { MiniMapNode } from './MiniMapNode';
-import type { ReactFlowState, Node } from '../../types';
+import type { ReactFlowState, Node, InternalNode } from '../../types';
import type { MiniMapNodes as MiniMapNodesProps, GetMiniMapNodeAttribute, MiniMapNodeProps } from './types';
declare const window: any;
@@ -85,7 +85,7 @@ function NodeComponentWrapperInner({
shapeRendering: string;
}) {
const { node, x, y } = useStore((s) => {
- const node = s.nodeLookup.get(id) as NodeType;
+ const node = s.nodeLookup.get(id) as InternalNode;
const { x, y } = getNodePositionWithOrigin(node, node?.origin || nodeOrigin).positionAbsolute;
return {
diff --git a/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx b/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx
index 1a1107b1..2052c98b 100644
--- a/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx
+++ b/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx
@@ -5,12 +5,14 @@ import {
ResizeControlVariant,
type XYResizerInstance,
type XYResizerChange,
- XYResizerChildChange,
+ type XYResizerChildChange,
+ type NodeChange,
+ type NodeDimensionChange,
+ type NodePositionChange,
} from '@xyflow/system';
import { useStoreApi } from '../../hooks/useStore';
import { useNodeId } from '../../contexts/NodeIdContext';
-import type { NodeChange, NodeDimensionChange, NodePositionChange } from '../../types';
import type { ResizeControlProps, ResizeControlLineProps } from './types';
function ResizeControl({
diff --git a/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx b/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx
index 6c0236d8..1fc6f25c 100644
--- a/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx
+++ b/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx
@@ -12,8 +12,8 @@ import type { NodeToolbarProps } from './types';
const nodeEqualityFn = (a?: InternalNode, b?: InternalNode) =>
a?.internals.positionAbsolute.x !== b?.internals.positionAbsolute.x ||
a?.internals.positionAbsolute.y !== b?.internals.positionAbsolute.y ||
- a?.computed.width !== b?.computed.width ||
- a?.computed.height !== b?.computed.height ||
+ a?.measured.width !== b?.measured.width ||
+ a?.measured.height !== b?.measured.height ||
a?.selected !== b?.selected ||
a?.internals.z !== b?.internals.z;
diff --git a/packages/react/src/components/ConnectionLine/index.tsx b/packages/react/src/components/ConnectionLine/index.tsx
index 86655232..54b3f24d 100644
--- a/packages/react/src/components/ConnectionLine/index.tsx
+++ b/packages/react/src/components/ConnectionLine/index.tsx
@@ -64,8 +64,8 @@ const ConnectionLine = ({
}
const fromHandle = handleId ? handleBounds.find((d) => d.id === handleId) : handleBounds[0];
- const fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.computed.width ?? 0) / 2;
- const fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.computed.height ?? 0;
+ const fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.measured.width ?? 0) / 2;
+ const fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.measured.height ?? 0;
const fromX = (fromNode.internals.positionAbsolute.x ?? 0) + fromHandleX;
const fromY = (fromNode.internals.positionAbsolute.y ?? 0) + fromHandleY;
const fromPosition = fromHandle?.position;
diff --git a/packages/react/src/container/Pane/index.tsx b/packages/react/src/container/Pane/index.tsx
index ad2b01ed..0c0eb122 100644
--- a/packages/react/src/container/Pane/index.tsx
+++ b/packages/react/src/container/Pane/index.tsx
@@ -5,13 +5,13 @@
import { useRef, type MouseEvent as ReactMouseEvent, type ReactNode } from 'react';
import { shallow } from 'zustand/shallow';
import cc from 'classcat';
-import { getNodesInside, getEventPosition, SelectionMode } from '@xyflow/system';
+import { getNodesInside, getEventPosition, SelectionMode, type NodeChange, type EdgeChange } from '@xyflow/system';
import { UserSelection } from '../../components/UserSelection';
import { containerStyle } from '../../styles/utils';
import { useStore, useStoreApi } from '../../hooks/useStore';
import { getSelectionChanges } from '../../utils';
-import type { ReactFlowProps, ReactFlowState, NodeChange, EdgeChange } from '../../types';
+import type { ReactFlowProps, ReactFlowState } from '../../types';
type PaneProps = {
isSelecting: boolean;
diff --git a/packages/react/src/hooks/useInternalNode.ts b/packages/react/src/hooks/useInternalNode.ts
new file mode 100644
index 00000000..d16d697b
--- /dev/null
+++ b/packages/react/src/hooks/useInternalNode.ts
@@ -0,0 +1,21 @@
+import { useCallback } from 'react';
+import { shallow } from 'zustand/shallow';
+
+import { useStore } from './useStore';
+import type { InternalNode, Node } from '../types';
+
+/**
+ * Hook for getting an internal node by id
+ *
+ * @public
+ * @param id - id of the node
+ * @returns array with visible node ids
+ */
+export function useInternalNode(id: string): InternalNode | undefined {
+ const node = useStore(
+ useCallback((s) => s.nodeLookup.get(id) as InternalNode | undefined, [id]),
+ shallow
+ );
+
+ return node;
+}
diff --git a/packages/react/src/hooks/useReactFlow.ts b/packages/react/src/hooks/useReactFlow.ts
index 4e83448a..3a022b15 100644
--- a/packages/react/src/hooks/useReactFlow.ts
+++ b/packages/react/src/hooks/useReactFlow.ts
@@ -1,12 +1,5 @@
import { useCallback, useMemo, useRef, useState } from 'react';
-import {
- getElementsToRemove,
- getOverlappingArea,
- isRectObject,
- nodeHasDimensions,
- nodeToRect,
- type Rect,
-} from '@xyflow/system';
+import { getElementsToRemove, getOverlappingArea, isRectObject, nodeToRect, type Rect } from '@xyflow/system';
import useViewportHelper from './useViewportHelper';
import { useStoreApi } from './useStore';
@@ -32,7 +25,7 @@ export function useReactFlow>((id) => {
- return store.getState().nodeLookup.get(id)?.internals.userProvidedNode as NodeType;
+ return store.getState().nodeLookup.get(id)?.internals.userNode as NodeType;
}, []);
const getEdges = useCallback>(() => {
@@ -223,13 +216,9 @@ export function useReactFlow {
- const node =
- isNode(nodeOrRect) && nodeHasDimensions(nodeOrRect)
- ? nodeOrRect
- : (store.getState().nodeLookup.get(nodeOrRect.id)?.internals.userProvidedNode as NodeType);
-
- return node ? nodeToRect(node) : null;
+ const getNodeRect = useCallback(({ id }: { id: string }): Rect | null => {
+ const internalNode = store.getState().nodeLookup.get(id);
+ return internalNode ? nodeToRect(internalNode) : null;
}, []);
const getIntersectingNodes = useCallback>(
diff --git a/packages/react/src/hooks/useViewportHelper.ts b/packages/react/src/hooks/useViewportHelper.ts
index 0e27d933..eb92b310 100644
--- a/packages/react/src/hooks/useViewportHelper.ts
+++ b/packages/react/src/hooks/useViewportHelper.ts
@@ -48,12 +48,12 @@ const useViewportHelper = (): ViewportHelperFunctions => {
return { x, y, zoom };
},
fitView: (options) => {
- const { nodes, width, height, nodeOrigin, minZoom, maxZoom, panZoom } = store.getState();
+ const { nodeLookup, width, height, nodeOrigin, minZoom, maxZoom, panZoom } = store.getState();
return panZoom
? fitView(
{
- nodes,
+ nodeLookup,
width,
height,
nodeOrigin,
diff --git a/packages/react/src/hooks/useVisibleNodeIds.ts b/packages/react/src/hooks/useVisibleNodeIds.ts
index 309391dc..e8d14c8e 100644
--- a/packages/react/src/hooks/useVisibleNodeIds.ts
+++ b/packages/react/src/hooks/useVisibleNodeIds.ts
@@ -1,13 +1,13 @@
-import { getNodesInside } from '@xyflow/system';
+import { useCallback } from 'react';
import { shallow } from 'zustand/shallow';
+import { getNodesInside } from '@xyflow/system';
import { useStore } from './useStore';
import type { Node, ReactFlowState } from '../types';
-import { useCallback } from 'react';
const selector = (onlyRenderVisible: boolean) => (s: ReactFlowState) => {
return onlyRenderVisible
- ? getNodesInside(s.nodes, { x: 0, y: 0, width: s.width, height: s.height }, s.transform, true).map(
+ ? getNodesInside(s.nodeLookup, { x: 0, y: 0, width: s.width, height: s.height }, s.transform, true).map(
(node) => node.id
)
: Array.from(s.nodeLookup.keys());
diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts
index 91be19eb..e7e6b37f 100644
--- a/packages/react/src/index.ts
+++ b/packages/react/src/index.ts
@@ -26,6 +26,7 @@ export { useNodesInitialized, type UseNodesInitializedOptions } from './hooks/us
export { useHandleConnections } from './hooks/useHandleConnections';
export { useNodesData } from './hooks/useNodesData';
export { useConnection } from './hooks/useConnection';
+export { useInternalNode } from './hooks/useInternalNode';
export { useNodeId } from './contexts/NodeIdContext';
export { applyNodeChanges, applyEdgeChanges } from './utils/changes';
diff --git a/packages/react/src/store/index.ts b/packages/react/src/store/index.ts
index 843a2500..3a5686b2 100644
--- a/packages/react/src/store/index.ts
+++ b/packages/react/src/store/index.ts
@@ -2,27 +2,20 @@ import { createWithEqualityFn } from 'zustand/traditional';
import {
clampPosition,
fitView as fitViewSystem,
- adoptUserProvidedNodes,
+ adoptUserNodes,
updateAbsolutePositions,
panBy as panBySystem,
updateNodeDimensions as updateNodeDimensionsSystem,
updateConnectionLookup,
handleParentExpand,
NodeChange,
+ EdgeSelectionChange,
+ NodeSelectionChange,
} from '@xyflow/system';
import { applyEdgeChanges, applyNodeChanges, createSelectionChange, getSelectionChanges } from '../utils/changes';
import getInitialState from './initialState';
-import type {
- ReactFlowState,
- Node,
- Edge,
- EdgeSelectionChange,
- NodeSelectionChange,
- UnselectNodesAndEdgesParams,
- FitViewOptions,
- InternalNode,
-} from '../types';
+import type { ReactFlowState, Node, Edge, UnselectNodesAndEdgesParams, FitViewOptions, InternalNode } from '../types';
const createRFStore = ({
nodes,
@@ -52,7 +45,7 @@ const createRFStore = ({
//
// When this happens, we take the note objects passed by the user and extend them with fields
// relevant for internal React Flow operations.
- adoptUserProvidedNodes(nodes, nodeLookup, { nodeOrigin, elevateNodesOnSelect });
+ adoptUserNodes(nodes, nodeLookup, { nodeOrigin, elevateNodesOnSelect });
set({ nodes });
},
@@ -263,21 +256,22 @@ const createRFStore = ({
triggerEdgeChanges(edgeChanges);
},
setNodeExtent: (nodeExtent) => {
- const { nodes } = get();
+ const { nodeLookup } = get();
+
+ for (const [, node] of nodeLookup) {
+ const positionAbsolute = clampPosition(node.position, nodeExtent);
+
+ nodeLookup.set(node.id, {
+ ...node,
+ internals: {
+ ...node.internals,
+ positionAbsolute,
+ },
+ });
+ }
set({
nodeExtent,
- nodes: nodes.map((node) => {
- const positionAbsolute = clampPosition(node.position, nodeExtent);
-
- return {
- ...node,
- computed: {
- ...node.computed,
- positionAbsolute,
- },
- };
- }),
});
},
panBy: (delta): boolean => {
diff --git a/packages/react/src/store/initialState.ts b/packages/react/src/store/initialState.ts
index 9f373719..cc754976 100644
--- a/packages/react/src/store/initialState.ts
+++ b/packages/react/src/store/initialState.ts
@@ -1,7 +1,7 @@
import {
infiniteExtent,
ConnectionMode,
- adoptUserProvidedNodes,
+ adoptUserNodes,
getNodesBounds,
getViewportForBounds,
Transform,
@@ -35,7 +35,7 @@ const getInitialState = ({
const storeNodes = defaultNodes ?? nodes ?? [];
updateConnectionLookup(connectionLookup, edgeLookup, storeEdges);
- adoptUserProvidedNodes(storeNodes, nodeLookup, {
+ adoptUserNodes(storeNodes, nodeLookup, {
nodeOrigin: [0, 0],
elevateNodesOnSelect: false,
});
diff --git a/packages/react/src/types/changes.ts b/packages/react/src/types/changes.ts
deleted file mode 100644
index adcb484d..00000000
--- a/packages/react/src/types/changes.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import type { XYPosition, Dimensions } from '@xyflow/system';
-
-import type { Node, Edge } from '.';
-
-export type NodeDimensionChange = {
- id: string;
- type: 'dimensions';
- dimensions?: Dimensions;
- resizing?: boolean;
-};
-
-export type NodePositionChange = {
- id: string;
- type: 'position';
- position?: XYPosition;
- positionAbsolute?: XYPosition;
- dragging?: boolean;
-};
-
-export type NodeSelectionChange = {
- id: string;
- type: 'select';
- selected: boolean;
-};
-
-export type NodeRemoveChange = {
- id: string;
- type: 'remove';
-};
-
-export type NodeAddChange = {
- item: NodeType;
- type: 'add';
-};
-
-export type NodeReplaceChange = {
- id: string;
- item: NodeType;
- type: 'replace';
-};
-
-/**
- * Union type of all possible node changes.
- * @public
- */
-export type NodeChange =
- | NodeDimensionChange
- | NodePositionChange
- | NodeSelectionChange
- | NodeRemoveChange
- | NodeAddChange
- | NodeReplaceChange;
-
-export type EdgeSelectionChange = NodeSelectionChange;
-export type EdgeRemoveChange = NodeRemoveChange;
-export type EdgeAddChange = {
- item: EdgeType;
- type: 'add';
-};
-
-export type EdgeReplaceChange = {
- id: string;
- item: EdgeType;
- type: 'replace';
-};
-
-export type EdgeChange =
- | EdgeSelectionChange
- | EdgeRemoveChange
- | EdgeAddChange
- | EdgeReplaceChange;
diff --git a/packages/react/src/types/general.ts b/packages/react/src/types/general.ts
index 302ffeee..8b55920f 100644
--- a/packages/react/src/types/general.ts
+++ b/packages/react/src/types/general.ts
@@ -12,9 +12,11 @@ import {
XYPosition,
OnBeforeDeleteBase,
Connection,
+ NodeChange,
+ EdgeChange,
} from '@xyflow/system';
-import type { NodeChange, EdgeChange, Node, Edge, ReactFlowInstance, EdgeProps, NodeProps } from '.';
+import type { Node, Edge, ReactFlowInstance, EdgeProps, NodeProps } from '.';
export type OnNodesChange = (changes: NodeChange[]) => void;
export type OnEdgesChange = (changes: EdgeChange[]) => void;
diff --git a/packages/react/src/types/index.ts b/packages/react/src/types/index.ts
index 6ee8dada..f18123f2 100644
--- a/packages/react/src/types/index.ts
+++ b/packages/react/src/types/index.ts
@@ -1,6 +1,5 @@
export * from './nodes';
export * from './edges';
-export * from './changes';
export * from './component-props';
export * from './general';
export * from './store';
diff --git a/packages/react/src/types/store.ts b/packages/react/src/types/store.ts
index eed7b9a3..416f56f3 100644
--- a/packages/react/src/types/store.ts
+++ b/packages/react/src/types/store.ts
@@ -25,12 +25,13 @@ import {
type EdgeLookup,
type ConnectionLookup,
type NodeLookup,
+ NodeChange,
+ EdgeChange,
} from '@xyflow/system';
import type {
Edge,
Node,
- NodeChange,
OnNodesChange,
OnEdgesChange,
DefaultEdgeOptions,
@@ -43,7 +44,6 @@ import type {
OnNodeDrag,
OnBeforeDelete,
IsValidConnection,
- EdgeChange,
InternalNode,
} from '.';
diff --git a/packages/react/src/utils/changes.ts b/packages/react/src/utils/changes.ts
index e4d0464d..44af2451 100644
--- a/packages/react/src/utils/changes.ts
+++ b/packages/react/src/utils/changes.ts
@@ -1,14 +1,13 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
-import { EdgeLookup, NodeLookup } from '@xyflow/system';
-import type {
- Node,
- Edge,
+import {
+ EdgeLookup,
+ NodeLookup,
EdgeChange,
NodeChange,
NodeSelectionChange,
EdgeSelectionChange,
- InternalNode,
-} from '../types';
+} from '@xyflow/system';
+import type { Node, Edge, InternalNode } from '../types';
// This function applies changes to nodes or edges that are triggered by React Flow internally.
// When you drag a node for example, React Flow will send a position change update.
@@ -97,9 +96,9 @@ function applyChange(change: any, element: any): any {
case 'dimensions': {
if (typeof change.dimensions !== 'undefined') {
- element.computed ??= {};
- element.computed.width = change.dimensions.width;
- element.computed.height = change.dimensions.height;
+ element.measured ??= {};
+ element.measured.width = change.dimensions.width;
+ element.measured.height = change.dimensions.height;
if (change.resizing) {
element.width = change.dimensions.width;
diff --git a/packages/svelte/src/lib/store/utils.ts b/packages/svelte/src/lib/store/utils.ts
index 0f72d746..a6ba38de 100644
--- a/packages/svelte/src/lib/store/utils.ts
+++ b/packages/svelte/src/lib/store/utils.ts
@@ -7,7 +7,7 @@ import {
type Writable
} from 'svelte/store';
import {
- adoptUserProvidedNodes,
+ adoptUserNodes,
updateConnectionLookup,
type Viewport,
type PanZoomInstance,
@@ -141,7 +141,7 @@ export const createNodesStore = (
let elevateNodesOnSelect = true;
const _set = (nds: Node[]): Node[] => {
- const nextNodes = adoptUserProvidedNodes(nds, nodeLookup, {
+ const nextNodes = adoptUserNodes(nds, nodeLookup, {
elevateNodesOnSelect,
defaults
});
diff --git a/packages/system/src/types/general.ts b/packages/system/src/types/general.ts
index a7c6665b..2fd0e3ab 100644
--- a/packages/system/src/types/general.ts
+++ b/packages/system/src/types/general.ts
@@ -127,7 +127,7 @@ export type SelectionRect = Rect & {
export type OnError = (id: string, message: string) => void;
-export type UpdateNodePositions = (dragItems: NodeDragItem[] | NodeBase[], dragging?: boolean) => void;
+export type UpdateNodePositions = (dragItems: NodeDragItem[] | InternalNodeBase[], dragging?: boolean) => void;
export type PanBy = (delta: XYPosition) => boolean;
export type UpdateConnection = (params: {
diff --git a/packages/system/src/types/nodes.ts b/packages/system/src/types/nodes.ts
index 2d9dfd5d..7b85fef8 100644
--- a/packages/system/src/types/nodes.ts
+++ b/packages/system/src/types/nodes.ts
@@ -59,27 +59,25 @@ export type NodeBase<
*/
origin?: NodeOrigin;
handles?: NodeHandle[];
- computed?: {
+ measured?: {
width?: number;
height?: number;
};
};
export type InternalNodeBase = NodeType & {
- computed: {
+ measured: {
width?: number;
height?: number;
};
- // Only used internally
internals: {
positionAbsolute: XYPosition;
z: number;
// @todo should we rename this to "handles" and use same type as node.handles?
isParent: boolean;
- /** Holds a reference to the original node object provided by the user
- * (which may lack some fields, like `computed` or `[internalSymbol]`. Used
- * as an optimization to avoid certain operations. */
- userProvidedNode: NodeType;
+ /** Holds a reference to the original node object provided by the user.
+ * Used as an optimization to avoid certain operations. */
+ userNode: NodeType;
handleBounds?: NodeHandleBounds;
};
};
@@ -123,7 +121,7 @@ export type NodeDragItem = {
position: XYPosition;
// distance from the mouse cursor to the node when start dragging
distance: XYPosition;
- computed: {
+ measured: {
width: number | null;
height: number | null;
};
diff --git a/packages/system/src/utils/edges/positions.ts b/packages/system/src/utils/edges/positions.ts
index 33fa59ee..de8416db 100644
--- a/packages/system/src/utils/edges/positions.ts
+++ b/packages/system/src/utils/edges/positions.ts
@@ -20,7 +20,7 @@ function isNodeInitialized(node: InternalNodeBase): boolean {
return (
node &&
!!(node.internals.handleBounds || node.handles?.length) &&
- !!(node.computed.width || node.width || node.initialWidth)
+ !!(node.measured.width || node.width || node.initialWidth)
);
}
diff --git a/packages/system/src/utils/general.ts b/packages/system/src/utils/general.ts
index 5fab4f49..b8af19bc 100644
--- a/packages/system/src/utils/general.ts
+++ b/packages/system/src/utils/general.ts
@@ -66,23 +66,23 @@ export const boxToRect = ({ x, y, x2, y2 }: Box): Rect => ({
height: y2 - y,
});
-export const nodeToRect = (node: InternalNodeBase, nodeOrigin: NodeOrigin = [0, 0]): Rect => {
+export const nodeToRect = (node: InternalNodeBase | NodeBase, nodeOrigin: NodeOrigin = [0, 0]): Rect => {
const { positionAbsolute } = getNodePositionWithOrigin(node, node.origin || nodeOrigin);
return {
...positionAbsolute,
- width: node.computed?.width ?? node.width ?? 0,
- height: node.computed?.height ?? node.height ?? 0,
+ width: node.measured?.width ?? node.width ?? 0,
+ height: node.measured?.height ?? node.height ?? 0,
};
};
-export const nodeToBox = (node: InternalNodeBase, nodeOrigin: NodeOrigin = [0, 0]): Box => {
+export const nodeToBox = (node: InternalNodeBase | NodeBase, nodeOrigin: NodeOrigin = [0, 0]): Box => {
const { positionAbsolute } = getNodePositionWithOrigin(node, node.origin || nodeOrigin);
return {
...positionAbsolute,
- x2: positionAbsolute.x + (node.computed?.width ?? node.width ?? 0),
- y2: positionAbsolute.y + (node.computed?.height ?? node.height ?? 0),
+ x2: positionAbsolute.x + (node.measured?.width ?? node.width ?? 0),
+ y2: positionAbsolute.y + (node.measured?.height ?? node.height ?? 0),
};
};
@@ -208,14 +208,14 @@ export function getNodeDimensions(
node: NodeType
): { width: number; height: number } {
return {
- width: node.computed?.width ?? node.width ?? node.initialWidth ?? 0,
- height: node.computed?.height ?? node.height ?? node.initialHeight ?? 0,
+ width: node.measured?.width ?? node.width ?? node.initialWidth ?? 0,
+ height: node.measured?.height ?? node.height ?? node.initialHeight ?? 0,
};
}
export function nodeHasDimensions(node: NodeType): boolean {
return (
- (node.computed?.width ?? node.width ?? node.initialWidth) !== undefined &&
- (node.computed?.height ?? node.height ?? node.initialHeight) !== undefined
+ (node.measured?.width ?? node.width ?? node.initialWidth) !== undefined &&
+ (node.measured?.height ?? node.height ?? node.initialHeight) !== undefined
);
}
diff --git a/packages/system/src/utils/graph.ts b/packages/system/src/utils/graph.ts
index 9df39893..c53add40 100644
--- a/packages/system/src/utils/graph.ts
+++ b/packages/system/src/utils/graph.ts
@@ -50,7 +50,7 @@ export const isNodeBase = (element: any):
export const isInternalNodeBase = (
element: any
-): element is NodeType => 'id' in element && 'computed' in element && !('source' in element) && !('target' in element);
+): element is NodeType => 'id' in element && 'internals' in element && !('source' in element) && !('target' in element);
/**
* Pass in a node, and get connected nodes where edge.source === node.id
@@ -106,7 +106,7 @@ export const getIncomers = {
if (!node) {
@@ -133,10 +133,13 @@ export const getNodePositionWithOrigin = (
return {
position,
- positionAbsolute: {
- x: node.internals.positionAbsolute.x - offsetX,
- y: node.internals.positionAbsolute.y - offsetY,
- },
+ positionAbsolute:
+ 'internals' in node
+ ? {
+ x: node.internals.positionAbsolute.x - offsetX,
+ y: node.internals.positionAbsolute.y - offsetY,
+ }
+ : position,
};
};
@@ -165,7 +168,6 @@ export const getNodesBounds = (
const box = nodes.reduce(
(currBox, node) => {
- // @ts-expect-error
const nodePos = getNodePositionWithOrigin(node, node.origin || params.nodeOrigin);
return getBoundsOfBoxes(
currBox,
@@ -238,9 +240,9 @@ export const getNodesInside = (
const visibleNodes: NodeType[] = [];
for (const [, node] of nodeLookup) {
- const { computed, selectable = true, hidden = false } = node;
- const width = computed?.width ?? node.width ?? node.initialWidth ?? null;
- const height = computed?.height ?? node.height ?? node.initialHeight ?? null;
+ const { measured, selectable = true, hidden = false } = node;
+ const width = measured.width ?? node.width ?? node.initialWidth ?? null;
+ const height = measured.height ?? node.height ?? node.initialHeight ?? null;
if ((excludeNonSelectableNodes && !selectable) || hidden) {
continue;
@@ -286,7 +288,7 @@ export function fitView, Options exte
const filteredNodes: InternalNodeBase[] = [];
nodeLookup.forEach((n) => {
- const isVisible = n.computed?.width && n.computed?.height && (options?.includeHiddenNodes || !n.hidden);
+ const isVisible = n.measured.width && n.measured.height && (options?.includeHiddenNodes || !n.hidden);
if (
isVisible &&
@@ -331,7 +333,7 @@ function clampNodeExtent(
if (!extent || extent === 'parent') {
return extent;
}
- return [extent[0], [extent[1][0] - (node.computed?.width ?? 0), extent[1][1] - (node.computed?.height ?? 0)]];
+ return [extent[0], [extent[1][0] - (node.measured?.width ?? 0), extent[1][1] - (node.measured?.height ?? 0)]];
}
/**
@@ -367,10 +369,10 @@ export function calculateNodePosition({
if (!parentNode) {
onError?.('005', errorMessages['error005']());
} else {
- const nodeWidth = node.computed.width;
- const nodeHeight = node.computed.height;
- const parentWidth = parentNode.computed.width;
- const parentHeight = parentNode.computed.height;
+ const nodeWidth = node.measured.width;
+ const nodeHeight = node.measured.height;
+ const parentWidth = parentNode.measured.width;
+ const parentHeight = parentNode.measured.height;
if (nodeWidth && nodeHeight && parentWidth && parentHeight) {
const currNodeOrigin = node.origin || nodeOrigin;
diff --git a/packages/system/src/utils/store.ts b/packages/system/src/utils/store.ts
index b43534eb..e82e2dea 100644
--- a/packages/system/src/utils/store.ts
+++ b/packages/system/src/utils/store.ts
@@ -70,7 +70,7 @@ type UpdateNodesOptions = {
defaults?: Partial;
};
-export function adoptUserProvidedNodes(
+export function adoptUserNodes(
nodes: NodeType[],
nodeLookup: Map>,
options: UpdateNodesOptions = {
@@ -84,33 +84,31 @@ export function adoptUserProvidedNodes(
const selectedNodeZ: number = options?.elevateNodesOnSelect ? 1000 : 0;
const parentNodeIds = new Set();
- nodes.forEach((n) => {
- const currentStoreNode = tmpLookup.get(n.id);
+ nodes.forEach((userNode) => {
+ const currentStoreNode = tmpLookup.get(userNode.id);
- if (n.parentNode) {
- parentNodeIds.add(n.parentNode);
+ if (userNode.parentNode) {
+ parentNodeIds.add(userNode.parentNode);
}
- if (n === currentStoreNode?.internals.userProvidedNode) {
- nodeLookup.set(n.id, currentStoreNode);
+ if (userNode === currentStoreNode?.internals.userNode) {
+ nodeLookup.set(userNode.id, currentStoreNode);
} else {
- const node: InternalNodeBase = {
+ nodeLookup.set(userNode.id, {
...options.defaults,
- ...n,
- computed: {
- width: n.computed?.width,
- height: n.computed?.height,
+ ...userNode,
+ measured: {
+ width: userNode.measured?.width,
+ height: userNode.measured?.height,
},
internals: {
- positionAbsolute: n.position,
+ positionAbsolute: userNode.position,
handleBounds: currentStoreNode?.internals?.handleBounds,
- z: (isNumeric(n.zIndex) ? n.zIndex : 0) + (n.selected ? selectedNodeZ : 0),
- userProvidedNode: n,
+ z: (isNumeric(userNode.zIndex) ? userNode.zIndex : 0) + (userNode.selected ? selectedNodeZ : 0),
+ userNode,
isParent: false,
},
- };
-
- nodeLookup.set(node.id, node);
+ });
}
});
@@ -241,14 +239,14 @@ export function updateNodeDimensions(
const doUpdate = !!(
dimensions.width &&
dimensions.height &&
- (node.computed?.width !== dimensions.width || node.computed?.height !== dimensions.height || update.force)
+ (node.measured?.width !== dimensions.width || node.measured?.height !== dimensions.height || update.force)
);
if (doUpdate) {
const newNode = {
...node,
- computed: {
- ...node.computed,
+ measured: {
+ ...node.measured,
...dimensions,
},
internals: {
diff --git a/packages/system/src/xydrag/XYDrag.ts b/packages/system/src/xydrag/XYDrag.ts
index 7d2fbaef..573b87af 100644
--- a/packages/system/src/xydrag/XYDrag.ts
+++ b/packages/system/src/xydrag/XYDrag.ts
@@ -139,10 +139,10 @@ export function XYDrag voi
if (dragItems.length > 1 && nodeExtent && !n.extent) {
const { positionAbsolute } = n.internals;
const x1 = positionAbsolute.x - nodesBox.x + nodeExtent[0][0];
- const x2 = positionAbsolute.x + (n.computed?.width ?? 0) - nodesBox.x2 + nodeExtent[1][0];
+ const x2 = positionAbsolute.x + (n.measured?.width ?? 0) - nodesBox.x2 + nodeExtent[1][0];
const y1 = positionAbsolute.y - nodesBox.y + nodeExtent[0][1];
- const y2 = positionAbsolute.y + (n.computed?.height ?? 0) - nodesBox.y2 + nodeExtent[1][1];
+ const y2 = positionAbsolute.y + (n.measured?.height ?? 0) - nodesBox.y2 + nodeExtent[1][1];
adjustedNodeExtent = [
[x1, y1],
diff --git a/packages/system/src/xydrag/utils.ts b/packages/system/src/xydrag/utils.ts
index e958cf64..e4570b6e 100644
--- a/packages/system/src/xydrag/utils.ts
+++ b/packages/system/src/xydrag/utils.ts
@@ -65,9 +65,9 @@ export function getDragItems(
internals: {
positionAbsolute: internalNode.internals.positionAbsolute || { x: 0, y: 0 },
},
- computed: {
- width: internalNode.computed.width || 0,
- height: internalNode.computed.height || 0,
+ measured: {
+ width: internalNode.measured.width || 0,
+ height: internalNode.measured.height || 0,
},
});
}
@@ -93,8 +93,8 @@ export function getEventHandlerParams({
return {
...node,
position: n.position,
- computed: {
- ...n.computed,
+ measured: {
+ ...n.measured,
},
};
});
diff --git a/packages/system/src/xyresizer/XYResizer.ts b/packages/system/src/xyresizer/XYResizer.ts
index 1953b327..ce1bbd12 100644
--- a/packages/system/src/xyresizer/XYResizer.ts
+++ b/packages/system/src/xyresizer/XYResizer.ts
@@ -71,15 +71,15 @@ export type XYResizerInstance = {
function nodeToParentExtent(node: NodeBase): CoordinateExtent {
return [
[0, 0],
- [node.computed!.width!, node.computed!.height!],
+ [node.measured!.width!, node.measured!.height!],
];
}
function nodeToChildExtent(child: NodeBase, parent: NodeBase, nodeOrigin: NodeOrigin): CoordinateExtent {
const x = parent.position.x + child.position.x;
const y = parent.position.y + child.position.y;
- const width = child.computed!.width! ?? 0;
- const height = child.computed!.height! ?? 0;
+ const width = child.measured!.width! ?? 0;
+ const height = child.measured!.height! ?? 0;
const originOffsetX = nodeOrigin[0] * width;
const originOffsetY = nodeOrigin[1] * height;
@@ -121,8 +121,8 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange }: XYResize
const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
prevValues = {
- width: node.computed?.width ?? 0,
- height: node.computed?.height ?? 0,
+ width: node.measured?.width ?? 0,
+ height: node.measured?.height ?? 0,
x: node.position.x ?? 0,
y: node.position.y ?? 0,
};