refactor(positions): remove unused node origins

This commit is contained in:
moklick
2024-06-27 15:03:35 +02:00
parent 1a51428bd4
commit 609f7ed792
12 changed files with 64 additions and 69 deletions
@@ -25,12 +25,8 @@ const selector = (s: ReactFlowState) => {
return {
viewBB,
boundingRect:
s.nodeLookup.size > 0
? getBoundsOfRects(getInternalNodesBounds(s.nodeLookup, { nodeOrigin: s.nodeOrigin }), viewBB)
: viewBB,
boundingRect: s.nodeLookup.size > 0 ? getBoundsOfRects(getInternalNodesBounds(s.nodeLookup), viewBB) : viewBB,
rfId: s.rfId,
nodeOrigin: s.nodeOrigin,
panZoom: s.panZoom,
translateExtent: s.translateExtent,
flowWidth: s.width,
@@ -1,7 +1,7 @@
import { useCallback, CSSProperties } from 'react';
import cc from 'classcat';
import { shallow } from 'zustand/shallow';
import { Rect, Position, getNodeToolbarTransform, getNodesBounds } from '@xyflow/system';
import { Position, getNodeToolbarTransform, getInternalNodesBounds, NodeLookup } from '@xyflow/system';
import { InternalNode, ReactFlowState } from '../../types';
import { useStore } from '../../hooks/useStore';
@@ -17,21 +17,24 @@ const nodeEqualityFn = (a?: InternalNode, b?: InternalNode) =>
a?.selected !== b?.selected ||
a?.internals.z !== b?.internals.z;
const nodesEqualityFn = (a: InternalNode[], b: InternalNode[]) => {
if (a.length !== b.length) {
const nodesEqualityFn = (a: NodeLookup, b: NodeLookup) => {
if (a.size !== b.size) {
return false;
}
return !a.some((node, i) => nodeEqualityFn(node, b[i]));
for (const [key, node] of a) {
if (nodeEqualityFn(node, b.get(key))) {
return false;
}
}
return true;
};
const storeSelector = (state: ReactFlowState) => ({
viewport: {
x: state.transform[0],
y: state.transform[1],
zoom: state.transform[2],
},
nodeOrigin: state.nodeOrigin,
x: state.transform[0],
y: state.transform[1],
zoom: state.transform[2],
selectedNodesCount: state.nodes.filter((node) => node.selected).length,
});
@@ -49,36 +52,41 @@ export function NodeToolbar({
const contextNodeId = useNodeId();
const nodesSelector = useCallback(
(state: ReactFlowState): InternalNode[] => {
(state: ReactFlowState): NodeLookup => {
const nodeIds = Array.isArray(nodeId) ? nodeId : [nodeId || contextNodeId || ''];
return nodeIds.reduce<InternalNode[]>((acc, id) => {
const internalNodes = nodeIds.reduce<NodeLookup>((res, id) => {
const node = state.nodeLookup.get(id);
if (node) {
acc.push(node);
res.set(node.id, node);
}
return acc;
}, []);
return res;
}, new Map());
return internalNodes;
},
[nodeId, contextNodeId]
);
const nodes = useStore(nodesSelector, nodesEqualityFn);
const { viewport, nodeOrigin, selectedNodesCount } = useStore(storeSelector, shallow);
const { x, y, zoom, selectedNodesCount } = useStore(storeSelector, shallow);
// if isVisible is not set, we show the toolbar only if its node is selected and no other node is selected
const isActive =
typeof isVisible === 'boolean' ? isVisible : nodes.length === 1 && nodes[0].selected && selectedNodesCount === 1;
typeof isVisible === 'boolean'
? isVisible
: nodes.size === 1 && nodes.values().next().value.selected && selectedNodesCount === 1;
if (!isActive || !nodes.length) {
if (!isActive || !nodes.size) {
return null;
}
const nodeRect: Rect = getNodesBounds(nodes, { nodeOrigin });
const zIndex: number = Math.max(...nodes.map((node) => node.internals.z + 1));
const nodeRect = getInternalNodesBounds(nodes);
const nodesArray = Array.from(nodes.values());
const zIndex = Math.max(...nodesArray.map((node) => node.internals.z + 1));
const wrapperStyle: CSSProperties = {
position: 'absolute',
transform: getNodeToolbarTransform(nodeRect, viewport, position, offset, align),
transform: getNodeToolbarTransform(nodeRect, { x, y, zoom }, position, offset, align),
zIndex,
...style,
};
@@ -89,7 +97,8 @@ export function NodeToolbar({
style={wrapperStyle}
className={cc(['react-flow__node-toolbar', className])}
{...rest}
data-id={nodes.reduce((acc, node) => `${acc}${node.id} `, '').trim()}
// @todo: check if we could only do this for non-prod envs
data-id={nodesArray.reduce((acc, node) => `${acc}${node.id} `, '').trim()}
>
{children}
</div>
@@ -21,7 +21,6 @@ export type NodesSelectionProps<NodeType> = {
const selector = (s: ReactFlowState) => {
const { width, height, x, y } = getInternalNodesBounds(s.nodeLookup, {
nodeOrigin: s.nodeOrigin,
filter: (node) => !!node.selected,
});
@@ -22,7 +22,6 @@ export type FlowRendererProps<NodeType extends Node = Node> = Omit<
| 'selectNodesOnDrag'
| 'defaultMarkerColor'
| 'rfId'
| 'nodeOrigin'
> & {
isControlledViewport: boolean;
children: ReactNode;
+2 -3
View File
@@ -155,7 +155,7 @@ export function Pane({
};
const onPointerMove = (event: ReactPointerEvent): void => {
const { userSelectionRect, edgeLookup, transform, nodeOrigin, nodeLookup, triggerNodeChanges, triggerEdgeChanges } =
const { userSelectionRect, edgeLookup, transform, nodeLookup, triggerNodeChanges, triggerEdgeChanges } =
store.getState();
if (!containerBounds.current || !userSelectionRect) {
@@ -181,8 +181,7 @@ export function Pane({
nextUserSelectRect,
transform,
selectionMode === SelectionMode.Partial,
true,
nodeOrigin
true
);
const selectedEdgeIds = new Set<string>();
+16 -15
View File
@@ -45,22 +45,23 @@ const useViewportHelper = (): ViewportHelperFunctions => {
return { x, y, zoom };
},
fitView: (options) => {
const { nodeLookup, width, height, nodeOrigin, minZoom, maxZoom, panZoom } = store.getState();
const { nodeLookup, width, height, minZoom, maxZoom, panZoom } = store.getState();
return panZoom
? fitView(
{
nodeLookup,
width,
height,
nodeOrigin,
minZoom,
maxZoom,
panZoom,
},
options
)
: false;
if (!panZoom) {
return false;
}
return fitView(
{
nodeLookup,
width,
height,
minZoom,
maxZoom,
panZoom,
},
options
);
},
setCenter: (x, y, options) => {
const { width, height, maxZoom, panZoom } = store.getState();
+1 -2
View File
@@ -288,7 +288,7 @@ const createStore = ({
return panBySystem({ delta, panZoom, transform, translateExtent, width, height });
},
fitView: (options?: FitViewOptions): boolean => {
const { panZoom, width, height, minZoom, maxZoom, nodeOrigin, nodeLookup } = get();
const { panZoom, width, height, minZoom, maxZoom, nodeLookup } = get();
if (!panZoom) {
return false;
@@ -302,7 +302,6 @@ const createStore = ({
panZoom,
minZoom,
maxZoom,
nodeOrigin,
},
options
);
-1
View File
@@ -46,7 +46,6 @@ const getInitialState = ({
if (fitView && width && height) {
// @todo users nodeOrigin should be used here
const bounds = getInternalNodesBounds(nodeLookup, {
nodeOrigin: [0, 0],
filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight)),
});
const { x, y, zoom } = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);