|
1 | | -import React, { useEffect, useState, memo, useContext } from "react"; |
2 | | - |
| 1 | +import React, { useEffect, useState, memo, useContext, useRef } from "react"; |
| 2 | +import { useDrag, useDrop } from "react-dnd"; |
3 | 3 | //Scripts |
4 | 4 | import { dataContext } from "../../context/dataContext"; |
5 | 5 |
|
6 | 6 | //Minor components |
7 | 7 | import { TagContent, Tag, DeleteIcon } from "./styles"; |
8 | 8 |
|
9 | | -const TagComponent = ({ data, index, type, style, todoAmount }) => { |
| 9 | +const TagComponent = ({ data, index, type, style, todoAmount, moveTag, id }) => { |
| 10 | + const ref = useRef(null); |
| 11 | + const [{ handlerId }, drop] = useDrop({ |
| 12 | + accept: "tag", |
| 13 | + collect(monitor) { |
| 14 | + return { |
| 15 | + handlerId: monitor.getHandlerId(), |
| 16 | + }; |
| 17 | + }, |
| 18 | + hover(item, monitor) { |
| 19 | + if (!ref.current) { |
| 20 | + return; |
| 21 | + } |
| 22 | + const dragIndex = item.index; |
| 23 | + const hoverIndex = index; |
| 24 | + // Don't replace items with themselves |
| 25 | + if (dragIndex === hoverIndex) { |
| 26 | + return; |
| 27 | + } |
| 28 | + // Determine rectangle on screen |
| 29 | + const hoverBoundingRect = ref.current?.getBoundingClientRect(); |
| 30 | + // Get vertical middle |
| 31 | + const hoverMiddleY = |
| 32 | + (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2; |
| 33 | + // Determine mouse position |
| 34 | + const clientOffset = monitor.getClientOffset(); |
| 35 | + // Get pixels to the top |
| 36 | + const hoverClientY = clientOffset.y - hoverBoundingRect.top; |
| 37 | + // Only perform the move when the mouse has crossed half of the items height |
| 38 | + // When dragging downwards, only move when the cursor is below 50% |
| 39 | + // When dragging upwards, only move when the cursor is above 50% |
| 40 | + // Dragging downwards |
| 41 | + if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) { |
| 42 | + return; |
| 43 | + } |
| 44 | + // Dragging upwards |
| 45 | + if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) { |
| 46 | + return; |
| 47 | + } |
| 48 | + // Time to actually perform the action |
| 49 | + moveTag(dragIndex, hoverIndex); |
| 50 | + // Note: we're mutating the monitor item here! |
| 51 | + // Generally it's better to avoid mutations, |
| 52 | + // but it's good here for the sake of performance |
| 53 | + // to avoid expensive index searches. |
| 54 | + item.index = hoverIndex; |
| 55 | + }, |
| 56 | + }); |
| 57 | + //eslint-disable-next-line |
| 58 | + const [{ isDragging }, drag] = useDrag({ |
| 59 | + type: "tag", |
| 60 | + item: () => { |
| 61 | + return { id, index }; |
| 62 | + }, |
| 63 | + collect: (monitor) => ({ |
| 64 | + isDragging: monitor.isDragging(), |
| 65 | + }), |
| 66 | + }); |
| 67 | + drag(drop(ref)); |
| 68 | + |
10 | 69 | const [opacity, setOpacity] = useState(0); |
11 | 70 | const [background, setBackground] = useState(""); |
12 | 71 | const [padding, setPadding] = useState(0); |
@@ -86,10 +145,11 @@ const TagComponent = ({ data, index, type, style, todoAmount }) => { |
86 | 145 | setOpacity(1); |
87 | 146 | }, 250); |
88 | 147 | } |
89 | | - |
90 | 148 | return ( |
91 | 149 | <> |
92 | 150 | <TagContent |
| 151 | + ref={ref} |
| 152 | + data-handler-id={handlerId} |
93 | 153 | style={{ |
94 | 154 | ...style, |
95 | 155 | opacity: opacity, |
|
0 commit comments