-
Notifications
You must be signed in to change notification settings - Fork 2k
/
Container.tsx
84 lines (77 loc) · 1.74 KB
/
Container.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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { CSSProperties, FC, useCallback, useState } from 'react'
import { useDrop, XYCoord } from 'react-dnd'
import { ItemTypes } from './ItemTypes'
import { Box } from './Box'
import update from 'immutability-helper'
import type { DragItem } from './interfaces'
const styles: CSSProperties = {
width: 300,
height: 300,
border: '1px solid black',
position: 'relative',
}
export interface ContainerProps {
hideSourceOnDrag: boolean
}
export interface ContainerState {
boxes: { [key: string]: { top: number; left: number; title: string } }
}
export const Container: FC<ContainerProps> = ({ hideSourceOnDrag }) => {
const [boxes, setBoxes] = useState<{
[key: string]: {
top: number
left: number
title: string
}
}>({
a: { top: 20, left: 80, title: 'Drag me around' },
b: { top: 180, left: 20, title: 'Drag me too' },
})
const moveBox = useCallback(
(id: string, left: number, top: number) => {
setBoxes(
update(boxes, {
[id]: {
$merge: { left, top },
},
}),
)
},
[boxes, setBoxes],
)
const [, drop] = useDrop(
() => ({
accept: ItemTypes.BOX,
drop(item: DragItem, monitor) {
const delta = monitor.getDifferenceFromInitialOffset() as XYCoord
const left = Math.round(item.left + delta.x)
const top = Math.round(item.top + delta.y)
moveBox(item.id, left, top)
return undefined
},
}),
[moveBox],
)
return (
<div ref={drop} style={styles}>
{Object.keys(boxes).map((key) => {
const { left, top, title } = boxes[key] as {
top: number
left: number
title: string
}
return (
<Box
key={key}
id={key}
left={left}
top={top}
hideSourceOnDrag={hideSourceOnDrag}
>
{title}
</Box>
)
})}
</div>
)
}