Property pane should open on move, add and resize
This commit is contained in:
parent
3e88ae0074
commit
189c380e85
|
|
@ -98,6 +98,7 @@ export type WidgetAddChild = {
|
|||
rows: number;
|
||||
parentRowSpace: number;
|
||||
parentColumnSpace: number;
|
||||
newWidgetId: string;
|
||||
};
|
||||
|
||||
export type WidgetMove = {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
import React, {
|
||||
useContext,
|
||||
createContext,
|
||||
useState,
|
||||
Context,
|
||||
useCallback,
|
||||
} from "react";
|
||||
import React, { useContext, createContext, Context } from "react";
|
||||
import styled from "styled-components";
|
||||
import { WidgetProps, WidgetOperations } from "widgets/BaseWidget";
|
||||
import { ContainerWidgetProps } from "widgets/ContainerWidget";
|
||||
|
|
@ -14,6 +8,8 @@ import { FocusContext, ResizingContext } from "pages/Editor/CanvasContexts";
|
|||
import { EditorContext } from "components/editorComponents/EditorContextProvider";
|
||||
import { ControlIcons } from "icons/ControlIcons";
|
||||
import { Tooltip } from "@blueprintjs/core";
|
||||
import { WIDGET_CLASSNAME_PREFIX } from "constants/WidgetConstants";
|
||||
import { IntentColors } from "constants/DefaultTheme";
|
||||
|
||||
// FontSizes array in DefaultTheme.tsx
|
||||
// Change this to toggle the size of delete and move handles.
|
||||
|
|
@ -54,15 +50,6 @@ const EditControl = styled.div`
|
|||
cursor: pointer;
|
||||
`;
|
||||
|
||||
const DraggableMask = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
`;
|
||||
|
||||
const CONTROL_ICON_SIZE = 20;
|
||||
|
||||
const moveControlIcon = ControlIcons.MOVE_CONTROL({
|
||||
|
|
@ -75,16 +62,10 @@ const deleteControlIcon = ControlIcons.DELETE_CONTROL({
|
|||
height: CONTROL_ICON_SIZE,
|
||||
});
|
||||
|
||||
const editControlIcon = ControlIcons.EDIT_CONTROL({
|
||||
width: CONTROL_ICON_SIZE,
|
||||
height: CONTROL_ICON_SIZE,
|
||||
});
|
||||
|
||||
type DraggableComponentProps = ContainerWidgetProps<WidgetProps>;
|
||||
|
||||
export const DraggableComponentContext: Context<{
|
||||
isDragging?: boolean;
|
||||
widgetNode?: HTMLDivElement;
|
||||
}> = createContext({});
|
||||
/* eslint-disable react/display-name */
|
||||
|
||||
|
|
@ -95,17 +76,15 @@ const DraggableComponent = (props: DraggableComponentProps) => {
|
|||
showPropertyPane,
|
||||
propertyPaneWidgetId,
|
||||
} = useContext(FocusContext);
|
||||
const editControlIcon = ControlIcons.EDIT_CONTROL({
|
||||
width: CONTROL_ICON_SIZE,
|
||||
height: CONTROL_ICON_SIZE,
|
||||
background:
|
||||
propertyPaneWidgetId === props.widgetId ? IntentColors.primary : "auto",
|
||||
});
|
||||
|
||||
const { updateWidget } = useContext(EditorContext);
|
||||
|
||||
const [currentNode, setCurrentNode] = useState<HTMLDivElement>();
|
||||
const referenceRef = useCallback(
|
||||
node => {
|
||||
if (node !== null && node !== currentNode) {
|
||||
setCurrentNode(node);
|
||||
}
|
||||
},
|
||||
[setCurrentNode, currentNode],
|
||||
);
|
||||
const { isResizing } = useContext(ResizingContext);
|
||||
|
||||
const deleteWidget = () => {
|
||||
|
|
@ -117,8 +96,8 @@ const DraggableComponent = (props: DraggableComponentProps) => {
|
|||
};
|
||||
|
||||
const togglePropertyEditor = (e: any) => {
|
||||
if (showPropertyPane && props.widgetId && currentNode) {
|
||||
showPropertyPane(props.widgetId, currentNode, true);
|
||||
if (showPropertyPane && props.widgetId) {
|
||||
showPropertyPane(props.widgetId, true);
|
||||
}
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
|
@ -129,14 +108,14 @@ const DraggableComponent = (props: DraggableComponentProps) => {
|
|||
isDragging: monitor.isDragging(),
|
||||
}),
|
||||
begin: () => {
|
||||
if (showPropertyPane && currentNode) {
|
||||
showPropertyPane(props.widgetId, undefined);
|
||||
if (showPropertyPane) {
|
||||
showPropertyPane(props.widgetId);
|
||||
}
|
||||
},
|
||||
end: (widget, monitor) => {
|
||||
if (monitor.didDrop()) {
|
||||
if (showPropertyPane && currentNode) {
|
||||
showPropertyPane(props.widgetId, currentNode);
|
||||
if (showPropertyPane) {
|
||||
showPropertyPane(props.widgetId);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -146,12 +125,10 @@ const DraggableComponent = (props: DraggableComponentProps) => {
|
|||
});
|
||||
|
||||
return (
|
||||
<DraggableComponentContext.Provider
|
||||
value={{ isDragging, widgetNode: currentNode }}
|
||||
>
|
||||
<DraggableComponentContext.Provider value={{ isDragging }}>
|
||||
<DragPreviewImage connect={preview} src={blankImage} />
|
||||
<DraggableWrapper
|
||||
className={props.widgetId}
|
||||
className={WIDGET_CLASSNAME_PREFIX + props.widgetId}
|
||||
ref={drag}
|
||||
onMouseOver={(e: any) => {
|
||||
if (setFocus) {
|
||||
|
|
@ -171,7 +148,7 @@ const DraggableComponent = (props: DraggableComponentProps) => {
|
|||
}}
|
||||
onDoubleClick={(e: any) => {
|
||||
setFocus && setFocus(props.widgetId);
|
||||
showPropertyPane && showPropertyPane(props.widgetId, currentNode);
|
||||
showPropertyPane && showPropertyPane(props.widgetId);
|
||||
e.stopPropagation();
|
||||
}}
|
||||
show={props.widgetId === isFocused && !isResizing}
|
||||
|
|
@ -186,7 +163,6 @@ const DraggableComponent = (props: DraggableComponentProps) => {
|
|||
userSelect: "none",
|
||||
}}
|
||||
>
|
||||
<DraggableMask ref={referenceRef} />
|
||||
{props.children}
|
||||
<DragHandle className="control" ref={drag}>
|
||||
<Tooltip content="Move" hoverOpenDelay={500}>
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ export const DropTargetComponent = (props: DropTargetComponentProps) => {
|
|||
props.widgetId,
|
||||
);
|
||||
|
||||
showPropertyPane &&
|
||||
showPropertyPane(updateWidgetParams.payload.newWidgetId);
|
||||
|
||||
updateWidget &&
|
||||
updateWidget(
|
||||
updateWidgetParams.operation,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import {
|
|||
/* eslint-disable react/display-name */
|
||||
export const ResizableComponent = memo((props: ResizableComponentProps) => {
|
||||
// Fetch information from the context
|
||||
const { isDragging, widgetNode } = useContext(DraggableComponentContext);
|
||||
const { isDragging } = useContext(DraggableComponentContext);
|
||||
const { setIsResizing } = useContext(ResizingContext);
|
||||
const { updateWidget, occupiedSpaces } = useContext(EditorContext);
|
||||
const { showPropertyPane, isFocused, setFocus } = useContext(FocusContext);
|
||||
|
|
@ -121,7 +121,7 @@ export const ResizableComponent = memo((props: ResizableComponentProps) => {
|
|||
// Let the propertypane show.
|
||||
// The propertypane decides whether to show itself, based on
|
||||
// whether it was showing when the widget resize started.
|
||||
showPropertyPane && showPropertyPane(props.widgetId, widgetNode);
|
||||
showPropertyPane && showPropertyPane(props.widgetId);
|
||||
};
|
||||
const style = getBorderStyles(
|
||||
isWidgetFocused,
|
||||
|
|
|
|||
|
|
@ -9,11 +9,7 @@ import { ResizingContext, FocusContext } from "./CanvasContexts";
|
|||
|
||||
interface CanvasProps {
|
||||
dsl: ContainerWidgetProps<WidgetProps>;
|
||||
showPropertyPane: (
|
||||
widgetId?: string,
|
||||
node?: HTMLDivElement,
|
||||
toggle?: boolean,
|
||||
) => void;
|
||||
showPropertyPane: (widgetId?: string, toggle?: boolean) => void;
|
||||
propertyPaneWidgetId?: string;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,7 @@ export const FocusContext: Context<{
|
|||
isFocused?: string;
|
||||
setFocus?: Function;
|
||||
propertyPaneWidgetId?: string;
|
||||
showPropertyPane?: (
|
||||
widgetId?: string,
|
||||
node?: HTMLDivElement,
|
||||
toggle?: boolean,
|
||||
) => void;
|
||||
showPropertyPane?: (widgetId?: string, toggle?: boolean) => void;
|
||||
}> = createContext({});
|
||||
|
||||
export const ResizingContext: Context<{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import PaneWrapper from "pages/common/PaneWrapper";
|
|||
|
||||
type PopperProps = {
|
||||
isOpen: boolean;
|
||||
targetRefNode?: HTMLDivElement;
|
||||
targetNode?: Element;
|
||||
children: JSX.Element;
|
||||
};
|
||||
|
||||
|
|
@ -24,16 +24,15 @@ export default (props: PopperProps) => {
|
|||
const contentRef = useRef(null);
|
||||
useEffect(() => {
|
||||
//TODO(abhinav): optimize this, remove previous Popper instance.
|
||||
const parentElement =
|
||||
props.targetRefNode && props.targetRefNode.parentElement;
|
||||
const parentElement = props.targetNode && props.targetNode.parentElement;
|
||||
if (
|
||||
parentElement &&
|
||||
parentElement.parentElement &&
|
||||
props.targetRefNode &&
|
||||
props.targetNode &&
|
||||
props.isOpen
|
||||
) {
|
||||
new PopperJS(
|
||||
props.targetRefNode,
|
||||
props.targetNode,
|
||||
(contentRef.current as unknown) as Element,
|
||||
{
|
||||
placement: "right-start",
|
||||
|
|
@ -51,7 +50,7 @@ export default (props: PopperProps) => {
|
|||
},
|
||||
);
|
||||
}
|
||||
}, [props.targetRefNode, props.isOpen]);
|
||||
}, [props.targetNode, props.isOpen]);
|
||||
return createPortal(
|
||||
<PopperWrapper ref={contentRef}>{props.children}</PopperWrapper>,
|
||||
document.body,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import { PropertySection } from "reducers/entityReducers/propertyPaneConfigReduc
|
|||
import { updateWidgetProperty } from "actions/controlActions";
|
||||
import {
|
||||
getCurrentWidgetId,
|
||||
getCurrentReferenceNode,
|
||||
getPropertyConfig,
|
||||
getIsPropertyPaneVisible,
|
||||
getWidgetPropsWithValidations,
|
||||
|
|
@ -17,7 +16,10 @@ import { Divider } from "@blueprintjs/core";
|
|||
|
||||
import Popper from "./Popper";
|
||||
import { ControlProps } from "components/propertyControls/BaseControl";
|
||||
import { RenderModes } from "constants/WidgetConstants";
|
||||
import {
|
||||
RenderModes,
|
||||
WIDGET_CLASSNAME_PREFIX,
|
||||
} from "constants/WidgetConstants";
|
||||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { CloseButton } from "components/designSystems/blueprint/CloseButton";
|
||||
import { theme } from "constants/DefaultTheme";
|
||||
|
|
@ -58,8 +60,11 @@ class PropertyPane extends Component<
|
|||
render() {
|
||||
if (this.props.isVisible) {
|
||||
const content = this.renderPropertyPane(this.props.propertySections);
|
||||
const el = document.getElementsByClassName(
|
||||
WIDGET_CLASSNAME_PREFIX + this.props.widgetId,
|
||||
)[0];
|
||||
return (
|
||||
<Popper isOpen={true} targetRefNode={this.props.targetNode}>
|
||||
<Popper isOpen={true} targetNode={el}>
|
||||
{content}
|
||||
</Popper>
|
||||
);
|
||||
|
|
@ -162,7 +167,6 @@ const mapStateToProps = (state: AppState): PropertyPaneProps => {
|
|||
widgetId: getCurrentWidgetId(state),
|
||||
widgetProperties: getWidgetPropsWithValidations(state),
|
||||
isVisible: getIsPropertyPaneVisible(state),
|
||||
targetNode: getCurrentReferenceNode(state),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -193,7 +197,6 @@ export interface PropertyPaneProps {
|
|||
widgetId?: string;
|
||||
widgetProperties?: WidgetProps; //TODO(abhinav): Secure type definition
|
||||
isVisible: boolean;
|
||||
targetNode?: HTMLDivElement;
|
||||
}
|
||||
|
||||
export interface PropertyPaneFunctions {
|
||||
|
|
|
|||
|
|
@ -47,11 +47,7 @@ const CanvasContainer = styled.section`
|
|||
type EditorProps = {
|
||||
dsl?: ContainerWidgetProps<WidgetProps>;
|
||||
savePageLayout: Function;
|
||||
showPropertyPane: (
|
||||
widgetId?: string,
|
||||
node?: HTMLDivElement,
|
||||
toggle?: boolean,
|
||||
) => void;
|
||||
showPropertyPane: (widgetId?: string, toggle?: boolean) => void;
|
||||
fetchPage: (pageId: string) => void;
|
||||
currentPageId?: string;
|
||||
isFetchingPage: boolean;
|
||||
|
|
@ -112,14 +108,10 @@ const mapDispatchToProps = (dispatch: any) => {
|
|||
layoutId: string,
|
||||
dsl: ContainerWidgetProps<WidgetProps>,
|
||||
) => dispatch(savePage(pageId, layoutId, dsl)),
|
||||
showPropertyPane: (
|
||||
widgetId?: string,
|
||||
node?: HTMLDivElement,
|
||||
toggle = false,
|
||||
) => {
|
||||
showPropertyPane: (widgetId?: string, toggle = false) => {
|
||||
dispatch({
|
||||
type: ReduxActionTypes.SHOW_PROPERTY_PANE,
|
||||
payload: { widgetId, node, toggle },
|
||||
payload: { widgetId, toggle },
|
||||
});
|
||||
},
|
||||
fetchPage: (pageId: string) => dispatch(fetchPage(pageId)),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import {
|
|||
const initialState: PropertyPaneReduxState = {
|
||||
isVisible: false,
|
||||
widgetId: undefined,
|
||||
node: undefined,
|
||||
};
|
||||
|
||||
const propertyPaneReducer = createReducer(initialState, {
|
||||
|
|
@ -16,8 +15,8 @@ const propertyPaneReducer = createReducer(initialState, {
|
|||
state: PropertyPaneReduxState,
|
||||
action: ReduxAction<ShowPropertyPanePayload>,
|
||||
) => {
|
||||
const { widgetId, node } = action.payload;
|
||||
return { ...state, widgetId, node, isVisible: true };
|
||||
const { widgetId } = action.payload;
|
||||
return { ...state, widgetId, isVisible: true };
|
||||
},
|
||||
[ReduxActionTypes.HIDE_PROPERTY_PANE]: (state: PropertyPaneReduxState) => {
|
||||
return { ...state, isVisible: false };
|
||||
|
|
@ -27,7 +26,6 @@ const propertyPaneReducer = createReducer(initialState, {
|
|||
export interface PropertyPaneReduxState {
|
||||
widgetId?: string;
|
||||
isVisible: boolean;
|
||||
node?: HTMLDivElement;
|
||||
}
|
||||
|
||||
export default propertyPaneReducer;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ export function* addChildSaga(addChildAction: ReduxAction<WidgetAddChild>) {
|
|||
rows,
|
||||
parentRowSpace,
|
||||
parentColumnSpace,
|
||||
newWidgetId,
|
||||
} = addChildAction.payload;
|
||||
const widget: FlattenedWidgetProps = yield select(getWidget, widgetId);
|
||||
const widgets = yield select(getWidgets);
|
||||
|
|
@ -49,6 +50,7 @@ export function* addChildSaga(addChildAction: ReduxAction<WidgetAddChild>) {
|
|||
getNextWidgetName(defaultWidgetConfig.widgetName, widgets),
|
||||
defaultWidgetConfig,
|
||||
);
|
||||
childWidget.widgetId = newWidgetId;
|
||||
widgets[childWidget.widgetId] = childWidget;
|
||||
if (widget && widget.children) {
|
||||
widget.children.push(childWidget.widgetId);
|
||||
|
|
|
|||
|
|
@ -52,13 +52,6 @@ export const getWidgetPropsWithValidations = createSelector(
|
|||
},
|
||||
);
|
||||
|
||||
export const getCurrentReferenceNode = createSelector(
|
||||
getPropertyPaneState,
|
||||
(pane: PropertyPaneReduxState) => {
|
||||
return pane.widgetId && pane.node ? pane.node : undefined;
|
||||
},
|
||||
);
|
||||
|
||||
export const getPropertyConfig = createSelector(
|
||||
getPropertyPaneConfig,
|
||||
getPropertyPaneState,
|
||||
|
|
@ -84,5 +77,5 @@ export const getIsPropertyPaneVisible = createSelector(
|
|||
getPropertyPaneState,
|
||||
getPropertyConfig,
|
||||
(pane: PropertyPaneReduxState, content?: PropertySection[]) =>
|
||||
!!(pane.isVisible && pane.widgetId && pane.node && content),
|
||||
!!(pane.isVisible && pane.widgetId && content),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ export const widgetOperationParams = (
|
|||
widgetId: parentWidgetId,
|
||||
payload: {
|
||||
type: widget.type,
|
||||
newWidgetId: generateReactKey(),
|
||||
leftColumn,
|
||||
topRow,
|
||||
...widgetDimensions,
|
||||
|
|
@ -239,7 +240,7 @@ export const generateWidgetProps = (
|
|||
parentColumnSpace: number,
|
||||
widgetName: string,
|
||||
widgetConfig: Partial<WidgetProps>,
|
||||
): ContainerWidgetProps<WidgetProps> => {
|
||||
): Partial<ContainerWidgetProps<WidgetProps>> => {
|
||||
if (parent && parent.snapColumns && parent.snapRows) {
|
||||
const sizes = {
|
||||
leftColumn,
|
||||
|
|
@ -259,7 +260,6 @@ export const generateWidgetProps = (
|
|||
return {
|
||||
...widgetConfig,
|
||||
type,
|
||||
widgetId: generateReactKey(),
|
||||
widgetName: widgetName,
|
||||
isVisible: true,
|
||||
isLoading: false,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user