-
Notifications
You must be signed in to change notification settings - Fork 2k
/
Card.tsx
69 lines (63 loc) · 1.41 KB
/
Card.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import { CSSProperties, FC, memo } from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { ItemTypes } from './ItemTypes'
const style: CSSProperties = {
border: '1px dashed gray',
padding: '0.5rem 1rem',
marginBottom: '.5rem',
backgroundColor: 'white',
cursor: 'move',
}
export interface CardProps {
id: string
text: string
moveCard: (id: string, to: number) => void
findCard: (id: string) => { index: number }
}
interface Item {
id: string
originalIndex: number
}
export const Card: FC<CardProps> = memo(function Card({
id,
text,
moveCard,
findCard,
}) {
const originalIndex = findCard(id).index
const [{ isDragging }, drag] = useDrag(
() => ({
type: ItemTypes.CARD,
item: { id, originalIndex },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
end: (item, monitor) => {
const { id: droppedId, originalIndex } = item
const didDrop = monitor.didDrop()
if (!didDrop) {
moveCard(droppedId, originalIndex)
}
},
}),
[id, originalIndex, moveCard],
)
const [, drop] = useDrop(
() => ({
accept: ItemTypes.CARD,
hover({ id: draggedId }: Item) {
if (draggedId !== id) {
const { index: overIndex } = findCard(id)
moveCard(draggedId, overIndex)
}
},
}),
[findCard, moveCard],
)
const opacity = isDragging ? 0 : 1
return (
<div ref={(node) => drag(drop(node))} style={{ ...style, opacity }}>
{text}
</div>
)
})