fix: zoom-aware drag positioning + Text node safety in windowDrag
Some checks are pending
ci / docker publish / build (amd64) (push) Waiting to run
ci / docker publish / build (arm64) (push) Waiting to run
ci / docker publish / merge manifest + tag (push) Blocked by required conditions

_startDrag(): divide getBoundingClientRect().left/.top by zoom factor
(right/left dock paths too). Also guard e.target.closest() calls
against Text nodes that lack the method — prevents close/minimize
buttons from failing the skipSelector check and triggering a drag
on click.
This commit is contained in:
Lukas Parsons 2026-07-07 14:23:46 -04:00
parent 2e06a82cc1
commit e19f03fb5d

View file

@ -157,11 +157,12 @@ export function makeWindowDraggable(modal, options = {}) {
.forEach(a => a.cancel());
} catch (_) {}
const rect = content.getBoundingClientRect();
const z = parseFloat(getComputedStyle(document.documentElement).zoom) || 1;
if (onDragStart) {
try { onDragStart({ rect, cx, cy }); } catch (_) {}
}
startX = cx; startY = cy;
startLeft = rect.left; startTop = rect.top;
startLeft = rect.left / z; startTop = rect.top / z;
// Pin position so the drag follows the cursor instead of fighting a
// centering transform / margin. Inline styles win unless CSS uses
// !important (the fullscreen rules do, by design).
@ -214,16 +215,18 @@ export function makeWindowDraggable(modal, options = {}) {
if (rightDock && modal && modal.classList.contains('modal-right-docked')) {
if (rightDock.onMove(cx, cy)) {
const r = content.getBoundingClientRect();
const z2 = parseFloat(getComputedStyle(document.documentElement).zoom) || 1;
startX = cx; startY = cy;
startLeft = r.left; startTop = r.top;
startLeft = r.left / z2; startTop = r.top / z2;
}
return;
}
if (leftDock && modal && modal.classList.contains('modal-left-docked')) {
if (leftDock.onMove(cx, cy)) {
const r = content.getBoundingClientRect();
const z3 = parseFloat(getComputedStyle(document.documentElement).zoom) || 1;
startX = cx; startY = cy;
startLeft = r.left; startTop = r.top;
startLeft = r.left / z3; startTop = r.top / z3;
}
return;
}
@ -280,7 +283,7 @@ export function makeWindowDraggable(modal, options = {}) {
header.addEventListener('mousedown', (e) => {
if (mobileSkip > 0 && window.innerWidth <= mobileSkip) return;
if (skipSelector && e.target.closest(skipSelector)) return;
if (skipSelector && e.target.closest && e.target.closest(skipSelector)) return;
e.preventDefault();
movedDuringDrag = false;
_startDrag(e.clientX, e.clientY);
@ -309,7 +312,7 @@ export function makeWindowDraggable(modal, options = {}) {
if (enableTouch) {
header.addEventListener('touchstart', (e) => {
if (mobileSkip > 0 && window.innerWidth <= mobileSkip) return;
if (skipSelector && e.target.closest(skipSelector)) return;
if (skipSelector && e.target.closest && e.target.closest(skipSelector)) return;
const t = e.touches[0];
if (!t) return;
movedDuringDrag = false;