diff --git a/src/js/components/Fields/Commands.js b/src/js/components/Fields/Commands.js index 88ccb82f..e7a0554a 100644 --- a/src/js/components/Fields/Commands.js +++ b/src/js/components/Fields/Commands.js @@ -1,9 +1,86 @@ -import React, { useState, useEffect } from 'react'; -import { ReactSortable } from 'react-sortablejs'; +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 ( +