From 27b5de2d96d4000bf5f0210dedd0496e602e8947 Mon Sep 17 00:00:00 2001 From: moklick Date: Thu, 26 May 2022 19:55:03 +0200 Subject: [PATCH] refactor(internals): use non enumerable props --- src/components/ConnectionLine/index.tsx | 6 ++++-- src/container/EdgeRenderer/utils.ts | 9 +++++---- src/container/NodeRenderer/index.tsx | 5 +++-- src/hooks/useVisibleEdges.ts | 4 ++-- src/store/index.ts | 4 ++-- src/store/utils.ts | 24 +++++++++++++++++------- src/types/nodes.ts | 7 ++++--- src/utils/index.ts | 4 ++++ 8 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/components/ConnectionLine/index.tsx b/src/components/ConnectionLine/index.tsx index 5a287ebf9..cd0e0b4c5 100644 --- a/src/components/ConnectionLine/index.tsx +++ b/src/components/ConnectionLine/index.tsx @@ -6,6 +6,7 @@ import { getBezierPath } from '../Edges/BezierEdge'; import { getSmoothStepPath } from '../Edges/SmoothStepEdge'; import { ConnectionLineType, ConnectionLineComponent, HandleType, Node, ReactFlowState, Position } from '../../types'; import { getSimpleBezierPath } from '../Edges/SimpleBezierEdge'; +import { handleBoundsSymbol } from '../../utils'; interface ConnectionLineProps { connectionNodeId: string; @@ -37,12 +38,13 @@ export default ({ const { nodeInternals, transform } = useStore(selector, shallow); const fromNode = useRef(nodeInternals.get(nodeId)); + const fromHandleBounds = fromNode.current?.[handleBoundsSymbol]; - if (!fromNode.current || !isConnectable || !fromNode.current.handleBounds?.[connectionHandleType]) { + if (!fromNode.current || !isConnectable || !fromHandleBounds?.[connectionHandleType]) { return null; } - const handleBound = fromNode.current.handleBounds?.[connectionHandleType]; + const handleBound = fromHandleBounds[connectionHandleType]; const fromHandle = handleId ? handleBound?.find((d) => d.id === handleId) : handleBound?.[0]; const fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.current?.width ?? 0) / 2; const fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.current?.height ?? 0; diff --git a/src/container/EdgeRenderer/utils.ts b/src/container/EdgeRenderer/utils.ts index caa18181a..8a77a1211 100644 --- a/src/container/EdgeRenderer/utils.ts +++ b/src/container/EdgeRenderer/utils.ts @@ -13,7 +13,7 @@ import { Transform, XYPosition, } from '../../types'; -import { rectToBox } from '../../utils'; +import { handleBoundsSymbol, rectToBox } from '../../utils'; export type CreateEdgeTypes = (edgeTypes: EdgeTypes) => EdgeTypesWrapped; @@ -168,10 +168,11 @@ export function isEdgeVisible({ export function getNodeData(nodeInternals: NodeInternals, nodeId: string): [Rect, NodeHandleBounds | null, boolean] { const node = nodeInternals.get(nodeId); - const handleBounds = node?.handleBounds; + const handleBounds = node?.[handleBoundsSymbol] || null; + const isInvalid = !node || - !node.handleBounds || + !handleBounds || !node.width || !node.height || typeof node.positionAbsolute?.x === 'undefined' || @@ -184,7 +185,7 @@ export function getNodeData(nodeInternals: NodeInternals, nodeId: string): [Rect width: node?.width || 0, height: node?.height || 0, }, - handleBounds || null, + handleBounds, !isInvalid, ]; } diff --git a/src/container/NodeRenderer/index.tsx b/src/container/NodeRenderer/index.tsx index 671559e70..d347c4bbf 100644 --- a/src/container/NodeRenderer/index.tsx +++ b/src/container/NodeRenderer/index.tsx @@ -11,6 +11,7 @@ import { ReactFlowState, WrapNodeProps, } from '../../types'; +import { isParentSymbol, zSymbol } from '../../utils'; interface NodeRendererProps { nodeTypes: NodeTypesWrapped; @@ -117,8 +118,8 @@ const NodeRenderer = (props: NodeRendererProps) => { isConnectable={isConnectable} resizeObserver={resizeObserver} dragHandle={node.dragHandle} - zIndex={node.z ?? 0} - isParent={!!node.isParent} + zIndex={node[zSymbol] ?? 0} + isParent={!!node[isParentSymbol]} noDragClassName={props.noDragClassName} noPanClassName={props.noPanClassName} /> diff --git a/src/hooks/useVisibleEdges.ts b/src/hooks/useVisibleEdges.ts index 763f41ee6..c5f99a054 100644 --- a/src/hooks/useVisibleEdges.ts +++ b/src/hooks/useVisibleEdges.ts @@ -3,7 +3,7 @@ import { useCallback } from 'react'; import { useStore } from '../store'; import { isEdgeVisible } from '../container/EdgeRenderer/utils'; import { ReactFlowState, NodeInternals, Edge } from '../types'; -import { isNumeric } from '../utils'; +import { isNumeric, zSymbol } from '../utils'; const defaultEdgeTree = [{ level: 0, isMaxLevel: true, edges: [] }]; @@ -17,7 +17,7 @@ function groupEdgesByZLevel(edges: Edge[], nodeInternals: NodeInternals, elevate if (elevateEdgesOnSelect) { z = hasZIndex ? edge.zIndex! - : Math.max(nodeInternals.get(edge.source)?.z || 0, nodeInternals.get(edge.target)?.z || 0); + : Math.max(nodeInternals.get(edge.source)?.[zSymbol] || 0, nodeInternals.get(edge.target)?.[zSymbol] || 0); } if (tree[z]) { diff --git a/src/store/index.ts b/src/store/index.ts index e5c271a98..d6ccde3a5 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,7 +1,7 @@ import create from 'zustand'; import createContext from 'zustand/context'; -import { clampPosition, getDimensions } from '../utils'; +import { clampPosition, getDimensions, handleBoundsSymbol } from '../utils'; import { applyNodeChanges } from '../utils/changes'; import { ReactFlowState, @@ -60,7 +60,7 @@ const createStore = () => const handleBounds = getHandleBounds(update.nodeElement, transform[2]); nodeInternals.set(node.id, { ...node, - handleBounds, + [handleBoundsSymbol]: handleBounds, ...dimensions, }); diff --git a/src/store/utils.ts b/src/store/utils.ts index d7c5921e3..9fd2ee607 100644 --- a/src/store/utils.ts +++ b/src/store/utils.ts @@ -1,7 +1,7 @@ import { zoomIdentity } from 'd3-zoom'; import { GetState, SetState } from 'zustand'; -import { isNumeric } from '../utils'; +import { handleBoundsSymbol, isNumeric, isParentSymbol, zSymbol } from '../utils'; import { getD3Transition, getRectOfNodes, getTransformForBounds } from '../utils/graph'; import { Edge, @@ -30,7 +30,7 @@ function calculateXYZPosition( return calculateXYZPosition(parentNode, nodeInternals, parentNodes, { x: (result.x ?? 0) + (parentNode.position?.x ?? 0), y: (result.y ?? 0) + (parentNode.position?.y ?? 0), - z: (parentNode.z ?? 0) > (result.z ?? 0) ? parentNode.z ?? 0 : result.z ?? 0, + z: (parentNode[zSymbol] ?? 0) > (result.z ?? 0) ? parentNode[zSymbol] ?? 0 : result.z ?? 0, }); } @@ -45,18 +45,28 @@ export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals) const internals: Node = { width: currInternals?.width, height: currInternals?.height, - handleBounds: currInternals?.handleBounds, ...node, positionAbsolute: { x: node.position.x, y: node.position.y, }, - z, }; + if (node.parentNode) { internals.parentNode = node.parentNode; parentNodes[node.parentNode] = true; } + + Object.defineProperty(internals, handleBoundsSymbol, { + enumerable: false, + value: currInternals?.[handleBoundsSymbol], + }); + + Object.defineProperty(internals, zSymbol, { + enumerable: false, + value: z, + }); + nextNodeInternals.set(node.id, internals); }); @@ -68,7 +78,7 @@ export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals) if (node.parentNode || parentNodes[node.id]) { const { x, y, z } = calculateXYZPosition(node, nextNodeInternals, parentNodes, { ...node.position, - z: node.z ?? 0, + z: node[zSymbol] ?? 0, }); node.positionAbsolute = { @@ -76,10 +86,10 @@ export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals) y, }; - node.z = z; + node[zSymbol] = z; if (parentNodes[node.id]) { - node.isParent = true; + node[isParentSymbol] = true; } } }); diff --git a/src/types/nodes.ts b/src/types/nodes.ts index ac7a3c204..ed289dd68 100644 --- a/src/types/nodes.ts +++ b/src/types/nodes.ts @@ -2,6 +2,7 @@ import { CSSProperties, MouseEvent as ReactMouseEvent } from 'react'; import { XYPosition, Position, CoordinateExtent } from './utils'; import { HandleElement } from './handles'; +import { handleBoundsSymbol, isParentSymbol, zSymbol } from '../utils'; // interface for the user node items export interface Node { @@ -28,9 +29,9 @@ export interface Node { // only used internally positionAbsolute?: XYPosition; - z?: number; - handleBounds?: NodeHandleBounds; - isParent?: boolean; + [zSymbol]?: number; + [handleBoundsSymbol]?: NodeHandleBounds; + [isParentSymbol]?: boolean; } // props that get passed to a custom node diff --git a/src/utils/index.ts b/src/utils/index.ts index 926977cb6..490a0338c 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -40,3 +40,7 @@ export const getBoundsofRects = (rect1: Rect, rect2: Rect): Rect => boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2))); export const isNumeric = (n: any): n is number => !isNaN(n) && isFinite(n); + +export const handleBoundsSymbol = Symbol('handleBound'); +export const zSymbol = Symbol('z'); +export const isParentSymbol = Symbol('isParent');