From e0f0426e5938ba257391a5d47df9391f4d8492c8 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Sun, 22 Mar 2026 13:25:27 -0700 Subject: [PATCH] fix(canvas): limit separation dynamics to rApps/embeds, not drawings/slides - Add folk-shape to pushExemptTags so wb drawings (pencil, rect, circle, line) are exempt from repulsion and can overlap other shapes freely - Skip wb-drawing elements in repulsion loop and free-position placement - Locked shapes are not pushed by repulsion (full push goes to unlocked neighbor) - getExistingShapeRects uses pushExemptTags instead of hardcoded arrow check Co-Authored-By: Claude Opus 4.6 --- lib/folk-shape.ts | 2 +- website/canvas.html | 28 +++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/folk-shape.ts b/lib/folk-shape.ts index faeaa56..10400f5 100644 --- a/lib/folk-shape.ts +++ b/lib/folk-shape.ts @@ -297,7 +297,7 @@ export class FolkShape extends FolkElement { } static GAP = 8; // minimum gap between shapes - static pushExemptTags = new Set(["folk-arrow", "folk-slide"]); + static pushExemptTags = new Set(["folk-arrow", "folk-slide", "folk-shape"]); #highlighted = false; get highlighted() { diff --git a/website/canvas.html b/website/canvas.html index eb62edb..e6ba1dd 100644 --- a/website/canvas.html +++ b/website/canvas.html @@ -3828,10 +3828,12 @@ } // Collect bounding boxes of all visible shapes on the canvas + // Only includes rApps and embedded content — slides, drawings, and arrows are excluded function getExistingShapeRects() { return [...canvasContent.children] .filter(el => el.tagName && el.tagName.includes('-') && - !el.tagName.toLowerCase().includes('arrow') && + !FolkShape.pushExemptTags.has(el.tagName.toLowerCase()) && + !el.dataset?.wbDrawing && typeof el.x === 'number' && typeof el.width === 'number' && el.width > 0) .map(el => ({ x: el.x, y: el.y, width: el.width, height: el.height })); @@ -6869,6 +6871,7 @@ for (const el of canvasContent.children) { if (!(el instanceof FolkShape)) continue; if (FolkShape.pushExemptTags.has(el.tagName.toLowerCase())) continue; + if (el.dataset?.wbDrawing) continue; // wb drawings can overlap freely shapes.push(el); } @@ -6889,16 +6892,31 @@ if (push < REPEL_THRESHOLD) continue; const half = push / 2; + const aLocked = a.locked; + const bLocked = b.locked; + if (aLocked && bLocked) continue; // both locked, skip if (ox < oy) { // Push apart horizontally const sign = (a.x + a.width / 2) < (b.x + b.width / 2) ? -1 : 1; - a.x += sign * half; - b.x -= sign * half; + if (aLocked) { + b.x -= sign * push; + } else if (bLocked) { + a.x += sign * push; + } else { + a.x += sign * half; + b.x -= sign * half; + } } else { // Push apart vertically const sign = (a.y + a.height / 2) < (b.y + b.height / 2) ? -1 : 1; - a.y += sign * half; - b.y -= sign * half; + if (aLocked) { + b.y -= sign * push; + } else if (bLocked) { + a.y += sign * push; + } else { + a.y += sign * half; + b.y -= sign * half; + } } } }