refactor(node-resizer): use nodeId from context, fix glitches while resizing

This commit is contained in:
Christopher Möller
2022-12-06 17:56:56 +01:00
parent 8bca8e4bfc
commit 0892e2ea9a
17 changed files with 201 additions and 128 deletions
@@ -1,9 +1,9 @@
import { memo, useContext, HTMLAttributes, forwardRef, MouseEvent as ReactMouseEvent } from 'react';
import { memo, HTMLAttributes, forwardRef, MouseEvent as ReactMouseEvent } from 'react';
import cc from 'classcat';
import shallow from 'zustand/shallow';
import { useStore, useStoreApi } from '../../hooks/useStore';
import NodeIdContext from '../../contexts/NodeIdContext';
import { useNodeId } from '../../contexts/NodeIdContext';
import { checkElementBelowIsValid, handleMouseDown } from './handler';
import { getHostForElement } from '../../utils';
import { addEdge } from '../../utils/graph';
@@ -37,7 +37,9 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
ref
) => {
const store = useStoreApi();
const nodeId = useContext(NodeIdContext) as string;
// @fixme: remove type assertion and handle nodeId === null
const nodeId = useNodeId() as string;
const { connectionStartHandle, connectOnClick, noPanClassName } = useStore(selector, shallow);
const handleId = id || null;
+6 -1
View File
@@ -1,7 +1,12 @@
import { createContext } from 'react';
import { createContext, useContext } from 'react';
export const NodeIdContext = createContext<string | null>(null);
export const Provider = NodeIdContext.Provider;
export const Consumer = NodeIdContext.Consumer;
export const useNodeId = (): string | null => {
const nodeId = useContext(NodeIdContext);
return nodeId;
};
export default NodeIdContext;
+1 -1
View File
@@ -22,7 +22,6 @@ export {
getNodePositionWithOrigin,
} from './utils/graph';
export { applyNodeChanges, applyEdgeChanges } from './utils/changes';
export { createNodeInternals } from './store/utils';
export { getMarkerEnd } from './components/Edges/utils';
export { default as ReactFlowProvider } from './components/ReactFlowProvider';
export { default as Panel } from './components/Panel';
@@ -40,5 +39,6 @@ export { default as useOnViewportChange } from './hooks/useOnViewportChange';
export { default as useOnSelectionChange } from './hooks/useOnSelectionChange';
export { default as useNodesInitialized } from './hooks/useNodesInitialized';
export { default as useGetPointerPosition } from './hooks/useGetPointerPosition';
export { useNodeId } from './contexts/NodeIdContext';
export * from './types';
+30 -35
View File
@@ -17,6 +17,7 @@ import type {
NodePositionChange,
NodeDragItem,
UnselectNodesAndEdgesParams,
NodeChange,
} from '../types';
const createRFStore = () =>
@@ -102,47 +103,41 @@ const createRFStore = () =>
onNodesChange?.(changes);
}
},
updateNodePositions: (
nodeDragItems: NodeDragItem[] | Node[],
positionChanged = true,
dragging = false,
applyChanges = true
) => {
const { onNodesChange, nodeInternals, hasDefaultNodes, nodeOrigin } = get();
updateNodePositions: (nodeDragItems: NodeDragItem[] | Node[], positionChanged = true, dragging = false) => {
const { triggerNodeChanges } = get();
if (hasDefaultNodes || onNodesChange) {
const changes = nodeDragItems.map((node) => {
const change: NodePositionChange = {
id: node.id,
type: 'position',
dragging,
};
const changes = nodeDragItems.map((node) => {
const change: NodePositionChange = {
id: node.id,
type: 'position',
dragging,
};
if (positionChanged) {
change.positionAbsolute = node.positionAbsolute;
change.position = node.position;
}
return change;
});
if (changes?.length) {
if (hasDefaultNodes) {
const nodes = applyNodeChanges(changes, Array.from(nodeInternals.values()));
const nextNodeInternals = createNodeInternals(nodes, nodeInternals, nodeOrigin);
set({ nodeInternals: nextNodeInternals });
}
if (applyChanges) {
onNodesChange?.(changes);
}
if (positionChanged) {
change.positionAbsolute = node.positionAbsolute;
change.position = node.position;
}
return changes;
}
return change;
});
return null;
triggerNodeChanges(changes);
},
triggerNodeChanges: (changes: NodeChange[]) => {
const { onNodesChange, nodeInternals, hasDefaultNodes, nodeOrigin } = get();
if (changes?.length) {
if (hasDefaultNodes) {
const nodes = applyNodeChanges(changes, Array.from(nodeInternals.values()));
const nextNodeInternals = createNodeInternals(nodes, nodeInternals, nodeOrigin);
set({ nodeInternals: nextNodeInternals });
}
onNodesChange?.(changes);
}
},
addSelectedNodes: (selectedNodeIds: string[]) => {
const { multiSelectionActive, nodeInternals, edges } = get();
let changedNodes: NodeSelectionChange[];
+2 -1
View File
@@ -7,8 +7,9 @@ import type { Edge } from './edges';
export type NodeDimensionChange = {
id: string;
type: 'dimensions';
dimensions: Dimensions;
dimensions?: Dimensions;
updateStyle?: boolean;
resizing?: boolean;
};
export type NodePositionChange = {
+2 -6
View File
@@ -215,12 +215,7 @@ 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,
applyChanges?: boolean
) => NodePositionChange[] | null;
updateNodePositions: (nodeDragItems: NodeDragItem[] | Node[], positionChanged: boolean, dragging: boolean) => void;
resetSelectedElements: () => void;
unselectNodesAndEdges: (params?: UnselectNodesAndEdgesParams) => void;
addSelectedNodes: (nodeIds: string[]) => void;
@@ -231,6 +226,7 @@ export type ReactFlowActions = {
setNodeExtent: (nodeExtent: CoordinateExtent) => void;
cancelConnection: () => void;
reset: () => void;
triggerNodeChanges: (changes: NodeChange[]) => void;
};
export type ReactFlowState = ReactFlowStore & ReactFlowActions;
+1
View File
@@ -31,6 +31,7 @@ export type Node<T = any> = {
positionAbsolute?: XYPosition;
ariaLabel?: string;
focusable?: boolean;
resizing?: boolean;
// only used internally
[internalsSymbol]?: {
+4
View File
@@ -94,6 +94,10 @@ function applyChanges(changes: any[], elements: any[]): any[] {
updateItem.style = { ...(updateItem.style || {}), ...currentChange.dimensions };
}
if (typeof currentChange.resizing === 'boolean') {
updateItem.resizing = currentChange.resizing;
}
if (updateItem.expandParent) {
handleParentExpand(res, updateItem);
}