feat(canvas): implement edge insertion reflow and enhance connection validation

- Introduced a new CSS transition for edge insertion reflowing to improve visual feedback during node adjustments.
- Enhanced the connection validation logic to include options for optimistic edges, ensuring better handling of edge creation scenarios.
- Updated the canvas connection drop menu to support additional templates and improved edge insertion handling.
- Refactored edge insertion logic to accommodate local node position adjustments during reflow operations.
- Added tests for new edge insertion features and connection validation improvements.
This commit is contained in:
2026-04-05 23:25:26 +02:00
parent 7c34da45b4
commit fa6a41f775
14 changed files with 1477 additions and 67 deletions

View File

@@ -65,16 +65,27 @@ async function assertConnectionPolicy(
throw new Error("Source or target node not found");
}
const targetIncomingCount = await countIncomingEdges(ctx, {
targetNodeId: args.targetNodeId,
edgeIdToIgnore: args.edgeIdToIgnore,
});
const reason = validateCanvasConnectionPolicy({
sourceType: sourceNode.type,
targetType: targetNode.type,
targetIncomingCount: await countIncomingEdges(ctx, {
targetNodeId: args.targetNodeId,
edgeIdToIgnore: args.edgeIdToIgnore,
}),
targetIncomingCount,
});
if (reason) {
console.warn("[edges.create] connection policy rejected", {
sourceNodeId: args.sourceNodeId,
targetNodeId: args.targetNodeId,
edgeIdToIgnore: args.edgeIdToIgnore,
sourceType: sourceNode.type,
targetType: targetNode.type,
targetIncomingCount,
reason,
});
throw new Error(getCanvasConnectionValidationMessage(reason));
}
}
@@ -178,6 +189,13 @@ export const create = mutation({
const source = await ctx.db.get(args.sourceNodeId);
const target = await ctx.db.get(args.targetNodeId);
if (!source || !target) {
console.warn("[edges.create] missing source or target node", {
canvasId: args.canvasId,
sourceNodeId: args.sourceNodeId,
targetNodeId: args.targetNodeId,
hasSource: Boolean(source),
hasTarget: Boolean(target),
});
throw new Error("Source or target node not found");
}
if (source.canvasId !== args.canvasId || target.canvasId !== args.canvasId) {