fix: arrow beginning und ending
This commit is contained in:
parent
590178b8f2
commit
6890a38546
2 changed files with 35 additions and 26 deletions
|
|
@ -263,10 +263,10 @@
|
|||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
width: 100%;
|
||||
padding: 0.35rem 0.5rem;
|
||||
padding: 0;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--border-color, #e0e0e0);
|
||||
background: var(--bg-secondary, #f8f9fa);
|
||||
border: none;
|
||||
background: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
|
@ -966,6 +966,8 @@
|
|||
|
||||
.handleWrapper:has(.handleOutput) {
|
||||
flex-direction: row;
|
||||
/* Bottom handles: keep circle math aligned with wires even when a label grows row height. */
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.handleWrapper:has(.handleInput) {
|
||||
|
|
|
|||
|
|
@ -115,6 +115,8 @@ export function getStickyNotePaletteEntry(colorId?: string) {
|
|||
|
||||
const NODE_WIDTH = 200;
|
||||
const NODE_HEIGHT = 72;
|
||||
/** Must match `.canvasNode { border: … solid }` — handles sit in the padding box. */
|
||||
const NODE_BORDER = 2;
|
||||
|
||||
export const FLOW_CANVAS_MIN_ZOOM = 0.25;
|
||||
export const FLOW_CANVAS_MAX_ZOOM = 4;
|
||||
|
|
@ -646,7 +648,7 @@ function feedbackConnectionPathD(
|
|||
const sx = src.x;
|
||||
const sy = src.y;
|
||||
const tx = tgt.x;
|
||||
const tyIn = tgt.y - HANDLE_OFFSET;
|
||||
const tyIn = tgt.y;
|
||||
|
||||
const minNx = allNodes.length
|
||||
? Math.min(...allNodes.map((n) => n.x))
|
||||
|
|
@ -687,10 +689,14 @@ function connectionPathD(
|
|||
tgtNode: CanvasNode,
|
||||
feedback: boolean,
|
||||
allNodes: CanvasNode[],
|
||||
/** Trennt überlagernde Kanten in der Kurvenmitte — Endpunkt bleibt am Handle-Mittelpunkt. */
|
||||
lateralBias = 0,
|
||||
): string {
|
||||
if (!feedback) {
|
||||
const dy = tgt.y - src.y;
|
||||
return `M ${src.x} ${src.y} C ${src.x} ${src.y + Math.abs(dy) / 2}, ${tgt.x} ${tgt.y - Math.abs(dy) / 2}, ${tgt.x} ${tgt.y}`;
|
||||
const mx = Math.abs(dy) / 2;
|
||||
const b = lateralBias;
|
||||
return `M ${src.x} ${src.y} C ${src.x + b} ${src.y + mx}, ${tgt.x + b} ${tgt.y - mx}, ${tgt.x} ${tgt.y}`;
|
||||
}
|
||||
return feedbackConnectionPathD(src, tgt, srcNode, tgtNode, allNodes);
|
||||
}
|
||||
|
|
@ -1039,19 +1045,20 @@ export const FlowCanvas = forwardRef<FlowCanvasHandle, FlowCanvasProps>(function
|
|||
const ioIndex = isOutput ? handleIndex - node.inputs : handleIndex;
|
||||
const ioCount = isOutput ? node.outputs : node.inputs;
|
||||
|
||||
const w = NODE_WIDTH;
|
||||
const h = NODE_HEIGHT;
|
||||
const centerX = node.x + w / 2;
|
||||
const innerLeft = node.x + NODE_BORDER;
|
||||
const innerTop = node.y + NODE_BORDER;
|
||||
const innerBottom = node.y + NODE_HEIGHT - NODE_BORDER;
|
||||
const innerWidth = NODE_WIDTH - 2 * NODE_BORDER;
|
||||
const centerX = innerLeft + innerWidth / 2;
|
||||
|
||||
if (isOutput) {
|
||||
if (ioCount === 1) return { x: centerX, y: node.y + h + HANDLE_OFFSET, side: 'bottom' };
|
||||
const step = w / (ioCount + 1);
|
||||
return { x: node.x + step * (ioIndex + 1), y: node.y + h + HANDLE_OFFSET, side: 'bottom' };
|
||||
} else {
|
||||
if (ioCount === 1) return { x: centerX, y: node.y, side: 'top' };
|
||||
const step = w / (ioCount + 1);
|
||||
return { x: node.x + step * (ioIndex + 1), y: node.y, side: 'top' };
|
||||
if (ioCount === 1) return { x: centerX, y: innerBottom, side: 'bottom' };
|
||||
const step = innerWidth / (ioCount + 1);
|
||||
return { x: innerLeft + step * (ioIndex + 1), y: innerBottom, side: 'bottom' };
|
||||
}
|
||||
if (ioCount === 1) return { x: centerX, y: innerTop, side: 'top' };
|
||||
const step = innerWidth / (ioCount + 1);
|
||||
return { x: innerLeft + step * (ioIndex + 1), y: innerTop, side: 'top' };
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
|
@ -1062,7 +1069,7 @@ export const FlowCanvas = forwardRef<FlowCanvasHandle, FlowCanvasProps>(function
|
|||
return used;
|
||||
}, [connections]);
|
||||
|
||||
/** Mehrere Kanten auf denselben Eingang: leicht versetzte Ziel-X für sichtbare, getrennte Enden. */
|
||||
/** Mehrere Kanten auf denselben Eingang: Kurven seitlich versetzen (Endpunkt = Handle-Mitte). */
|
||||
const inboundStacksByTarget = useMemo(() => {
|
||||
const m = new Map<string, CanvasConnection[]>();
|
||||
for (const c of connections) {
|
||||
|
|
@ -1746,9 +1753,10 @@ export const FlowCanvas = forwardRef<FlowCanvasHandle, FlowCanvasProps>(function
|
|||
<defs>
|
||||
<marker
|
||||
id="arrowhead"
|
||||
markerUnits="userSpaceOnUse"
|
||||
markerWidth="10"
|
||||
markerHeight="7"
|
||||
refX="9"
|
||||
refX="10"
|
||||
refY="3.5"
|
||||
orient="auto"
|
||||
>
|
||||
|
|
@ -1756,9 +1764,10 @@ export const FlowCanvas = forwardRef<FlowCanvasHandle, FlowCanvasProps>(function
|
|||
</marker>
|
||||
<marker
|
||||
id="arrowhead-selected"
|
||||
markerUnits="userSpaceOnUse"
|
||||
markerWidth="10"
|
||||
markerHeight="7"
|
||||
refX="9"
|
||||
refX="10"
|
||||
refY="3.5"
|
||||
orient="auto"
|
||||
>
|
||||
|
|
@ -1766,9 +1775,10 @@ export const FlowCanvas = forwardRef<FlowCanvasHandle, FlowCanvasProps>(function
|
|||
</marker>
|
||||
<marker
|
||||
id="arrowhead-warning"
|
||||
markerUnits="userSpaceOnUse"
|
||||
markerWidth="10"
|
||||
markerHeight="7"
|
||||
refX="9"
|
||||
refX="10"
|
||||
refY="3.5"
|
||||
orient="auto"
|
||||
>
|
||||
|
|
@ -1783,13 +1793,10 @@ export const FlowCanvas = forwardRef<FlowCanvasHandle, FlowCanvasProps>(function
|
|||
const tgtBase = getHandlePosition(tgtNode, c.targetHandle);
|
||||
const stack = inboundStacksByTarget.get(`${c.targetId}-${c.targetHandle}`) ?? [c];
|
||||
const si = stack.findIndex((x) => x.id === c.id);
|
||||
const spread = 12;
|
||||
const tgt =
|
||||
stack.length > 1
|
||||
? { ...tgtBase, x: tgtBase.x + (si - (stack.length - 1) / 2) * spread }
|
||||
: tgtBase;
|
||||
const lateralBias =
|
||||
stack.length > 1 ? (si - (stack.length - 1) / 2) * 14 : 0;
|
||||
const feedback = isLoopFeedbackEdge(c, srcNode, tgtNode);
|
||||
const pathD = connectionPathD(src, tgt, srcNode, tgtNode, feedback, nodes);
|
||||
const pathD = connectionPathD(src, tgtBase, srcNode, tgtNode, feedback, nodes, lateralBias);
|
||||
const isSelected = selectedConnectionId === c.id;
|
||||
const isWarning = connectionWarnings[c.id];
|
||||
const strokeColor = isSelected
|
||||
|
|
@ -1971,7 +1978,7 @@ export const FlowCanvas = forwardRef<FlowCanvasHandle, FlowCanvasProps>(function
|
|||
style={{
|
||||
top: pos.side === 'top' ? -HANDLE_OFFSET : undefined,
|
||||
bottom: pos.side === 'bottom' ? -HANDLE_OFFSET : undefined,
|
||||
left: pos.x - node.x - HANDLE_OFFSET,
|
||||
left: pos.x - node.x - NODE_BORDER - HANDLE_OFFSET,
|
||||
}}
|
||||
>
|
||||
{outputLabel && pos.side === 'bottom' && isOutput ? (
|
||||
|
|
|
|||
Loading…
Reference in a new issue