@zohodesk/dot
Version:
In this Library, we Provide Some Basic Components to Build Your Application
124 lines (114 loc) • 3.9 kB
JavaScript
//Hooks from React
import { useEffect, useRef, useCallback } from 'react'; //CustomFunction
import { DragPosCalc } from "./utils/DraggerUtil"; //GlobalConfig
import { getDotLibraryConfig } from "../../Provider/Config"; //Props
import defaultProps from "./props/defaultProps";
import propTypes from "./props/propTypes"; //CSS
import style from "./css/Dragger.module.css";
export default function useDragger(_ref) {
let {
isActive,
ChildRef,
boundaryLimit = getDotLibraryConfig('boundaryLimit')
} = _ref;
const draggableEle = useRef(null);
const parentEle = useRef(null);
const offset = useRef({
x: 0,
y: 0
});
const draggable = useRef(false);
useEffect(() => {
if (isActive) {
parentEle.current = ChildRef.current.closest('[data-drag-parent=true]') || getDotLibraryConfig('draggerBoundary') || document.body;
}
}, [isActive]); //calculateDragPosition --> To sperate Dom action
const calculateDragPosition = useCallback((x, y) => {
if (parentEle.current && draggableEle.current) {
return DragPosCalc({
x,
y,
dragWrapper: parentEle.current,
element: draggableEle.current,
boundaryLimit
});
} else {
return {
x,
y
};
}
}, []);
const elementDrag = useCallback(e => {
e = e || window.event;
e.preventDefault();
if (draggable.current) {
const left = offset.current.x + e.clientX;
const top = offset.current.y + e.clientY;
const {
x,
y
} = calculateDragPosition(left, top);
draggableEle.current.style.left = x + 'px';
draggableEle.current.style.top = y + 'px';
}
}, [calculateDragPosition]);
const closeDragElement = useCallback(() => {
document.removeEventListener('mouseup', closeDragElement);
document.removeEventListener('mousemove', elementDrag);
}, []);
const dragMouseDown = useCallback(e => {
e = e || window.event; // e.preventDefault();
const draggableEleRect = draggableEle.current.getBoundingClientRect();
const style = draggableEle.current.style;
const {
width
} = draggableEleRect;
const parentEleRect = parentEle ? parentEle.current.getBoundingClientRect() : {
left: 0,
top: 0
};
const relativeRect = {
left: draggableEleRect.left - parentEleRect.left,
top: draggableEleRect.top - parentEleRect.top
};
const {
top,
left
} = relativeRect;
style.top = `${top}px`;
style.left = `${left}px`;
style.width = `${width}px`;
style.bottom = 'initial';
style.right = 'initial';
style.position = 'fixed';
offset.current.x = draggableEle.current.offsetLeft - e.clientX;
offset.current.y = draggableEle.current.offsetTop - e.clientY;
draggable.current = true;
document.addEventListener('mouseup', closeDragElement);
document.addEventListener('mousemove', elementDrag);
}, []);
const removeListener = useCallback(draggableEle => {
let dragController = draggableEle.current && draggableEle.current.querySelector('[data-drag-hook=true]');
if (dragController) {
dragController.removeEventListener('mousedown', dragMouseDown);
draggableEle.current = null;
}
}, []);
useEffect(() => {
if (isActive) {
draggableEle.current = ChildRef.current.closest('[data-drag-container=true]');
let dragController = draggableEle.current && draggableEle.current.querySelector('[data-drag-hook=true]');
dragController && dragController.addEventListener('mousedown', dragMouseDown);
dragController && dragController.classList.add(style.dragCursor);
} else {
removeListener(draggableEle);
}
return () => {
removeListener(draggableEle);
};
}, [ChildRef.current, isActive]);
return null;
} //Props
useDragger.propTypes = propTypes;
useDragger.defaultProps = defaultProps;