UNPKG

@zohodesk/dot

Version:

In this Library, we Provide Some Basic Components to Build Your Application

142 lines (128 loc) 4.45 kB
//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({ isActive, ChildRef, boundaryLimit = getDotLibraryConfig('boundaryLimit') }) { const draggableEle = useRef(null); const parentEle = useRef(null); const offset = useRef({ x: 0, y: 0 }); const draggable = useRef(false); const dragStarted = useRef(false); const initialMouse = useRef({ x: 0, y: 0 }); const DRAG_DISTANCE_THRESHOLD = 4; 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) { return; } if (!dragStarted.current) { const dx = Math.abs(e.clientX - initialMouse.current.x); const dy = Math.abs(e.clientY - initialMouse.current.y); if (dx < DRAG_DISTANCE_THRESHOLD && dy < DRAG_DISTANCE_THRESHOLD) { return; } const draggableEleRect = draggableEle.current.getBoundingClientRect(); const parentEleRect = parentEle ? parentEle.current.getBoundingClientRect() : { left: 0, top: 0 }; offset.current.x = draggableEleRect.left - e.clientX; offset.current.y = draggableEleRect.top - e.clientY; const relativeRect = { left: draggableEleRect.left - parentEleRect.left, top: draggableEleRect.top - parentEleRect.top }; const styleRef = draggableEle.current.style; styleRef.top = `${relativeRect.top}px`; styleRef.left = `${relativeRect.left}px`; styleRef.width = `${draggableEleRect.width}px`; styleRef.position = "fixed"; styleRef.bottom = "initial"; styleRef.right = "initial"; dragStarted.current = true; } 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); dragStarted.current = false; draggable.current = false; }, []); const dragMouseDown = useCallback(e => { e = e || window.event; // e.preventDefault(); initialMouse.current = { x: e.clientX, y: e.clientY }; dragStarted.current = false; 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;