diff --git a/src/components/Nodes/utils.ts b/src/components/Nodes/utils.ts new file mode 100644 index 00000000..82d9322e --- /dev/null +++ b/src/components/Nodes/utils.ts @@ -0,0 +1,41 @@ +import { HandleElement, Position } from '../../types'; +import { getDimensions } from '../../utils'; + +export const getHandleBounds = ( + selector: string, + nodeElement: HTMLDivElement, + parentBounds: ClientRect | DOMRect, + k: number +): HandleElement[] | null => { + const handles = nodeElement.querySelectorAll(selector); + + if (!handles || !handles.length) { + return null; + } + + const handlesArray = Array.from(handles) as HTMLDivElement[]; + + return handlesArray.map( + (handle): HandleElement => { + const bounds = handle.getBoundingClientRect(); + const dimensions = getDimensions(handle); + const nodeIdAttr = handle.getAttribute('data-nodeid'); + const handlePosition = (handle.getAttribute('data-handlepos') as unknown) as Position; + const nodeIdSplitted = nodeIdAttr ? nodeIdAttr.split('__') : null; + + let handleId = null; + + if (nodeIdSplitted) { + handleId = (nodeIdSplitted.length ? nodeIdSplitted[1] : nodeIdSplitted) as string; + } + + return { + id: handleId, + position: handlePosition, + x: (bounds.left - parentBounds.left) * (1 / k), + y: (bounds.top - parentBounds.top) * (1 / k), + ...dimensions, + }; + } + ); +}; diff --git a/src/components/Nodes/wrapNode.tsx b/src/components/Nodes/wrapNode.tsx index 8e0a7ced..ee491c9a 100644 --- a/src/components/Nodes/wrapNode.tsx +++ b/src/components/Nodes/wrapNode.tsx @@ -3,58 +3,9 @@ import { DraggableCore } from 'react-draggable'; import cx from 'classnames'; import { ResizeObserver } from 'resize-observer'; -import { getDimensions } from '../../utils'; import { Provider } from '../../contexts/NodeIdContext'; import store from '../../store'; -import { - Node, - XYPosition, - HandleElement, - Position, - Transform, - ElementId, - NodeComponentProps, - WrapNodeProps, -} from '../../types'; - -const getHandleBounds = ( - selector: string, - nodeElement: HTMLDivElement, - parentBounds: ClientRect | DOMRect, - k: number -): HandleElement[] | null => { - const handles = nodeElement.querySelectorAll(selector); - - if (!handles || !handles.length) { - return null; - } - - const handlesArray = Array.from(handles) as HTMLDivElement[]; - - return handlesArray.map( - (handle): HandleElement => { - const bounds = handle.getBoundingClientRect(); - const dimensions = getDimensions(handle); - const nodeIdAttr = handle.getAttribute('data-nodeid'); - const handlePosition = (handle.getAttribute('data-handlepos') as unknown) as Position; - const nodeIdSplitted = nodeIdAttr ? nodeIdAttr.split('__') : null; - - let handleId = null; - - if (nodeIdSplitted) { - handleId = (nodeIdSplitted.length ? nodeIdSplitted[1] : nodeIdSplitted) as string; - } - - return { - id: handleId, - position: handlePosition, - x: (bounds.left - parentBounds.left) * (1 / k), - y: (bounds.top - parentBounds.top) * (1 / k), - ...dimensions, - }; - } - ); -}; +import { Node, XYPosition, Transform, ElementId, NodeComponentProps, WrapNodeProps } from '../../types'; const onStart = ( evt: MouseEvent, @@ -153,14 +104,7 @@ export default (NodeComponent: ComponentType) => { return; } - const storeState = store.getState(); - const bounds = nodeElement.current.getBoundingClientRect(); - const dimensions = getDimensions(nodeElement.current); - const handleBounds = { - source: getHandleBounds('.source', nodeElement.current, bounds, storeState.transform[2]), - target: getHandleBounds('.target', nodeElement.current, bounds, storeState.transform[2]), - }; - store.dispatch.updateNodeData({ id, ...dimensions, handleBounds }); + store.dispatch.updateNodeDimensions({ id, nodeElement: nodeElement.current }); }; useEffect(() => { diff --git a/src/store/index.ts b/src/store/index.ts index d8a0a992..19ed9dda 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -2,6 +2,9 @@ import { createStore, Action, action } from 'easy-peasy'; import isEqual from 'fast-deep-equal'; import { Selection as D3Selection, ZoomBehavior } from 'd3'; +import { getDimensions } from '../utils'; +import { getHandleBounds } from '../components/Nodes/utils'; + import { getNodesInside, getConnectedEdges, getRectOfNodes } from '../utils/graph'; import { ElementId, @@ -14,7 +17,6 @@ import { XYPosition, OnConnectFunc, SelectionRect, - HandleElement, } from '../types'; type TransformXYK = { @@ -28,14 +30,9 @@ type NodePosUpdate = { pos: XYPosition; }; -type NodeUpdate = { +type NodeDimensionUpdate = { id: ElementId; - width: number; - height: number; - handleBounds: { - source: HandleElement[] | null; - target: HandleElement[] | null; - }; + nodeElement: HTMLDivElement; }; type SelectionUpdate = { @@ -86,7 +83,7 @@ export interface StoreModel { setEdges: Action; - updateNodeData: Action; + updateNodeDimensions: Action; updateNodePos: Action; @@ -152,12 +149,20 @@ const storeModel: StoreModel = { state.edges = edges; }), - updateNodeData: action((state, { id, ...data }) => { + updateNodeDimensions: action((state, { id, nodeElement }) => { + const bounds = nodeElement.getBoundingClientRect(); + const dimensions = getDimensions(nodeElement); + const handleBounds = { + source: getHandleBounds('.source', nodeElement, bounds, state.transform[2]), + target: getHandleBounds('.target', nodeElement, bounds, state.transform[2]), + }; + state.nodes.forEach(n => { if (n.id === id) { n.__rg = { ...n.__rg, - ...data, + ...dimensions, + handleBounds, }; } });