Focus widget on hover. Show property pane on double click

This commit is contained in:
Abhinav Jha 2019-12-27 15:40:04 +05:30
parent a7a83119ee
commit d9b8059799
10 changed files with 56 additions and 37 deletions

View File

@ -86,7 +86,7 @@
},
"scripts": {
"analyze": "source-map-explorer 'build/static/js/*.js'",
"start": "REACT_APP_ENVIRONMENT=DEVELOPMENT craco start",
"start": "REACT_APP_ENVIRONMENT=DEVELOPMENT HOST=dev.appsmith.com craco start",
"build": "craco build",
"test": "CI=true craco test",
"eject": "react-scripts eject",

View File

@ -1,6 +1,6 @@
import React, { useContext } from "react";
import styled from "styled-components";
import { FocusContext } from "pages/Editor/Canvas";
import { FocusContext } from "pages/Editor/CanvasContexts";
import { DraggableComponentContext } from "components/editorComponents/DraggableComponent";
const PositionStyle = styled.div`

View File

@ -33,10 +33,10 @@ const DragLayerComponent = (props: DragLayerProps) => {
const { isDragging, currentOffset, widget, canDrop } = useDragLayer(
monitor => ({
isDragging: monitor.isDragging(),
currentOffset: monitor.getClientOffset(),
currentOffset: monitor.getSourceClientOffset(),
widget: monitor.getItem(),
canDrop: noCollision(
monitor.getClientOffset() as XYCoord,
monitor.getSourceClientOffset() as XYCoord,
props.parentColumnWidth,
props.parentRowHeight,
monitor.getItem(),

View File

@ -10,7 +10,7 @@ import { WidgetProps, WidgetOperations } from "widgets/BaseWidget";
import { ContainerWidgetProps } from "widgets/ContainerWidget";
import { useDrag, DragPreviewImage, DragSourceMonitor } from "react-dnd";
import blankImage from "assets/images/blank.png";
import { FocusContext, ResizingContext } from "pages/Editor/Canvas";
import { FocusContext, ResizingContext } from "pages/Editor/CanvasContexts";
import { EditorContext } from "components/editorComponents/EditorContextProvider";
import { ControlIcons } from "icons/ControlIcons";
import { Tooltip } from "@blueprintjs/core";
@ -88,9 +88,6 @@ export const DraggableComponentContext: Context<{
}> = createContext({});
/* eslint-disable react/display-name */
//TODO(abhinav): the contexts and states are getting out of hand.
// Refactor here and in ResizableComponent
const DraggableComponent = (props: DraggableComponentProps) => {
const { isFocused, setFocus, showPropertyPane } = useContext(FocusContext);
const { updateWidget } = useContext(EditorContext);
@ -146,16 +143,25 @@ const DraggableComponent = (props: DraggableComponentProps) => {
<DraggableComponentContext.Provider
value={{ isDragging, widgetNode: currentNode }}
>
<DragPreviewImage src={blankImage} connect={preview} />
<DragPreviewImage connect={preview} src={blankImage} />
<DraggableWrapper
ref={drag}
onClick={(e: any) => {
if (setFocus && showPropertyPane) {
onMouseOver={(e: any) => {
if (setFocus) {
setFocus(props.widgetId);
showPropertyPane(props.widgetId, currentNode);
e.stopPropagation();
}
}}
onMouseLeave={(e: any) => {
setFocus && setFocus(null);
showPropertyPane && showPropertyPane(props.widgetId);
e.stopPropagation();
}}
onDoubleClick={(e: any) => {
setFocus && setFocus(props.widgetId);
showPropertyPane && showPropertyPane(props.widgetId, currentNode);
e.stopPropagation();
}}
show={props.widgetId === isFocused && !isResizing}
style={{
display: isDragging ? "none" : "flex",

View File

@ -5,7 +5,7 @@ import { WidgetConfigProps } from "reducers/entityReducers/widgetConfigReducer";
import WidgetFactory from "utils/WidgetFactory";
import { widgetOperationParams, noCollision } from "utils/WidgetPropsUtils";
import { EditorContext } from "components/editorComponents/EditorContextProvider";
import { FocusContext, ResizingContext } from "pages/Editor/Canvas";
import { FocusContext, ResizingContext } from "pages/Editor/CanvasContexts";
import DragLayerComponent from "./DragLayerComponent";
@ -46,7 +46,7 @@ export const DropTargetComponent = (props: DropTargetComponentProps) => {
if (isExactlyOver) {
const updateWidgetParams = widgetOperationParams(
widget,
monitor.getClientOffset() as XYCoord,
monitor.getSourceClientOffset() as XYCoord,
dropTargetOffset,
props.snapColumnSpace,
props.snapRowSpace,
@ -78,7 +78,7 @@ export const DropTargetComponent = (props: DropTargetComponentProps) => {
// Check if the draggable is the same as the dropTarget
if (isExactlyOver) {
const hasCollision = !noCollision(
monitor.getClientOffset() as XYCoord,
monitor.getSourceClientOffset() as XYCoord,
props.snapColumnSpace,
props.snapRowSpace,
widget,

View File

@ -4,7 +4,7 @@ import { XYCoord } from "react-dnd";
import { getAbsolutePixels } from "utils/helpers";
import { WidgetOperations, WidgetRowCols } from "widgets/BaseWidget";
import { EditorContext } from "components/editorComponents/EditorContextProvider";
import { FocusContext, ResizingContext } from "pages/Editor/Canvas";
import { FocusContext, ResizingContext } from "pages/Editor/CanvasContexts";
import { DraggableComponentContext } from "./DraggableComponent";
import { generateClassName } from "utils/generators";
@ -111,7 +111,8 @@ export const ResizableComponent = memo((props: ResizableComponentProps) => {
updateWidget &&
updateWidget(WidgetOperations.RESIZE, props.widgetId, newRowCols);
}
// Clear border styles
setIsColliding && setIsColliding(false);
// Tell the Canvas that we've stopped resizing
setIsResizing && setIsResizing(false);
// Tell the Canvas to put the focus back to this widget

View File

@ -1,10 +1,11 @@
import React, { createContext, useState, Context } from "react";
import React, { useState } from "react";
import WidgetFactory from "utils/WidgetFactory";
import { RenderModes } from "constants/WidgetConstants";
import { ContainerWidgetProps } from "widgets/ContainerWidget";
import { WidgetProps } from "widgets/BaseWidget";
import PropertyPane from "./PropertyPane";
import ArtBoard from "pages/common/ArtBoard";
import { ResizingContext, FocusContext } from "./CanvasContexts";
interface CanvasProps {
dsl: ContainerWidgetProps<WidgetProps>;
@ -15,21 +16,6 @@ interface CanvasProps {
) => void;
}
export const FocusContext: Context<{
isFocused?: string;
setFocus?: Function;
showPropertyPane?: (
widgetId?: string,
node?: HTMLDivElement,
toggle?: boolean,
) => void;
}> = createContext({});
export const ResizingContext: Context<{
isResizing?: boolean;
setIsResizing?: Function;
}> = createContext({});
/* eslint-disable react/display-name */
/* eslint-disable react/prop-types */

View File

@ -0,0 +1,16 @@
import { Context, createContext } from "react";
export const FocusContext: Context<{
isFocused?: string;
setFocus?: Function;
showPropertyPane?: (
widgetId?: string,
node?: HTMLDivElement,
toggle?: boolean,
) => void;
}> = createContext({});
export const ResizingContext: Context<{
isResizing?: boolean;
setIsResizing?: Function;
}> = createContext({});

View File

@ -26,7 +26,12 @@ export default (props: PopperProps) => {
//TODO(abhinav): optimize this, remove previous Popper instance.
const parentElement =
props.targetRefNode && props.targetRefNode.parentElement;
if (parentElement && parentElement.parentElement && props.targetRefNode) {
if (
parentElement &&
parentElement.parentElement &&
props.targetRefNode &&
props.isOpen
) {
new PopperJS(
props.targetRefNode,
(contentRef.current as unknown) as Element,
@ -46,7 +51,7 @@ export default (props: PopperProps) => {
},
);
}
}, [props.targetRefNode]);
}, [props.targetRefNode, props.isOpen]);
return createPortal(
<PopperWrapper ref={contentRef}>{props.children}</PopperWrapper>,
document.body,

View File

@ -13,6 +13,7 @@ import {
getIsPropertyPaneVisible,
getWidgetPropsWithValidations,
} from "selectors/propertyPaneSelectors";
import { FocusContext } from "pages/Editor/CanvasContexts";
import { Divider } from "@blueprintjs/core";
import Popper from "./Popper";
@ -55,12 +56,16 @@ class PropertyPane extends Component<
this.onPropertyChange = this.onPropertyChange.bind(this);
}
static contextType = FocusContext;
render() {
if (this.props.isVisible) {
const content = this.renderPropertyPane(this.props.propertySections);
return (
<Popper isOpen={true} targetRefNode={this.props.targetNode}>
<Popper
isOpen={true && this.context.isFocused === this.props.widgetId}
targetRefNode={this.props.targetNode}
>
{content}
</Popper>
);