@@ -27681,9 +27681,33 @@ import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, re
2768127681 const hulls = Array.from(container.querySelectorAll(".plan-cluster"))
2768227682 .filter(el => carriedCids.has(el.dataset.cluster))
2768327683 .map(el => ({ el, x: parseFloat(el.style.left) || 0, y: parseFloat(el.style.top) || 0 }));
27684+ /* HOW FAR THE BOARD MAY BE STRETCHED. It grows with whatever is on it, so
27685+ a card pulled to the edge of the visible board makes room to be pulled
27686+ further, drop after drop, and nothing ever stopped it: one went to
27687+ x ≈ 11 000 and was off the screen after a reload. A group may reach one
27688+ screenful past the furthest object it is NOT carrying — room to spread
27689+ machines out, not room to lose one. Worked out once, here: whatever is
27690+ not carried does not move while the hand is down. */
27691+ const _carried = new Set([bid, ...followers.map(f => f.id)]);
27692+ let farRight = 0, farBottom = 0;
27693+ Array.from(container.children).forEach(el => {
27694+ const oid = el.dataset.boardId;
27695+ if (!oid || _carried.has(oid) || !el.offsetWidth) return;
27696+ farRight = Math.max(farRight, (parseFloat(el.style.left) || 0) + el.offsetWidth);
27697+ farBottom = Math.max(farBottom, (parseFloat(el.style.top) || 0) + el.offsetHeight);
27698+ });
27699+ const _scroll = container.closest(".printers-scroll");
27700+ const _zoomNow = _printerZoom || 1;
27701+ const viewW = (_scroll ? _scroll.clientWidth : window.innerWidth) / _zoomNow;
27702+ const viewH = (_scroll ? _scroll.clientHeight : window.innerHeight) / _zoomNow;
27703+ // How far the group's own right / bottom edge sits past its leader's origin.
27704+ const reachX = Math.max(card.offsetWidth, ...followers.map(f => f.dx + f.el.offsetWidth));
27705+ const reachY = Math.max(card.offsetHeight, ...followers.map(f => f.dy + f.el.offsetHeight));
2768427706 _planG = { id: bid, card, followers, hulls, container, pointerId: e.pointerId,
2768527707 sx: e.clientX, sy: e.clientY, ox: pos.x, oy: pos.y,
2768627708 w: card.offsetWidth, h: card.offsetHeight,
27709+ maxX: Math.max(0, farRight + viewW - reachX),
27710+ maxY: Math.max(0, farBottom + viewH - reachY),
2768727711 neighbours: planNeighboursIn(container, "boardId", boardPos, bid)
2768827712 // An object being carried cannot also be something to snap to.
2768927713 .filter(o => !_planSel.has(o.id)) };
@@ -27732,6 +27756,9 @@ import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, re
2773227756 or the card trails the cursor by exactly the zoom factor. */
2773327757 const z = _printerZoom || 1;
2773427758 const want = planSnap(g.ox + dx / z, g.oy + dy / z, g.w, g.h, g.neighbours);
27759+ // The limit wins over a snap: a guide that points past it would lie.
27760+ if (want.x > g.maxX) { want.x = Math.round(g.maxX); want.guideX = null; }
27761+ if (want.y > g.maxY) { want.y = Math.round(g.maxY); want.guideY = null; }
2773527762 g.nx = want.x; g.ny = want.y;
2773627763 _planHeldPos.set(g.id, { x: want.x, y: want.y });
2773727764 g.followers.forEach(f => _planHeldPos.set(f.id, { x: want.x + f.dx, y: want.y + f.dy }));
0 commit comments