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

View File

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

View File

@ -7,7 +7,6 @@ import { ContainerProps } from "./ContainerComponent";
import WidgetFactory from "../utils/WidgetFactory";
import { widgetOperationParams, noCollision } from "../utils/WidgetPropsUtils";
import DragLayerComponent from "./DragLayerComponent";
import DropTargetMask from "./DropTargetMask";
type DropTargetComponentProps = ContainerProps & {
updateWidget?: Function;
@ -29,7 +28,7 @@ export const DropTargetComponent = (props: DropTargetComponentProps) => {
// Hook to keep the offset 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({
const [{ isOver, isExactlyOver }, drop] = useDrop({
accept: Object.values(WidgetFactory.getWidgetTypes()),
drop(widget: WidgetProps & Partial<WidgetConfigProps>, monitor) {
// Make sure we're dropping in this container.
@ -54,6 +53,7 @@ export const DropTargetComponent = (props: DropTargetComponentProps) => {
(monitor.isOver({ shallow: true }) &&
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
// 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 (
<div
ref={drop}
className="dropTarget"
style={{
position: "absolute",
left: props.style.xPosition + props.style.xPositionUnit,
height: props.style.componentHeight,
width: props.style.componentWidth,
top: props.style.yPosition + props.style.yPositionUnit,
position: "relative",
left: 0,
height: props.isRoot
? props.style.componentHeight + (props.style.heightUnit || "px")
: "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
parentOffset={dropTargetOffset}
parentRowHeight={props.snapRowSpace}
parentColumnWidth={props.snapColumnSpace}
visible={isOver}
isOver={isExactlyOver}
dropTargetOffset={dropTargetOffset}
occupiedSpaces={props.occupiedSpaces}
onBoundsUpdate={handleBoundsUpdate}
/>
{props.children}
</div>
);

View File

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

View File

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

View File

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