* feat(react/svelte): add initialWidth/initialHeight closes #3793 * chore(packages): update changelogs
123 lines
3.7 KiB
TypeScript
123 lines
3.7 KiB
TypeScript
import { EdgePosition } from '../../types/edges';
|
|
import { ConnectionMode, OnError } from '../../types/general';
|
|
import { NodeBase, NodeHandle } from '../../types/nodes';
|
|
import { Position } from '../../types/utils';
|
|
import { errorMessages, internalsSymbol } from '../../constants';
|
|
import { HandleElement } from '../../types';
|
|
import { getNodeDimensions } from '../general';
|
|
|
|
export type GetEdgePositionParams = {
|
|
id: string;
|
|
sourceNode: NodeBase;
|
|
sourceHandle: string | null;
|
|
targetNode: NodeBase;
|
|
targetHandle: string | null;
|
|
connectionMode: ConnectionMode;
|
|
onError?: OnError;
|
|
};
|
|
|
|
function isNodeInitialized(node: NodeBase): boolean {
|
|
return (
|
|
!!(node?.[internalsSymbol]?.handleBounds || node?.handles?.length) &&
|
|
!!(node?.computed?.width || node?.width || node?.initialWidth)
|
|
);
|
|
}
|
|
|
|
export function getEdgePosition(params: GetEdgePositionParams): EdgePosition | null {
|
|
const { sourceNode, targetNode } = params;
|
|
|
|
if (!isNodeInitialized(sourceNode) || !isNodeInitialized(targetNode)) {
|
|
return null;
|
|
}
|
|
|
|
const sourceHandleBounds = sourceNode[internalsSymbol]?.handleBounds || toHandleBounds(sourceNode.handles);
|
|
const targetHandleBounds = targetNode[internalsSymbol]?.handleBounds || toHandleBounds(targetNode.handles);
|
|
|
|
const sourceHandle = getHandle(sourceHandleBounds?.source ?? [], params.sourceHandle);
|
|
const targetHandle = getHandle(
|
|
// when connection type is loose we can define all handles as sources and connect source -> source
|
|
params.connectionMode === ConnectionMode.Strict
|
|
? targetHandleBounds?.target ?? []
|
|
: (targetHandleBounds?.target ?? []).concat(targetHandleBounds?.source ?? []),
|
|
params.targetHandle
|
|
);
|
|
const sourcePosition = sourceHandle?.position || Position.Bottom;
|
|
const targetPosition = targetHandle?.position || Position.Top;
|
|
|
|
if (!sourceHandle || !targetHandle) {
|
|
params.onError?.(
|
|
'008',
|
|
errorMessages['error008'](!sourceHandle ? 'source' : 'target', {
|
|
id: params.id,
|
|
sourceHandle: params.sourceHandle,
|
|
targetHandle: params.targetHandle,
|
|
})
|
|
);
|
|
|
|
return null;
|
|
}
|
|
|
|
const [sourceX, sourceY] = getHandlePosition(sourcePosition, sourceNode, sourceHandle);
|
|
const [targetX, targetY] = getHandlePosition(targetPosition, targetNode, targetHandle);
|
|
|
|
return {
|
|
sourceX,
|
|
sourceY,
|
|
targetX,
|
|
targetY,
|
|
sourcePosition,
|
|
targetPosition,
|
|
};
|
|
}
|
|
|
|
function toHandleBounds(handles?: NodeHandle[]) {
|
|
if (!handles) {
|
|
return null;
|
|
}
|
|
|
|
const source = [];
|
|
const target = [];
|
|
|
|
for (const handle of handles) {
|
|
handle.width = handle.width ?? 1;
|
|
handle.height = handle.height ?? 1;
|
|
|
|
if (handle.type === 'source') {
|
|
source.push(handle as HandleElement);
|
|
} else if (handle.type === 'target') {
|
|
target.push(handle as HandleElement);
|
|
}
|
|
}
|
|
|
|
return {
|
|
source,
|
|
target,
|
|
};
|
|
}
|
|
|
|
function getHandlePosition(position: Position, node: NodeBase, handle: HandleElement | null = null): number[] {
|
|
const x = (handle?.x ?? 0) + (node.computed?.positionAbsolute?.x ?? 0);
|
|
const y = (handle?.y ?? 0) + (node.computed?.positionAbsolute?.y ?? 0);
|
|
const { width, height } = handle ?? getNodeDimensions(node);
|
|
|
|
switch (position) {
|
|
case Position.Top:
|
|
return [x + width / 2, y];
|
|
case Position.Right:
|
|
return [x + width, y + height / 2];
|
|
case Position.Bottom:
|
|
return [x + width / 2, y + height];
|
|
case Position.Left:
|
|
return [x, y + height / 2];
|
|
}
|
|
}
|
|
|
|
function getHandle(bounds: HandleElement[], handleId?: string | null): HandleElement | null {
|
|
if (!bounds) {
|
|
return null;
|
|
}
|
|
|
|
// if no handleId is given, we use the first handle, otherwise we check for the id
|
|
return (!handleId ? bounds[0] : bounds.find((d) => d.id === handleId)) || null;
|
|
}
|