-
Notifications
You must be signed in to change notification settings - Fork 2k
/
CustomDragLayer.tsx
80 lines (71 loc) · 1.63 KB
/
CustomDragLayer.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
import type { CSSProperties, FC } from 'react'
import { XYCoord, useDragLayer } from 'react-dnd'
import { ItemTypes } from './ItemTypes'
import { BoxDragPreview } from './BoxDragPreview'
import { snapToGrid } from './snapToGrid'
const layerStyles: CSSProperties = {
position: 'fixed',
pointerEvents: 'none',
zIndex: 100,
left: 0,
top: 0,
width: '100%',
height: '100%',
}
function getItemStyles(
initialOffset: XYCoord | null,
currentOffset: XYCoord | null,
isSnapToGrid: boolean,
) {
if (!initialOffset || !currentOffset) {
return {
display: 'none',
}
}
let { x, y } = currentOffset
if (isSnapToGrid) {
x -= initialOffset.x
y -= initialOffset.y
;[x, y] = snapToGrid(x, y)
x += initialOffset.x
y += initialOffset.y
}
const transform = `translate(${x}px, ${y}px)`
return {
transform,
WebkitTransform: transform,
}
}
export interface CustomDragLayerProps {
snapToGrid: boolean
}
export const CustomDragLayer: FC<CustomDragLayerProps> = (props) => {
const { itemType, isDragging, item, initialOffset, currentOffset } =
useDragLayer((monitor) => ({
item: monitor.getItem(),
itemType: monitor.getItemType(),
initialOffset: monitor.getInitialSourceClientOffset(),
currentOffset: monitor.getSourceClientOffset(),
isDragging: monitor.isDragging(),
}))
function renderItem() {
switch (itemType) {
case ItemTypes.BOX:
return <BoxDragPreview title={item.title} />
default:
return null
}
}
if (!isDragging) {
return null
}
return (
<div style={layerStyles}>
<div
style={getItemStyles(initialOffset, currentOffset, props.snapToGrid)}
>
{renderItem()}
</div>
</div>
)
}