chore(react): node origin cleanup

This commit is contained in:
moklick
2024-06-26 15:26:22 +02:00
parent c444eb380b
commit f968ff42ca
13 changed files with 33 additions and 71 deletions

View File

@@ -128,7 +128,7 @@ const initialNodes: Node[] = [
data: { label: 'Parent', keepAspectRatio: true },
position: { x: 700, y: 0 },
width: 300,
height: 400,
height: 300,
style: { ...nodeStyle },
},
{
@@ -148,7 +148,9 @@ const initialNodes: Node[] = [
id: '5b',
type: 'defaultResizer',
data: { label: 'Child with expandParent' },
position: { x: 150, y: 100 },
position: { x: 100, y: 100 },
width: 100,
height: 100,
parentId: '5',
expandParent: true,
style: { ...nodeStyle },
@@ -187,7 +189,6 @@ const CustomNodeFlow = () => {
minZoom={0.2}
maxZoom={5}
snapToGrid={snapToGrid}
nodeOrigin={[1, 1]}
fitView
onlyRenderVisibleElements
>

View File

@@ -84,8 +84,8 @@ function ResizeControl({
height,
...evaluateAbsolutePosition(
{
x: change.x ?? node.internals.positionAbsolute.x,
y: change.y ?? node.internals.positionAbsolute.y,
x: change.x ?? node.position.x,
y: change.y ?? node.position.y,
},
{ width, height },
node.parentId,
@@ -94,6 +94,7 @@ function ResizeControl({
),
},
};
console.log(child);
const parentExpandChanges = handleExpandParent([child], nodeLookup, parentLookup, nodeOrigin);
changes.push(...parentExpandChanges);

View File

@@ -39,7 +39,6 @@ export function NodeWrapper<NodeType extends Node>({
rfId,
nodeTypes,
nodeExtent,
nodeOrigin,
onError,
}: NodeWrapperProps<NodeType>) {
const { node, internals, isParent } = useStore((s) => {
@@ -87,7 +86,9 @@ export function NodeWrapper<NodeType extends Node>({
const nodeDimensions = getNodeDimensions(node);
const inlineDimensions = getNodeInlineStyleDimensions(node);
// TODO: clamping should happen earlier
let clampedPosition = nodeExtent ? clampPosition(internals.positionAbsolute, nodeExtent) : internals.positionAbsolute;
const clampedPosition = nodeExtent
? clampPosition(internals.positionAbsolute, nodeExtent)
: internals.positionAbsolute;
const hasPointerEvents = isSelectable || isDraggable || onClick || onMouseEnter || onMouseMove || onMouseLeave;

View File

@@ -32,7 +32,6 @@ export type GraphViewProps<NodeType extends Node = Node, EdgeType extends Edge =
| 'noPanClassName'
| 'defaultViewport'
| 'disableKeyboardA11y'
| 'nodeOrigin'
>
> & {
rfId: string;
@@ -97,7 +96,6 @@ function GraphViewComponent<NodeType extends Node = Node, EdgeType extends Edge
noWheelClassName,
noPanClassName,
disableKeyboardA11y,
nodeOrigin,
nodeExtent,
rfId,
viewport,
@@ -186,7 +184,6 @@ function GraphViewComponent<NodeType extends Node = Node, EdgeType extends Edge
noPanClassName={noPanClassName}
noDragClassName={noDragClassName}
disableKeyboardA11y={disableKeyboardA11y}
nodeOrigin={nodeOrigin}
nodeExtent={nodeExtent}
rfId={rfId}
/>

View File

@@ -22,7 +22,6 @@ export type NodeRendererProps<NodeType extends Node> = Pick<
| 'noDragClassName'
| 'rfId'
| 'disableKeyboardA11y'
| 'nodeOrigin'
| 'nodeExtent'
| 'nodeTypes'
>;
@@ -72,7 +71,6 @@ function NodeRendererComponent<NodeType extends Node>(props: NodeRendererProps<N
id={nodeId}
nodeTypes={props.nodeTypes}
nodeExtent={props.nodeExtent}
nodeOrigin={props.nodeOrigin}
onClick={props.onNodeClick}
onMouseEnter={props.onNodeMouseEnter}
onMouseMove={props.onNodeMouseMove}

View File

@@ -217,7 +217,6 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
noPanClassName={noPanClassName}
rfId={rfId}
disableKeyboardA11y={disableKeyboardA11y}
nodeOrigin={nodeOrigin}
nodeExtent={nodeExtent}
viewport={viewport}
onViewportChange={onViewportChange}

View File

@@ -1,12 +1,5 @@
import type { CSSProperties, MouseEvent as ReactMouseEvent } from 'react';
import type {
CoordinateExtent,
NodeBase,
NodeOrigin,
OnError,
NodeProps as NodePropsBase,
InternalNodeBase,
} from '@xyflow/system';
import type { CoordinateExtent, NodeBase, OnError, NodeProps as NodePropsBase, InternalNodeBase } from '@xyflow/system';
import { NodeTypes } from './general';
@@ -59,7 +52,6 @@ export type NodeWrapperProps<NodeType extends Node> = {
disableKeyboardA11y: boolean;
nodeTypes?: NodeTypes;
nodeExtent?: CoordinateExtent;
nodeOrigin: NodeOrigin;
onError?: OnError;
};

View File

@@ -54,7 +54,7 @@ export type ReactFlowStore<NodeType extends Node = Node, EdgeType extends Edge =
transform: Transform;
nodes: NodeType[];
nodeLookup: NodeLookup<InternalNode<NodeType>>;
parentLookup: Map<string, InternalNode<NodeType>[]>;
parentLookup: Map<string, Map<string, InternalNode<NodeType>>>;
edges: Edge[];
edgeLookup: EdgeLookup<EdgeType>;
connectionLookup: ConnectionLookup;

View File

@@ -107,7 +107,7 @@ export const getInitialStore = ({
flowId: writable<string | null>(null),
nodes: createNodesStore(nodes, nodeLookup, parentLookup),
nodeLookup: readable<NodeLookup<InternalNode>>(nodeLookup),
parentLookup: readable<Map<string, InternalNode[]>>(parentLookup),
parentLookup: readable<Map<string, Map<string, InternalNode>>>(parentLookup),
edgeLookup: readable<EdgeLookup<Edge>>(edgeLookup),
visibleNodes: readable<InternalNode[]>([]),
edges: createEdgesStore(edges, connectionLookup, edgeLookup),

View File

@@ -13,7 +13,8 @@ import {
type PanZoomInstance,
type ConnectionLookup,
type EdgeLookup,
type NodeLookup
type NodeLookup,
type ParentLookup
} from '@xyflow/system';
import type { DefaultEdgeOptions, DefaultNodeOptions, Edge, InternalNode, Node } from '$lib/types';
@@ -128,7 +129,7 @@ export type NodeStoreOptions = {
export const createNodesStore = (
nodes: Node[],
nodeLookup: NodeLookup<InternalNode>,
parentLookup: Map<string, InternalNode[]>
parentLookup: ParentLookup<InternalNode>
): {
subscribe: (this: void, run: Subscriber<Node[]>) => Unsubscriber;
update: (this: void, updater: Updater<Node[]>) => void;

View File

@@ -154,4 +154,4 @@ export type NodeHandle = Optional<HandleElement, 'width' | 'height'>;
export type Align = 'center' | 'start' | 'end';
export type NodeLookup<NodeType extends InternalNodeBase = InternalNodeBase> = Map<string, NodeType>;
export type ParentLookup<NodeType extends InternalNodeBase = InternalNodeBase> = Map<string, NodeType[]>;
export type ParentLookup<NodeType extends InternalNodeBase = InternalNodeBase> = Map<string, Map<string, NodeType>>;

View File

@@ -118,29 +118,6 @@ export const devWarn = (id: string, message: string) => {
}
};
export const getPositionWithOrigin = ({
x,
y,
width,
height,
origin = [0, 0],
}: {
x: number;
y: number;
width: number;
height: number;
origin?: NodeOrigin;
}): XYPosition => {
if (!width || !height || origin[0] < 0 || origin[1] < 0 || origin[0] > 1 || origin[1] > 1) {
return { x, y };
}
return {
x: x - width * origin[0],
y: y - height * origin[1],
};
};
export const snapPosition = (position: XYPosition, snapGrid: SnapGrid = [1, 1]): XYPosition => {
return {
x: snapGrid[0] * Math.round(position.x / snapGrid[0]),
@@ -243,7 +220,7 @@ export function nodeHasDimensions<NodeType extends NodeBase = NodeBase>(node: No
*/
export function evaluateAbsolutePosition(
position: XYPosition,
dimensions: { width: number; height: number },
dimensions: { width?: number; height?: number } = { width: 0, height: 0 },
parentId: string,
nodeLookup: NodeLookup,
nodeOrigin: NodeOrigin
@@ -257,10 +234,8 @@ export function evaluateAbsolutePosition(
if (parent) {
const origin = parent.origin || nodeOrigin;
const xOffset = (parent.measured.width ?? 0) * origin[0];
const yOffset = (parent.measured.height ?? 0) * origin[1];
positionAbsolute.x += parent.internals.positionAbsolute.x - dimensions.width * nodeOrigin[0];
positionAbsolute.y += parent.internals.positionAbsolute.y - dimensions.height * nodeOrigin[1];
positionAbsolute.x += parent.internals.positionAbsolute.x - (dimensions.width ?? 0) * origin[0];
positionAbsolute.y += parent.internals.positionAbsolute.y - (dimensions.height ?? 0) * origin[1];
}
}

View File

@@ -15,7 +15,6 @@ import {
NodeDimensionChange,
NodePositionChange,
ParentLookup,
Dimensions,
} from '../types';
import { getDimensions, getHandleBounds } from './dom';
import { getBoundsOfRects, getNodeDimensions, isNumeric, nodeToRect } from './general';
@@ -23,8 +22,8 @@ import { getNodePositionWithOrigin } from './graph';
import { ParentExpandChild } from './types';
export function updateAbsolutePositions<NodeType extends NodeBase>(
nodeLookup: Map<string, InternalNodeBase<NodeType>>,
parentLookup: Map<string, InternalNodeBase<NodeType>[]>,
nodeLookup: NodeLookup<InternalNodeBase<NodeType>>,
parentLookup: ParentLookup<InternalNodeBase<NodeType>>,
options: UpdateNodesOptions<NodeType> = {
nodeOrigin: [0, 0] as NodeOrigin,
elevateNodesOnSelect: true,
@@ -49,8 +48,8 @@ type UpdateNodesOptions<NodeType extends NodeBase> = {
export function adoptUserNodes<NodeType extends NodeBase>(
nodes: NodeType[],
nodeLookup: Map<string, InternalNodeBase<NodeType>>,
parentLookup: Map<string, InternalNodeBase<NodeType>[]>,
nodeLookup: NodeLookup<InternalNodeBase<NodeType>>,
parentLookup: ParentLookup<InternalNodeBase<NodeType>>,
options: UpdateNodesOptions<NodeType> = {
nodeOrigin: [0, 0] as NodeOrigin,
elevateNodesOnSelect: true,
@@ -94,8 +93,8 @@ export function adoptUserNodes<NodeType extends NodeBase>(
function updateChildPosition<NodeType extends NodeBase>(
node: InternalNodeBase<NodeType>,
nodeLookup: NodeLookup,
parentLookup: ParentLookup,
nodeLookup: NodeLookup<InternalNodeBase<NodeType>>,
parentLookup: ParentLookup<InternalNodeBase<NodeType>>,
options: UpdateNodesOptions<NodeType> = {
nodeOrigin: [0, 0] as NodeOrigin,
elevateNodesOnSelect: true,
@@ -111,9 +110,9 @@ function updateChildPosition<NodeType extends NodeBase>(
// update the parentLookup
const childNodes = parentLookup.get(parentId);
if (childNodes) {
childNodes.push(node);
childNodes.set(node.id, node);
} else {
parentLookup.set(parentId, [node]);
parentLookup.set(parentId, new Map([[node.id, node]]);
}
const selectedNodeZ: number = options?.elevateNodesOnSelect ? 1000 : 0;
@@ -160,7 +159,7 @@ export function handleExpandParent(
): (NodeDimensionChange | NodePositionChange)[] {
const changes: (NodeDimensionChange | NodePositionChange)[] = [];
const parentExpansions = new Map<string, { expandedRect: Rect; parent: InternalNodeBase }>();
console.log(children)
// determine the expanded rectangle the child nodes would take for each parent
for (const child of children) {
const parent = nodeLookup.get(child.parentId);
@@ -168,14 +167,13 @@ export function handleExpandParent(
continue;
}
const parentRect =
parentExpansions.get(child.parentId)?.expandedRect ?? nodeToRect(parent, parent.origin ?? nodeOrigin);
const parentRect = parentExpansions.get(child.parentId)?.expandedRect ?? nodeToRect(parent);
const expandedRect = getBoundsOfRects(parentRect, child.rect);
parentExpansions.set(child.parentId, { expandedRect, parent });
}
if (parentExpansions.size > 0) {
parentExpansions.forEach(({ expandedRect, parent }, parentId) => {
// determine the position & dimensions of the parent
@@ -208,8 +206,7 @@ export function handleExpandParent(
// We move all child nodes in the oppsite direction
// so the x,y changes of the parent do not move the children
const childNodes = parentLookup.get(parentId);
childNodes?.forEach((childNode) => {
parentLookup.get(parentId)?.forEach((childNode) => {
if (!children.some((child) => child.id === childNode.id)) {
changes.push({
id: childNode.id,
@@ -295,7 +292,7 @@ export function updateNodeInternals<NodeType extends InternalNodeBase>(
},
};
if (node.parentId) {
updateChildPosition(node, nodeLookup, parentLookup, { nodeOrigin });
updateChildPosition(node, nodeLookup, parentLookup, { nodeOrigin });
}
updatedInternals = true;