import React, { useState } from "react"; import { WidgetProps } from "../widgets/BaseWidget"; import { WidgetConfigProps } from "../reducers/entityReducers/widgetConfigReducer"; import { useDrop, XYCoord } from "react-dnd"; import { ContainerProps } from "./ContainerComponent"; import WidgetFactory from "../utils/WidgetFactory"; import { widgetOperationParams } from "../utils/WidgetPropsUtils"; import DragLayerComponent from "./DragLayerComponent"; import DropTargetMask from "./DropTargetMask"; /*TODO: - Try to keep only component props, state and drop hook here - DONE - Move all child components to their own file - DONE - Provide Draglayer with the actual component size if exists - else pull it from widgetConfig - DONE - Provide Draglayer with rows, columns, rowHeight, columnWidth instead of width height pixels - DONE - Return rows and columns to the drop handler (updateWidget) - DONE - Update WidgetOperations to handle rows and columns - Increase default canvas rowHeight - Fix child container positioning */ type DropTargetComponentProps = ContainerProps & { updateWidget?: Function; snapColumns?: number; snapRows?: number; snapColumnSpace: number; snapRowSpace: number; }; type DropTargetBounds = { x: number; y: number; width: number; height: number; }; export const DropTargetComponent = (props: DropTargetComponentProps) => { // Hook to keep the bounds of the drop target container in state const [dropTargetOffset, setDropTargetOffset] = useState({ x: 0, y: 0 }); // Make this component a drop target const [{ isOver }, drop] = useDrop({ accept: Object.values(WidgetFactory.getWidgetTypes()), drop(widget: WidgetProps & Partial, monitor) { // Make sure we're dropping in this container. if (isOver) { props.updateWidget && props.updateWidget( ...widgetOperationParams( widget, monitor.getClientOffset() as XYCoord, dropTargetOffset, props.snapColumnSpace, props.snapRowSpace, props.widgetId, ), ); } return undefined; }, // Collect isOver for ui transforms when hovering over this component collect: monitor => ({ isOver: !!monitor.isOver({ shallow: true }), }), // Only allow drop if the drag object is directly over this component // As opposed to the drag object being over a child component, or outside the component bounds canDrop: (widget, monitor) => { return monitor.isOver({ shallow: true }); }, }); const handleBoundsUpdate = (rect: DOMRect) => { if (rect.x !== dropTargetOffset.x || rect.y !== dropTargetOffset.y) { setDropTargetOffset({ x: rect.x, y: rect.y, }); } }; return (
{props.children}
); }; export default DropTargetComponent;