72 lines
3.7 KiB
JavaScript
72 lines
3.7 KiB
JavaScript
function createDialogDrag({ environment }) {
|
|
const { document, window } = environment;
|
|
const panels = ".opportunities-extension-action-form-dialog, .opportunities-extension-preferences-dialog, .opportunities-extension-account-plans-dialog, .oe-org-confirm-panel";
|
|
const positions = new WeakMap();
|
|
let installed = false, drag = null;
|
|
function move(panel, dx, dy) {
|
|
const rect = panel.getBoundingClientRect();
|
|
const viewport = window.visualViewport;
|
|
const left = viewport?.offsetLeft || 0, top = viewport?.offsetTop || 0;
|
|
const width = viewport?.width || document.documentElement.clientWidth;
|
|
const height = viewport?.height || document.documentElement.clientHeight;
|
|
const x = Math.max(left - rect.width * 0.7, Math.min(rect.left + dx, left + width - rect.width * 0.3));
|
|
const y = Math.max(top - rect.height * 0.7, Math.min(rect.top + dy, top + height - rect.height * 0.3));
|
|
const previous = positions.get(panel) || { x: 0, y: 0 };
|
|
const next = { x: previous.x + x - rect.left, y: previous.y + y - rect.top };
|
|
positions.set(panel, next);
|
|
panel.style.position = "relative";
|
|
panel.style.left = `${next.x}px`;
|
|
panel.style.top = `${next.y}px`;
|
|
panel.setAttribute("data-dialog-moved", "true");
|
|
}
|
|
function stop() {
|
|
if (!drag) return;
|
|
const previous = drag;
|
|
drag = null;
|
|
previous.panel.removeAttribute("data-dialog-dragging");
|
|
if (previous.title.hasPointerCapture?.(previous.id)) previous.title.releasePointerCapture(previous.id);
|
|
}
|
|
function install() {
|
|
if (installed || window.__opportunitiesDialogDragInstalled || !document.addEventListener || !window.addEventListener) return;
|
|
installed = true;
|
|
window.__opportunitiesDialogDragInstalled = true;
|
|
document.addEventListener("pointerdown", event => {
|
|
if (event.button !== 0 || event.isPrimary === false) return;
|
|
const title = event.target.closest?.("header, h2, h3");
|
|
const panel = title?.closest(panels);
|
|
if (!panel || !panel.closest(".opportunities-extension-modal") || panel.closest("[inert], [hidden]") ||
|
|
event.target.closest("button, a, input, select, textarea, [role='button'], [contenteditable='true']")) return;
|
|
// Accept the whole title bar, but not headers inside the dialog's content.
|
|
const heading = panel.querySelector("h2, h3");
|
|
if (!heading || (heading !== title && !title.contains(heading))) return;
|
|
const rect = panel.getBoundingClientRect();
|
|
if (rect.width >= document.documentElement.clientWidth - 2 && rect.height >= document.documentElement.clientHeight - 2) return;
|
|
stop();
|
|
event.preventDefault();
|
|
drag = { title, panel, id: event.pointerId, x: event.clientX, y: event.clientY };
|
|
panel.setAttribute("data-dialog-dragging", "true");
|
|
title.setPointerCapture?.(event.pointerId);
|
|
});
|
|
document.addEventListener("pointermove", event => {
|
|
if (!drag || event.pointerId !== drag.id) return;
|
|
if (!drag.panel.isConnected || drag.panel.closest("[hidden], [inert]")) { stop(); return; }
|
|
event.preventDefault();
|
|
move(drag.panel, event.clientX - drag.x, event.clientY - drag.y);
|
|
drag.x = event.clientX; drag.y = event.clientY;
|
|
});
|
|
for (const name of ["pointerup", "pointercancel", "lostpointercapture"]) {
|
|
document.addEventListener(name, event => { if (drag?.id === event.pointerId) stop(); });
|
|
}
|
|
window.addEventListener("blur", stop);
|
|
function resize() {
|
|
stop();
|
|
for (const panel of document.querySelectorAll('[data-dialog-moved="true"]')) {
|
|
if (panel.getClientRects().length) move(panel, 0, 0);
|
|
}
|
|
}
|
|
window.addEventListener("resize", resize);
|
|
window.visualViewport?.addEventListener("resize", resize);
|
|
}
|
|
return { install };
|
|
}
|