From b511b15ef8b01ca97c860f3538ad1bd18e7a8639 Mon Sep 17 00:00:00 2001 From: moklick Date: Thu, 1 Dec 2022 20:28:37 +0100 Subject: [PATCH] refactor(core): make it possible to batch changes --- .../core/src/container/NodeRenderer/index.tsx | 1 + packages/core/src/store/index.ts | 15 +++- packages/core/src/types/changes.ts | 1 + packages/core/src/types/general.ts | 9 +- packages/core/src/utils/changes.ts | 85 ++++++++++--------- 5 files changed, 67 insertions(+), 44 deletions(-) diff --git a/packages/core/src/container/NodeRenderer/index.tsx b/packages/core/src/container/NodeRenderer/index.tsx index 70a62dfe..389cd2d0 100644 --- a/packages/core/src/container/NodeRenderer/index.tsx +++ b/packages/core/src/container/NodeRenderer/index.tsx @@ -57,6 +57,7 @@ const NodeRenderer = (props: NodeRendererProps) => { nodeElement: entry.target as HTMLDivElement, forceUpdate: true, })); + updateNodeDimensions(updates); }); diff --git a/packages/core/src/store/index.ts b/packages/core/src/store/index.ts index 5ffd64c3..e05f2048 100644 --- a/packages/core/src/store/index.ts +++ b/packages/core/src/store/index.ts @@ -102,7 +102,12 @@ const createRFStore = () => onNodesChange?.(changes); } }, - updateNodePositions: (nodeDragItems: NodeDragItem[] | Node[], positionChanged = true, dragging = false) => { + updateNodePositions: ( + nodeDragItems: NodeDragItem[] | Node[], + positionChanged = true, + dragging = false, + applyChanges = true + ) => { const { onNodesChange, nodeInternals, hasDefaultNodes, nodeOrigin } = get(); if (hasDefaultNodes || onNodesChange) { @@ -128,9 +133,15 @@ const createRFStore = () => set({ nodeInternals: nextNodeInternals }); } - onNodesChange?.(changes); + if (applyChanges) { + onNodesChange?.(changes); + } } + + return changes; } + + return null; }, addSelectedNodes: (selectedNodeIds: string[]) => { const { multiSelectionActive, nodeInternals, edges } = get(); diff --git a/packages/core/src/types/changes.ts b/packages/core/src/types/changes.ts index b4395803..ec2f6693 100644 --- a/packages/core/src/types/changes.ts +++ b/packages/core/src/types/changes.ts @@ -8,6 +8,7 @@ export type NodeDimensionChange = { id: string; type: 'dimensions'; dimensions: Dimensions; + updateStyle?: boolean; }; export type NodePositionChange = { diff --git a/packages/core/src/types/general.ts b/packages/core/src/types/general.ts index 1ceb1cff..2daed27b 100644 --- a/packages/core/src/types/general.ts +++ b/packages/core/src/types/general.ts @@ -3,7 +3,7 @@ import type { MouseEvent as ReactMouseEvent, ComponentType, MemoExoticComponent import type { D3DragEvent, Selection as D3Selection, SubjectPosition, ZoomBehavior } from 'd3'; import type { XYPosition, Rect, Transform, CoordinateExtent } from './utils'; -import type { NodeChange, EdgeChange } from './changes'; +import type { NodeChange, EdgeChange, NodePositionChange } from './changes'; import type { Node, NodeInternals, @@ -215,7 +215,12 @@ export type ReactFlowActions = { setEdges: (edges: Edge[]) => void; setDefaultNodesAndEdges: (nodes?: Node[], edges?: Edge[]) => void; updateNodeDimensions: (updates: NodeDimensionUpdate[]) => void; - updateNodePositions: (nodeDragItems: NodeDragItem[] | Node[], positionChanged: boolean, dragging: boolean) => void; + updateNodePositions: ( + nodeDragItems: NodeDragItem[] | Node[], + positionChanged: boolean, + dragging: boolean, + applyChanges?: boolean + ) => NodePositionChange[] | null; resetSelectedElements: () => void; unselectNodesAndEdges: (params?: UnselectNodesAndEdgesParams) => void; addSelectedNodes: (nodeIds: string[]) => void; diff --git a/packages/core/src/utils/changes.ts b/packages/core/src/utils/changes.ts index 897c1ffb..edfd0719 100644 --- a/packages/core/src/utils/changes.ts +++ b/packages/core/src/utils/changes.ts @@ -50,58 +50,63 @@ function applyChanges(changes: any[], elements: any[]): any[] { const initElements: any[] = changes.filter((c) => c.type === 'add').map((c) => c.item); return elements.reduce((res: any[], item: any) => { - const currentChange = changes.find((c) => c.id === item.id); + const currentChanges = changes.filter((c) => c.id === item.id); - if (currentChange) { - switch (currentChange.type) { - case 'select': { - res.push({ ...item, selected: currentChange.selected }); - return res; - } - case 'position': { - const updateItem = { ...item }; + if (currentChanges.length === 0) { + res.push(item); + return res; + } - if (typeof currentChange.position !== 'undefined') { - updateItem.position = currentChange.position; + const updateItem = { ...item }; + + for (const currentChange of currentChanges) { + if (currentChange) { + switch (currentChange.type) { + case 'select': { + updateItem.selected = currentChange.selected; + break; } + case 'position': { + if (typeof currentChange.position !== 'undefined') { + updateItem.position = currentChange.position; + } - if (typeof currentChange.positionAbsolute !== 'undefined') { - updateItem.positionAbsolute = currentChange.positionAbsolute; + if (typeof currentChange.positionAbsolute !== 'undefined') { + updateItem.positionAbsolute = currentChange.positionAbsolute; + } + + if (typeof currentChange.dragging !== 'undefined') { + updateItem.dragging = currentChange.dragging; + } + + if (updateItem.expandParent) { + handleParentExpand(res, updateItem); + } + break; } + case 'dimensions': { + if (typeof currentChange.dimensions !== 'undefined') { + updateItem.width = currentChange.dimensions.width; + updateItem.height = currentChange.dimensions.height; + } - if (typeof currentChange.dragging !== 'undefined') { - updateItem.dragging = currentChange.dragging; + if (typeof currentChange.updateStyle !== 'undefined') { + updateItem.style = { ...(updateItem.style || {}), ...currentChange.dimensions }; + } + + if (updateItem.expandParent) { + handleParentExpand(res, updateItem); + } + break; } - - if (updateItem.expandParent) { - handleParentExpand(res, updateItem); + case 'remove': { + return res; } - - res.push(updateItem); - return res; - } - case 'dimensions': { - const updateItem = { ...item }; - - if (typeof currentChange.dimensions !== 'undefined') { - updateItem.width = currentChange.dimensions.width; - updateItem.height = currentChange.dimensions.height; - } - - if (updateItem.expandParent) { - handleParentExpand(res, updateItem); - } - - res.push(updateItem); - return res; - } - case 'remove': { - return res; } } } - res.push(item); + res.push(updateItem); return res; }, initElements); }