Show grid only on hover. Remove min grid space between adjacent components. Fix all dropzones showing issue. Disable show control on hover.

This commit is contained in:
Abhinav Jha 2019-10-03 20:44:50 +05:30
parent 5bf84ee361
commit 622e5dc0a9
6 changed files with 61 additions and 43 deletions

View File

@ -4,6 +4,7 @@ import { useDragLayer, XYCoord } from "react-dnd";
import DropZone from "./Dropzone"; import DropZone from "./Dropzone";
import { noCollision } from "../utils/WidgetPropsUtils"; import { noCollision } from "../utils/WidgetPropsUtils";
import { OccupiedSpace } from "../widgets/ContainerWidget"; import { OccupiedSpace } from "../widgets/ContainerWidget";
import DropTargetMask from "./DropTargetMask";
const WrappedDragLayer = styled.div` const WrappedDragLayer = styled.div`
position: absolute; position: absolute;
@ -23,6 +24,8 @@ type DragLayerProps = {
visible: boolean; visible: boolean;
dropTargetOffset: XYCoord; dropTargetOffset: XYCoord;
occupiedSpaces: OccupiedSpace[] | null; occupiedSpaces: OccupiedSpace[] | null;
onBoundsUpdate: Function;
isOver: boolean;
}; };
const DragLayerComponent = (props: DragLayerProps) => { const DragLayerComponent = (props: DragLayerProps) => {
@ -54,8 +57,15 @@ const DragLayerComponent = (props: DragLayerProps) => {
} }
return ( return (
<WrappedDragLayer> <WrappedDragLayer>
<DropTargetMask
rowHeight={props.parentRowHeight}
columnWidth={props.parentColumnWidth}
setBounds={props.onBoundsUpdate}
showGrid={isDragging && props.isOver}
/>
<DropZone <DropZone
{...props} {...props}
visible={props.visible && props.isOver}
width={widgetWidth} width={widgetWidth}
height={widgetHeight} height={widgetHeight}
currentOffset={currentOffset as XYCoord} currentOffset={currentOffset as XYCoord}

View File

@ -16,9 +16,6 @@ const DraggableWrapper = styled.div<{ show: boolean }>`
& > div.control { & > div.control {
display: ${props => (props.show ? "block" : "none")}; display: ${props => (props.show ? "block" : "none")};
} }
&:hover > div {
display: block;
}
display: block; display: block;
`; `;

View File

@ -7,7 +7,6 @@ import { ContainerProps } from "./ContainerComponent";
import WidgetFactory from "../utils/WidgetFactory"; import WidgetFactory from "../utils/WidgetFactory";
import { widgetOperationParams, noCollision } from "../utils/WidgetPropsUtils"; import { widgetOperationParams, noCollision } from "../utils/WidgetPropsUtils";
import DragLayerComponent from "./DragLayerComponent"; import DragLayerComponent from "./DragLayerComponent";
import DropTargetMask from "./DropTargetMask";
type DropTargetComponentProps = ContainerProps & { type DropTargetComponentProps = ContainerProps & {
updateWidget?: Function; updateWidget?: Function;
@ -29,7 +28,7 @@ export const DropTargetComponent = (props: DropTargetComponentProps) => {
// Hook to keep the offset of the drop target container in state // Hook to keep the offset of the drop target container in state
const [dropTargetOffset, setDropTargetOffset] = useState({ x: 0, y: 0 }); const [dropTargetOffset, setDropTargetOffset] = useState({ x: 0, y: 0 });
// Make this component a drop target // Make this component a drop target
const [{ isOver }, drop] = useDrop({ const [{ isOver, isExactlyOver }, drop] = useDrop({
accept: Object.values(WidgetFactory.getWidgetTypes()), accept: Object.values(WidgetFactory.getWidgetTypes()),
drop(widget: WidgetProps & Partial<WidgetConfigProps>, monitor) { drop(widget: WidgetProps & Partial<WidgetConfigProps>, monitor) {
// Make sure we're dropping in this container. // Make sure we're dropping in this container.
@ -54,6 +53,7 @@ export const DropTargetComponent = (props: DropTargetComponentProps) => {
(monitor.isOver({ shallow: true }) && (monitor.isOver({ shallow: true }) &&
props.widgetId !== monitor.getItem().widgetId) || props.widgetId !== monitor.getItem().widgetId) ||
(monitor.isOver() && props.widgetId !== monitor.getItem().widgetId), (monitor.isOver() && props.widgetId !== monitor.getItem().widgetId),
isExactlyOver: monitor.isOver({ shallow: true }),
}), }),
// Only allow drop if the drag object is directly over this component // 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 // As opposed to the drag object being over a child component, or outside the component bounds
@ -86,27 +86,31 @@ export const DropTargetComponent = (props: DropTargetComponentProps) => {
return ( return (
<div <div
ref={drop} ref={drop}
className="dropTarget"
style={{ style={{
position: "absolute", position: "relative",
left: props.style.xPosition + props.style.xPositionUnit, left: 0,
height: props.style.componentHeight, height: props.isRoot
width: props.style.componentWidth, ? props.style.componentHeight + (props.style.heightUnit || "px")
top: props.style.yPosition + props.style.yPositionUnit, : "100%",
width: props.isRoot
? props.style.componentWidth + (props.style.widthUnit || "px")
: "100%",
top: 0,
background: "white",
}} }}
> >
<DropTargetMask
rowHeight={props.snapRowSpace}
columnWidth={props.snapColumnSpace}
setBounds={handleBoundsUpdate}
/>
<DragLayerComponent <DragLayerComponent
parentOffset={dropTargetOffset} parentOffset={dropTargetOffset}
parentRowHeight={props.snapRowSpace} parentRowHeight={props.snapRowSpace}
parentColumnWidth={props.snapColumnSpace} parentColumnWidth={props.snapColumnSpace}
visible={isOver} visible={isOver}
isOver={isExactlyOver}
dropTargetOffset={dropTargetOffset} dropTargetOffset={dropTargetOffset}
occupiedSpaces={props.occupiedSpaces} occupiedSpaces={props.occupiedSpaces}
onBoundsUpdate={handleBoundsUpdate}
/> />
{props.children} {props.children}
</div> </div>
); );

View File

@ -1,10 +1,11 @@
import React, { useLayoutEffect, MutableRefObject } from "react"; import React, { useLayoutEffect, MutableRefObject } from "react";
import styled from "styled-components"; import styled, { css } from "styled-components";
type DropTargetMaskProps = { type DropTargetMaskProps = {
rowHeight: number; rowHeight: number;
columnWidth: number; columnWidth: number;
setBounds: Function; setBounds: Function;
showGrid: boolean;
}; };
export const DropTargetMaskWrapper = styled.div<DropTargetMaskProps>` export const DropTargetMaskWrapper = styled.div<DropTargetMaskProps>`
@ -16,14 +17,19 @@ export const DropTargetMaskWrapper = styled.div<DropTargetMaskProps>`
width: 100%; width: 100%;
height: 100%; height: 100%;
background: white; background: white;
${props =>
props.showGrid &&
css`
background-image: radial-gradient( background-image: radial-gradient(
circle, circle,
${props => props.theme.colors.grid} 2px, ${props => props.theme.colors.grid} 2px,
transparent 0 transparent 0
); );
background-size: ${props => props.columnWidth}px ${props => props.rowHeight}px; background-size: ${props => props.columnWidth}px
${props => props.rowHeight}px;
background-position: -${props => props.columnWidth / 2}px -${props => background-position: -${props => props.columnWidth / 2}px -${props =>
props.rowHeight / 2}px; props.rowHeight / 2}px;
`}
`; `;
/* eslint-disable react/display-name */ /* eslint-disable react/display-name */
export const DropTargetMask = (props: DropTargetMaskProps) => { export const DropTargetMask = (props: DropTargetMaskProps) => {
@ -39,7 +45,6 @@ export const DropTargetMask = (props: DropTargetMaskProps) => {
props.setBounds(rect); props.setBounds(rect);
} }
}); });
return <DropTargetMaskWrapper {...props} ref={dropTargetMask} />; return <DropTargetMaskWrapper {...props} ref={dropTargetMask} />;
}; };

View File

@ -57,10 +57,10 @@ export const getDropZoneOffsets = (
const areIntersecting = (r1: Rect, r2: Rect) => { const areIntersecting = (r1: Rect, r2: Rect) => {
return !( return !(
r2.left > r1.right || r2.left >= r1.right ||
r2.right < r1.left || r2.right <= r1.left ||
r2.top > r1.bottom || r2.top >= r1.bottom ||
r2.bottom < r1.top r2.bottom <= r1.top
); );
}; };

View File

@ -90,19 +90,7 @@ class ContainerWidget extends BaseWidget<
getCanvasView() { getCanvasView() {
const style = this.getPositionStyle(); const style = this.getPositionStyle();
const occupiedSpaces = this.getOccupiedSpaces(); const occupiedSpaces = this.getOccupiedSpaces();
const renderDraggableComponent = ( const renderComponent = (
<DraggableComponent
style={{ ...style, xPosition: 0, yPosition: 0 }}
{...this.props}
orientation={"VERTICAL"}
>
<ResizableComponent style={{ ...style }} {...this.props}>
{this.getPageView()}
</ResizableComponent>
</DraggableComponent>
);
return (
<DropTargetComponent <DropTargetComponent
{...this.props} {...this.props}
{...this.state} {...this.state}
@ -110,10 +98,24 @@ class ContainerWidget extends BaseWidget<
style={{ style={{
...style, ...style,
}} }}
isRoot={!this.props.parentId}
> >
{this.props.parentId ? renderDraggableComponent : this.getPageView()} {this.getPageView()}
</DropTargetComponent> </DropTargetComponent>
); );
const renderDraggableComponent = (
<DraggableComponent
style={{ ...style }}
{...this.props}
orientation={"VERTICAL"}
>
<ResizableComponent style={{ ...style }} {...this.props}>
{renderComponent}
</ResizableComponent>
</DraggableComponent>
);
return this.props.parentId ? renderDraggableComponent : renderComponent;
} }
getWidgetType(): WidgetType { getWidgetType(): WidgetType {