2019-09-19 22:25:37 +00:00
|
|
|
import React, { useState, useLayoutEffect, MutableRefObject } from "react";
|
|
|
|
|
import styled from "styled-components";
|
|
|
|
|
import { WidgetProps, WidgetOperations } from "../widgets/BaseWidget";
|
2019-09-21 01:52:38 +00:00
|
|
|
import { useDrop } from "react-dnd";
|
2019-09-17 10:09:00 +00:00
|
|
|
import { ContainerProps } from "./ContainerComponent";
|
|
|
|
|
import WidgetFactory from "../utils/WidgetFactory";
|
2019-09-19 22:25:37 +00:00
|
|
|
import { snapToGrid } from "../utils/helpers";
|
2019-09-21 01:52:38 +00:00
|
|
|
import DragLayerComponent from "./DragLayerComponent";
|
2019-09-19 22:25:37 +00:00
|
|
|
|
2019-09-22 20:25:05 +00:00
|
|
|
import { GridDefaults } from "../constants/WidgetConstants";
|
|
|
|
|
|
|
|
|
|
const {
|
|
|
|
|
DEFAULT_CELL_SIZE,
|
|
|
|
|
DEFAULT_WIDGET_HEIGHT,
|
|
|
|
|
DEFAULT_WIDGET_WIDTH,
|
|
|
|
|
} = GridDefaults;
|
2019-09-19 22:25:37 +00:00
|
|
|
|
2019-09-17 15:09:55 +00:00
|
|
|
type DropTargetComponentProps = ContainerProps & {
|
2019-09-19 22:25:37 +00:00
|
|
|
updateWidget?: Function;
|
2019-09-17 15:09:55 +00:00
|
|
|
};
|
2019-09-19 22:25:37 +00:00
|
|
|
|
|
|
|
|
const WrappedDropTarget = styled.div`
|
|
|
|
|
background: white;
|
|
|
|
|
`;
|
|
|
|
|
const DropTargetMask = styled.div`
|
|
|
|
|
position: absolute;
|
|
|
|
|
z-index: -10;
|
|
|
|
|
left: 0;
|
|
|
|
|
right: 0;
|
|
|
|
|
`;
|
|
|
|
|
|
2019-09-17 10:09:00 +00:00
|
|
|
export const DropTargetComponent = (props: DropTargetComponentProps) => {
|
2019-09-19 22:25:37 +00:00
|
|
|
const [dropTargetTopLeft, setDropTargetTopLeft] = useState({ x: 0, y: 0 });
|
|
|
|
|
const dropTargetMask: MutableRefObject<HTMLDivElement | null> = React.useRef(
|
|
|
|
|
null,
|
|
|
|
|
);
|
|
|
|
|
useLayoutEffect(() => {
|
|
|
|
|
const el = dropTargetMask.current;
|
|
|
|
|
if (el) {
|
|
|
|
|
const rect = el.getBoundingClientRect();
|
|
|
|
|
setDropTargetTopLeft({
|
|
|
|
|
x: rect.left,
|
|
|
|
|
y: rect.top,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}, [setDropTargetTopLeft]);
|
|
|
|
|
|
2019-09-21 01:52:38 +00:00
|
|
|
const [{ isOver }, drop] = useDrop({
|
2019-09-17 10:09:00 +00:00
|
|
|
accept: Object.values(WidgetFactory.getWidgetTypes()),
|
|
|
|
|
drop(item: WidgetProps, monitor) {
|
|
|
|
|
if (monitor.isOver({ shallow: true })) {
|
|
|
|
|
const item = monitor.getItem();
|
2019-09-21 01:52:38 +00:00
|
|
|
const clientOffset = monitor.getClientOffset();
|
2019-09-19 22:25:37 +00:00
|
|
|
if (clientOffset) {
|
|
|
|
|
const [x, y] = snapToGrid(
|
|
|
|
|
DEFAULT_CELL_SIZE,
|
|
|
|
|
clientOffset.x - dropTargetTopLeft.x,
|
|
|
|
|
clientOffset.y - dropTargetTopLeft.y,
|
|
|
|
|
);
|
2019-09-22 20:25:05 +00:00
|
|
|
if (item.widgetId) {
|
|
|
|
|
props.updateWidget &&
|
|
|
|
|
props.updateWidget(WidgetOperations.MOVE, item.widgetId, {
|
|
|
|
|
left: x,
|
|
|
|
|
top: y,
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
props.updateWidget &&
|
|
|
|
|
props.updateWidget(WidgetOperations.ADD_CHILD, props.widgetId, {
|
|
|
|
|
type: item.type,
|
|
|
|
|
left: x,
|
|
|
|
|
top: y,
|
|
|
|
|
width:
|
|
|
|
|
Math.round(DEFAULT_WIDGET_WIDTH / DEFAULT_CELL_SIZE) *
|
|
|
|
|
DEFAULT_CELL_SIZE,
|
|
|
|
|
height:
|
|
|
|
|
Math.round(DEFAULT_WIDGET_HEIGHT / DEFAULT_CELL_SIZE) *
|
|
|
|
|
DEFAULT_CELL_SIZE,
|
|
|
|
|
});
|
|
|
|
|
}
|
2019-09-19 22:25:37 +00:00
|
|
|
}
|
2019-09-17 10:09:00 +00:00
|
|
|
}
|
|
|
|
|
return undefined;
|
|
|
|
|
},
|
2019-09-19 22:25:37 +00:00
|
|
|
collect: monitor => ({
|
|
|
|
|
isOver: !!monitor.isOver({ shallow: true }),
|
|
|
|
|
}),
|
|
|
|
|
canDrop: (item, monitor) => {
|
|
|
|
|
return monitor.isOver({ shallow: true });
|
2019-09-17 10:09:00 +00:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
return (
|
2019-09-19 22:25:37 +00:00
|
|
|
<WrappedDropTarget
|
2019-09-17 10:09:00 +00:00
|
|
|
ref={drop}
|
|
|
|
|
style={{
|
|
|
|
|
left: props.style.xPosition + props.style.xPositionUnit,
|
2019-09-22 20:25:05 +00:00
|
|
|
height: props.style.defaultHeight,
|
|
|
|
|
width: props.style.defaultWidth,
|
2019-09-17 10:09:00 +00:00
|
|
|
top: props.style.yPosition + props.style.yPositionUnit,
|
|
|
|
|
}}
|
|
|
|
|
>
|
2019-09-19 22:25:37 +00:00
|
|
|
<DropTargetMask ref={dropTargetMask} />
|
2019-09-21 01:52:38 +00:00
|
|
|
<DragLayerComponent
|
2019-09-19 22:25:37 +00:00
|
|
|
parentOffset={dropTargetTopLeft}
|
|
|
|
|
width={DEFAULT_WIDGET_WIDTH}
|
|
|
|
|
height={DEFAULT_WIDGET_HEIGHT}
|
|
|
|
|
cellSize={DEFAULT_CELL_SIZE}
|
|
|
|
|
visible={isOver}
|
|
|
|
|
/>
|
|
|
|
|
{props.children}
|
|
|
|
|
</WrappedDropTarget>
|
2019-09-17 10:09:00 +00:00
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default DropTargetComponent;
|