You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openNG/src/client/hooks/draggable.js

79 lines
2.5 KiB
JavaScript

"use strict";
// const React = require("react");
const euclideanDistance = require("euclidean-distance");
const throttleit = require("throttleit");
// const useForceUpdate = require("use-force-update");
/* CAUTION: This hook has a bunch of effectively-global state! This is fine since a) there can only ever be one drag operation on a document at a time anyway, and b) this appears to be necessary to sidestep performance limitations introduced by React's state-handling cycles, but it's definitely something you shouldn't normally do. */
let operationData;
let isDragging;
let lastMouseX;
let lastMouseY;
let newX;
let newY;
let onChangeCallback;
let thresholdMet = false;
let dragThreshold;
function getCurrentValues() {
return {
x: operationData.initialValueX + (lastMouseX - operationData.initialMouseX),
y: operationData.initialValueY + (lastMouseY - operationData.initialMouseY)
};
}
let processMouseMove = throttleit(() => {
/* Yes, the below check is there for a reason; just in case the `movingWindow` state changes between the call to the throttled wrapper and the wrapped function itself. */
if (onChangeCallback != null) {
if (thresholdMet === false) {
let origin = [operationData.initialMouseX, operationData.initialMouseY];
let position = [lastMouseX, lastMouseY];
if (euclideanDistance(origin, position) > dragThreshold) {
thresholdMet = true;
}
}
if (thresholdMet === true) {
let {x, y} = getCurrentValues();
newX = x;
newY = y;
onChangeCallback(x, y, lastMouseX, lastMouseY);
}
}
}, 10);
module.exports = {
mouseMove: function (x, y) {
/* NOTE: Due to how synthetic events work in React, we need to separate out the 'get coordinates from event' and 'do something with the coordinates' step; if we throttle the coordinate extraction logic, we'll run into problems when synthetic events have already been cleared for reuse by the time we try to obtain the coordinates. Therefore, `processMouseMove` contains all the throttled logic, whereas the coordinate extraction happens on *every* mousemove event. */
lastMouseX = x;
lastMouseY = y;
if (isDragging) {
processMouseMove();
}
},
useDraggable: function (options) {
let dragEnded;
if (isDragging === true && options.isDragging === false) {
dragEnded = true;
} else {
dragEnded = false;
}
operationData = options.operationData;
dragThreshold = options.threshold;
onChangeCallback = options.onChange;
isDragging = options.isDragging;
if (dragEnded) {
return [newX, newY];
} else {
return [null, null];
}
}
};