* Fix: On renaming a widget via entity explorer the canvas gets resized * Fix: Close prop pane on resize start of unselected widget. * Fix: Match all - corejs polyfill * Fix: Proppane not updated properly when same type widgets are selected. * Feature: Draggable Proppane. * Bug fixes for draggable popup. * Fix: Property pane editor when selecting another widget. * resolve rebase bad merges. * cytest fix * cytest fix * cytest fix * cytest fix * cytest fix * cytest fix * cytest fixes * cytest fix * fixing draggable components inside porp pane. * Adding cypress test. * refactored Draggable list POC version * reverting unwanted changes. * prop pane bug fix * unwanted dependencies. * double click to open prop pane. * Fixing bugs in draggable prop pane. * one click prop pane open. * ignore drag/resize click captures * make prop pane draggable only via drag handler. * Fixed property pane title. * converting layer to hook and adding it to top most layer. * removing irrelevant comments. * close panel when widget changes. * fixing cytests. * bug fix * fixing cytest * Addressing code review comments. * bug fix
146 lines
3.9 KiB
TypeScript
146 lines
3.9 KiB
TypeScript
import { debounce } from "lodash";
|
|
import ReactDOM from "react-dom";
|
|
import ResizeObserver from "resize-observer-polyfill";
|
|
|
|
export const draggableElement = (
|
|
id: string,
|
|
element: any,
|
|
onPositionChange: any,
|
|
initPostion?: any,
|
|
dragHandle?: () => JSX.Element,
|
|
) => {
|
|
let newXPos = 0,
|
|
newYPos = 0,
|
|
oldXPos = 0,
|
|
oldYPos = 0;
|
|
let dragHandler = element;
|
|
let isDragged = !!initPostion;
|
|
|
|
const setElementPosition = () => {
|
|
element.style.top = initPostion.top + "px";
|
|
element.style.left = initPostion.left + "px";
|
|
};
|
|
|
|
const dragMouseDown = (e: MouseEvent) => {
|
|
e = e || window.event;
|
|
oldXPos = e.clientX;
|
|
oldYPos = e.clientY;
|
|
document.onmouseup = closeDragElement;
|
|
document.onmousemove = elementDrag;
|
|
};
|
|
const calculateBoundaryConfinedPosition = (
|
|
calculatedLeft: number,
|
|
calculatedTop: number,
|
|
) => {
|
|
if (calculatedLeft <= 0) {
|
|
calculatedLeft = 0;
|
|
}
|
|
if (calculatedTop <= 30) {
|
|
calculatedTop = 30;
|
|
}
|
|
if (calculatedLeft >= window.innerWidth - element.clientWidth) {
|
|
calculatedLeft = window.innerWidth - element.clientWidth;
|
|
}
|
|
if (calculatedTop >= window.innerHeight - element.clientHeight) {
|
|
calculatedTop = window.innerHeight - element.clientHeight;
|
|
}
|
|
return {
|
|
left: calculatedLeft,
|
|
top: calculatedTop,
|
|
};
|
|
};
|
|
|
|
const elementDrag = (e: MouseEvent) => {
|
|
e = e || window.event;
|
|
e.preventDefault();
|
|
newXPos = oldXPos - e.clientX;
|
|
newYPos = oldYPos - e.clientY;
|
|
oldXPos = e.clientX;
|
|
oldYPos = e.clientY;
|
|
const calculatedTop = element.offsetTop - newYPos;
|
|
const calculatedLeft = element.offsetLeft - newXPos;
|
|
element.style.top = calculatedTop + "px";
|
|
element.style.left = calculatedLeft + "px";
|
|
const validFirstDrag = !isDragged && newXPos !== 0 && newYPos !== 0;
|
|
if (validFirstDrag) {
|
|
resizeObserver.observe(element);
|
|
isDragged = true;
|
|
}
|
|
};
|
|
|
|
const calculateNewPosition = () => {
|
|
const { height, width, top, left } = element.getBoundingClientRect();
|
|
const isElementOpen = height && width;
|
|
const {
|
|
left: calculatedLeft,
|
|
top: calculatedTop,
|
|
} = calculateBoundaryConfinedPosition(left, top);
|
|
|
|
return {
|
|
updatePosition: isDragged && isElementOpen,
|
|
left: calculatedLeft,
|
|
top: calculatedTop,
|
|
};
|
|
};
|
|
|
|
const updateElementPosition = () => {
|
|
const calculatedPositionData = calculateNewPosition();
|
|
if (calculatedPositionData.updatePosition) {
|
|
const { left, top } = calculatedPositionData;
|
|
onPositionChange({
|
|
left: left,
|
|
top: top,
|
|
});
|
|
element.style.top = top + "px";
|
|
element.style.left = left + "px";
|
|
}
|
|
};
|
|
|
|
const closeDragElement = () => {
|
|
updateElementPosition();
|
|
document.onmouseup = null;
|
|
document.onmousemove = null;
|
|
};
|
|
const debouncedUpdatePosition = debounce(updateElementPosition, 50);
|
|
|
|
const resizeObserver = new ResizeObserver(function() {
|
|
debouncedUpdatePosition();
|
|
});
|
|
|
|
if (isDragged) {
|
|
resizeObserver.observe(element);
|
|
}
|
|
|
|
const OnInit = () => {
|
|
if (dragHandle) {
|
|
dragHandler = createDragHandler(id, element, dragHandle);
|
|
}
|
|
if (initPostion) {
|
|
setElementPosition();
|
|
}
|
|
dragHandler.addEventListener("mousedown", dragMouseDown);
|
|
// stop clicks from propogating to widget editor.
|
|
dragHandler.addEventListener("click", (e: any) => e.stopPropagation());
|
|
};
|
|
|
|
OnInit();
|
|
};
|
|
|
|
const createDragHandler = (
|
|
id: string,
|
|
el: any,
|
|
dragHandle: () => JSX.Element,
|
|
) => {
|
|
const oldDragHandler = document.getElementById(`${id}-draghandler`);
|
|
const dragElement = document.createElement("div");
|
|
dragElement.setAttribute("id", `${id}-draghandler`);
|
|
dragElement.style.position = "absolute";
|
|
dragElement.style.left = "0px";
|
|
dragElement.style.top = "0px";
|
|
oldDragHandler
|
|
? el.replaceChild(dragElement, oldDragHandler)
|
|
: el.appendChild(dragElement);
|
|
ReactDOM.render(dragHandle(), dragElement);
|
|
return dragElement;
|
|
};
|