fix(ui): +Dev inside a frame was silently dropped
onCanvasPointerDown returned early whenever the click landed on a [data-device-id] or [data-frame-id] element so the per-element drag handlers wouldn't get hijacked. Problem: this early-return fired BEFORE the tool check, so clicking +Dev inside an existing frame never reached placeDeviceAt(). Reordered: tool-armed branches run first and short-circuit. Only when no tool is armed does the "click started on a child element — leave it alone" guard kick in. End behaviour: - +Dev anywhere (incl. inside a frame) drops a device. frame_id auto-resolves via the existing frameAt() point-in-rect. - +Frm anywhere (incl. inside an existing frame) starts a rubber-band; rare but not harmful. - No tool armed: clicking a device/frame still goes to its own handler (drag / select). Clicking empty canvas still clears selection. Hand-tested via the served /main.js + the equivalent backend POST/PATCH sequence: device-in-frame, device-outside, device-drag, frame-drag with cascaded device patches — all work.
This commit is contained in:
@@ -458,12 +458,13 @@ let rubberStart = /** @type {{x:number,y:number}|null} */ (null);
|
|||||||
|
|
||||||
function onCanvasPointerDown(e) {
|
function onCanvasPointerDown(e) {
|
||||||
if (!state.active) return;
|
if (!state.active) return;
|
||||||
// Ignore clicks that started on a device/frame — their own handlers
|
|
||||||
// captured the pointer already.
|
|
||||||
if (e.target instanceof Element && e.target.closest("[data-device-id], [data-frame-id]")) return;
|
|
||||||
|
|
||||||
const p = svgPoint(e);
|
const p = svgPoint(e);
|
||||||
|
|
||||||
|
// Armed tool wins: a click anywhere on the canvas — including on top
|
||||||
|
// of an existing frame or device — fires the tool. The +Dev tool needs
|
||||||
|
// this so m can drop a device inside a frame; without it the frame's
|
||||||
|
// own pointerdown handler would steal the click and start a drag.
|
||||||
if (state.tool === "frame") {
|
if (state.tool === "frame") {
|
||||||
startFrameRubberBand(e, p);
|
startFrameRubberBand(e, p);
|
||||||
return;
|
return;
|
||||||
@@ -472,6 +473,11 @@ function onCanvasPointerDown(e) {
|
|||||||
placeDeviceAt(p);
|
placeDeviceAt(p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No tool armed: clicks that started on a device/frame go to their
|
||||||
|
// own handlers (drag / select). Leave them alone.
|
||||||
|
if (e.target instanceof Element && e.target.closest("[data-device-id], [data-frame-id]")) return;
|
||||||
|
|
||||||
// Plain canvas click = clear selection.
|
// Plain canvas click = clear selection.
|
||||||
if (state.selection) { state.selection = null; render(); }
|
if (state.selection) { state.selection = null; render(); }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user