import React, { useState, useEffect, useRef, useCallback } from 'react'; import { useDrop, useDrag } from 'react-dnd'; import Icon from '../Icon'; import Link from '../Link'; import { sortItems, indexToArray } from '../../util/arrays'; const DRAGGABLE_TYPE = 'COMMAND'; const Command = ({ index, onExecute, onDrag, onDragEnd, command: { id, url, name, icon, colour, } = {}, }) => { const ref = useRef(null); const [{ isDragging }, dragRef] = useDrag({ type: DRAGGABLE_TYPE, item: { index }, collect: (monitor) => ({ isDragging: monitor.isDragging(), }), end: onDragEnd, }); const [_dropProps, dropRef] = useDrop({ accept: DRAGGABLE_TYPE, hover: (item, monitor) => { const dragIndex = item.index; const hoverIndex = index; const hoverBoundingRect = ref.current?.getBoundingClientRect() const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2; const hoverActualY = monitor.getClientOffset().y - hoverBoundingRect.top; // if dragging down, continue only when hover is smaller than middle Y if (dragIndex < hoverIndex && hoverActualY < hoverMiddleY) return; // if dragging up, continue only when hover is bigger than middle Y if (dragIndex > hoverIndex && hoverActualY > hoverMiddleY) return; onDrag(dragIndex, hoverIndex); item.index = hoverIndex; }, }) let className = 'list__item commands-setup__item'; if (isDragging) className += ' list__item--dragging'; return (