chore(react): node origin cleanup
This commit is contained in:
@@ -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
|
||||
>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>>;
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user