feat: implement createNodeConnectedFromSource functionality for enhanced node creation

- Added a new mutation to create nodes connected to existing nodes, improving the canvas interaction model.
- Updated the CanvasPlacementContext to include createNodeConnectedFromSource, allowing for seamless node connections.
- Refactored the PromptNode component to utilize the new connection method, enhancing the workflow for AI image generation.
- Introduced optimistic updates for immediate UI feedback during node creation and connection processes.
This commit is contained in:
Matthias
2026-03-28 00:06:45 +01:00
parent 5dd5dcf55b
commit b243443431
5 changed files with 376 additions and 86 deletions

View File

@@ -17,7 +17,8 @@ const RESIZE_CONFIGS: Record<string, ResizeConfig> = {
group: { minWidth: 150, minHeight: 100 },
image: { minWidth: 140, minHeight: 120, keepAspectRatio: true },
asset: { minWidth: 140, minHeight: 208, keepAspectRatio: false },
"ai-image": { minWidth: 200, minHeight: 200 },
// Chrome 88 + min. Viewport 120 → äußere Mindesthöhe 208 (siehe canvas onNodesChange)
"ai-image": { minWidth: 200, minHeight: 208, keepAspectRatio: false },
compare: { minWidth: 300, minHeight: 200 },
prompt: { minWidth: 260, minHeight: 220 },
text: { minWidth: 220, minHeight: 90 },

View File

@@ -118,9 +118,8 @@ export default function PromptNode({
availableCredits !== null && availableCredits >= creditCost;
const updateData = useMutation(api.nodes.updateData);
const createEdge = useMutation(api.edges.create);
const generateImage = useAction(api.ai.generateImage);
const { createNodeWithIntersection } = useCanvasPlacement();
const { createNodeConnectedFromSource } = useCanvasPlacement();
const debouncedSave = useDebouncedCallback(() => {
const raw = dataRef.current as Record<string, unknown>;
@@ -215,7 +214,9 @@ export default function PromptNode({
const viewport = getImageViewportSize(aspectRatio);
const outer = getAiImageNodeOuterSize(viewport);
const aiNodeId = await createNodeWithIntersection({
const clientRequestId = crypto.randomUUID();
const aiNodeId = await createNodeConnectedFromSource({
type: "ai-image",
position: { x: posX, y: posY },
width: outer.width,
@@ -229,13 +230,8 @@ export default function PromptNode({
outputWidth: viewport.width,
outputHeight: viewport.height,
},
clientRequestId: crypto.randomUUID(),
});
await createEdge({
canvasId,
clientRequestId,
sourceNodeId: id as Id<"nodes">,
targetNodeId: aiNodeId,
sourceHandle: "prompt-out",
targetHandle: "prompt-in",
});
@@ -274,8 +270,7 @@ export default function PromptNode({
id,
getEdges,
getNode,
createNodeWithIntersection,
createEdge,
createNodeConnectedFromSource,
generateImage,
creditCost,
availableCredits,