WIP: Fix positioning bug

This commit is contained in:
Abhinav Jha 2019-09-21 07:22:38 +05:30
parent ffb532fa7a
commit 7237250adc
10 changed files with 63 additions and 61 deletions

View File

@ -5,7 +5,6 @@ import { Container } from "./ContainerComponent";
class ButtonComponent extends React.Component<ButtonComponentProps> {
render() {
console.log("button props", this.props);
return (
<Container {...this.props}>
<Button icon={this.props.icon} onClick={this.props.onClick}>

View File

@ -0,0 +1,40 @@
import React from "react";
import styled from "styled-components";
import { useDragLayer, XYCoord } from "react-dnd";
import DropZone from "./Dropzone";
const WrappedDragLayer = styled.div`
position: absolute;
pointer-events: none;
z-index: 100;
left: 0;
top: 0;
width: 100%;
height: 100%;
cursor: grab;
`;
type DragLayerProps = {
height: number;
width: number;
parentOffset: XYCoord;
cellSize: number;
visible: boolean;
};
const DragLayerComponent = (props: DragLayerProps) => {
const { isDragging, currentOffset } = useDragLayer(monitor => ({
isDragging: monitor.isDragging(),
currentOffset: monitor.getClientOffset(),
}));
if (!isDragging) {
return null;
}
return (
<WrappedDragLayer>
<DropZone {...props} currentOffset={currentOffset as XYCoord} />
</WrappedDragLayer>
);
};
export default DragLayerComponent;

View File

@ -1,11 +1,11 @@
import React, { useState, useLayoutEffect, MutableRefObject } from "react";
import styled from "styled-components";
import { WidgetProps, WidgetOperations } from "../widgets/BaseWidget";
import { useDrop, XYCoord } from "react-dnd";
import { useDrop } from "react-dnd";
import { ContainerProps } from "./ContainerComponent";
import WidgetFactory from "../utils/WidgetFactory";
import DropZone from "./Dropzone";
import { snapToGrid } from "../utils/helpers";
import DragLayerComponent from "./DragLayerComponent";
const DEFAULT_CELL_SIZE = 1;
const DEFAULT_WIDGET_WIDTH = 200;
@ -26,7 +26,6 @@ const DropTargetMask = styled.div`
`;
export const DropTargetComponent = (props: DropTargetComponentProps) => {
const [dummyState, setDummyState] = useState({ x: 0, y: 0 });
const [dropTargetTopLeft, setDropTargetTopLeft] = useState({ x: 0, y: 0 });
const dropTargetMask: MutableRefObject<HTMLDivElement | null> = React.useRef(
null,
@ -42,11 +41,12 @@ export const DropTargetComponent = (props: DropTargetComponentProps) => {
}
}, [setDropTargetTopLeft]);
const [{ isOver, clientOffset }, drop] = useDrop({
const [{ isOver }, drop] = useDrop({
accept: Object.values(WidgetFactory.getWidgetTypes()),
drop(item: WidgetProps, monitor) {
if (monitor.isOver({ shallow: true })) {
const item = monitor.getItem();
const clientOffset = monitor.getClientOffset();
if (clientOffset) {
const [x, y] = snapToGrid(
DEFAULT_CELL_SIZE,
@ -67,21 +67,16 @@ export const DropTargetComponent = (props: DropTargetComponentProps) => {
});
}
}
return undefined;
},
hover: (item, monitor) => {
setDummyState(monitor.getDifferenceFromInitialOffset() as XYCoord);
},
collect: monitor => ({
hovered: !!monitor.isOver(),
isOver: !!monitor.isOver({ shallow: true }),
clientOffset: monitor.getClientOffset(),
}),
canDrop: (item, monitor) => {
return monitor.isOver({ shallow: true });
},
});
return (
<WrappedDropTarget
ref={drop}
@ -95,14 +90,12 @@ export const DropTargetComponent = (props: DropTargetComponentProps) => {
}}
>
<DropTargetMask ref={dropTargetMask} />
<DropZone
<DragLayerComponent
parentOffset={dropTargetTopLeft}
width={DEFAULT_WIDGET_WIDTH}
height={DEFAULT_WIDGET_HEIGHT}
cellSize={DEFAULT_CELL_SIZE}
visible={isOver}
currentOffset={clientOffset as XYCoord}
dummyState={dummyState}
/>
{props.children}
</WrappedDropTarget>

View File

@ -9,18 +9,13 @@ type DropZoneWrapperProps = {
height: number;
top: number;
};
const DropZoneWrapper = styled.div<DropZoneWrapperProps>`
const DropZoneWrapper = styled.div`
position: absolute;
z-index: 100;
display: ${props => (props.visible ? "block" : "none")};
left: ${props => props.left}px;
width: ${props => props.width}px;
top: ${props => props.top}px;
height: ${props => props.height}px;
background: ${props => props.theme.colors.hover};
border: 1px dashed ${props => props.theme.colors.textAnchor};
opacity: 0.7;
transition: all 0.2s ease-in-out 0s;
`;
type DropZoneProps = {
@ -30,8 +25,8 @@ type DropZoneProps = {
visible: boolean;
parentOffset: XYCoord;
cellSize: number;
dummyState: XYCoord;
};
/* eslint-disable react/display-name */
export const DropZone = (props: DropZoneProps) => {
let wrapperProps = {
@ -59,7 +54,18 @@ export const DropZone = (props: DropZoneProps) => {
}
}
return <DropZoneWrapper {...wrapperProps} />;
return (
<DropZoneWrapper
style={{
display: wrapperProps.visible ? "block" : "none",
left: wrapperProps.left + "px",
width: wrapperProps.width + "px",
top: wrapperProps.top + "px",
height: wrapperProps.height + "px",
}}
{...wrapperProps}
/>
);
};
export default DropZone;

View File

@ -1,26 +0,0 @@
import React from "react";
import styled from "styled-components";
import { useDragLayer } from "react-dnd";
const WrappedDragLayer = styled.div`
position: absolute;
pointer-events: none;
z-index: 100;
left: 0;
top: 0;
width: 100%;
height: 100%;
cursor: grab;
`;
const EditorDragLayer = () => {
const { isDragging } = useDragLayer(monitor => ({
isDragging: monitor.isDragging(),
}));
if (!isDragging) {
return null;
}
return <WrappedDragLayer></WrappedDragLayer>;
};
export default EditorDragLayer;

View File

@ -15,7 +15,6 @@ import CanvasWidgetsNormalizer from "../../normalizers/CanvasWidgetsNormalizer";
import { ContainerWidgetProps } from "../../widgets/ContainerWidget";
import { fetchPage, updateWidget, savePage } from "../../actions/pageActions";
import { RenderModes } from "../../constants/WidgetConstants";
import EditorDragLayer from "./EditorDragLayer";
import { executeAction } from "../../actions/widgetActions";
import { ActionPayload } from "../../constants/ActionConstants";
@ -72,7 +71,6 @@ class Editor extends Component<EditorProps> {
<EditorHeader></EditorHeader>
<EditorWrapper>
<WidgetCardsPane cards={this.props.cards} />
<EditorDragLayer />
<CanvasContainer>
<Canvas
dsl={{

View File

@ -24,10 +24,9 @@ class WidgetFactory {
const widgetProps: WidgetProps = {
key: widgetData.widgetId,
renderMode: renderMode,
...widgetData,
...widgetFunctions,
...widgetData,
};
console.log("=====", widgetData);
const widgetBuilder = this.widgetMap.get(widgetData.type);
if (widgetBuilder) {
const widget = widgetBuilder.buildWidget(widgetProps);

View File

@ -17,7 +17,6 @@ class WidgetBuilderRegistry {
static registerWidgetBuilders() {
WidgetFactory.registerWidgetBuilder("CONTAINER_WIDGET", {
buildWidget(widgetData: ContainerWidgetProps<WidgetProps>): JSX.Element {
console.log("Registry container", widgetData);
return <ContainerWidget {...widgetData} />;
},
});
@ -30,7 +29,6 @@ class WidgetBuilderRegistry {
WidgetFactory.registerWidgetBuilder("BUTTON_WIDGET", {
buildWidget(widgetData: ButtonWidgetProps): JSX.Element {
console.log("Register button", widgetData);
return <ButtonWidget {...widgetData} />;
},
});

View File

@ -29,7 +29,6 @@ abstract class BaseWidget<
initialState.height = 0;
initialState.width = 0;
this.state = initialState as K;
console.log(this.props);
}
componentDidMount(): void {
@ -116,10 +115,7 @@ abstract class BaseWidget<
getPositionStyle(): BaseStyle {
return {
positionType:
this.props.renderMode !== RenderModes.PAGE
? "CONTAINER_DIRECTION"
: "ABSOLUTE",
positionType: "ABSOLUTE",
height: this.state.height,
width: this.state.width,
yPosition: this.props.topRow * this.props.parentRowSpace,

View File

@ -105,7 +105,6 @@ export interface ContainerWidgetProps<T extends WidgetProps>
snapRows?: number;
orientation?: ContainerOrientation;
backgroundColor?: Color;
onPropertyChange?: Function;
}
export default ContainerWidget;