Skip to content

Commit

Permalink
fix(app-page-builder): add props to control editor element interactions
Browse files Browse the repository at this point in the history
  • Loading branch information
Pavel910 committed Nov 18, 2024
1 parent 7454937 commit 741cf53
Show file tree
Hide file tree
Showing 17 changed files with 230 additions and 181 deletions.
166 changes: 0 additions & 166 deletions packages/app-page-builder/src/editor/components/Element.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Elements as BaseElements } from "~/editor/config/Elements";
import { Element as BaseElement, ElementProps as BaseElementProps } from "~/editor/config/Element";
import { createGetId } from "~/editor/config/createGetId";
import { useDebugUtilities } from "~/editor/useDebugUtilities";
import { ElementControls } from "~/editor/contexts/EditorPageElementsProvider/ElementControls";

const SCOPE = "content";

Expand Down Expand Up @@ -38,4 +39,4 @@ const Elements = makeDecoratable("ContentElements", () => {
return <BaseElements scope={SCOPE} />;
});

export const Content = Object.assign(BaseContent, { Layout, Element, Elements });
export const Content = Object.assign(BaseContent, { Layout, Element, Elements, ElementControls });
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,44 @@ import Droppable, { DragObjectWithTypeWithTarget } from "~/editor/components/Dro
import { useRecoilValue } from "recoil";
import { uiAtom } from "~/editor/recoil/modules";
import { useElementPlugin } from "~/editor/contexts/EditorPageElementsProvider/useElementPlugin";
import { useSnackbar } from "@webiny/app-admin";
import { makeDecoratable, useSnackbar } from "@webiny/app-admin";
import { getElementTitle } from "~/editor/contexts/EditorPageElementsProvider/getElementTitle";
import styled from "@emotion/styled";

const DisablePointerEvents = styled("pb-eco-interactivity")`
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
`;

export interface ElementControlsProps {
canDrag?: boolean;
canEdit?: boolean;
canHighlight?: boolean;
canActivate?: boolean;
children?: React.ReactNode;
}

// Provides controls and visual feedback for page elements:
// - hover / active visual overlays
// - drag and drop functionality
export const ElementControls = () => {
export const ElementControls = makeDecoratable("ElementControls", (props: ElementControlsProps) => {
const { getElement, meta } = useRenderer();
const { showSnackbar } = useSnackbar();

const element = getElement();

const overlayInteractions = {
canDrag: typeof props.canDrag === "undefined" ? true : props.canDrag,
canHighlight: typeof props.canHighlight === "undefined" ? true : props.canHighlight,
canActivate: typeof props.canActivate === "undefined" ? true : props.canActivate
};

const canEdit = typeof props.canEdit === "undefined" ? true : props.canEdit;

// No need to add any controls and visual feedback for the root document page element.
// Note that the element type never changes, that's why we're safe to return here,
// despite the fact that below we're using more React hooks.
Expand Down Expand Up @@ -102,7 +128,11 @@ export const ElementControls = () => {
type={element.type}
isVisible={() => true}
>
{({ drop }) => <ElementControlsOverlay dropRef={drop} />}
{({ drop }) => (
<ElementControlsOverlay dropRef={drop} {...overlayInteractions}>
{props.children}
</ElementControlsOverlay>
)}
</Droppable>
{render}
</>
Expand All @@ -112,5 +142,12 @@ export const ElementControls = () => {
return render;
}

return <ElementControlsOverlay />;
};
return (
<>
<ElementControlsOverlay {...overlayInteractions}>
{props.children}
</ElementControlsOverlay>
{!canEdit ? <DisablePointerEvents /> : null}
</>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ declare global {
namespace JSX {
interface IntrinsicElements {
"pb-eco": React.HTMLProps<HTMLDivElement>;
"pb-eco-interactivity": React.HTMLProps<HTMLDivElement>;
}
}
}
Expand Down Expand Up @@ -203,6 +204,9 @@ const StyledPbElementControlsOverlay = styled(
);

interface Props {
canDrag: boolean;
canHighlight: boolean;
canActivate: boolean;
children?: React.ReactNode;
dropRef?: React.RefCallback<any>;
}
Expand Down Expand Up @@ -230,6 +234,11 @@ export const ElementControlsOverlay = (props: Props) => {
let isDraggable = false;
if (elementPlugin) {
isDraggable = Array.isArray(elementPlugin?.target) && elementPlugin.target.length > 0;

// In case this flag is passed from outside...
if (typeof props.canDrag !== "undefined") {
isDraggable = props.canDrag;
}
}

const beginDrag = useCallback(() => {
Expand Down Expand Up @@ -282,11 +291,14 @@ export const ElementControlsOverlay = (props: Props) => {
element={element}
elementRendererMeta={meta}
onClick={() => {
if (!rest.canActivate) {
return;
}
updateEditorElement(element => ({ ...element, isHighlighted: false }));
setActiveElementId(element.id);
}}
onMouseEnter={e => {
if (isActive || isHighlighted) {
if (isActive || isHighlighted || !rest.canHighlight) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ export const EventActionHandlerProvider = makeDecoratable(
);

const takeSnapshot = useRecoilCallback(({ snapshot }) => () => {
snapshot.retain();
return snapshot;
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import mirrorCellPlugin from "../recoil/actions/mirrorCell/plugin";
import updateElementPlugin from "../recoil/actions/updateElement/plugin";
import afterDropElementPlugin from "../recoil/actions/afterDropElement/plugin";
import moveBlockPlugin from "../recoil/actions/moveBlock/plugin";
import moveElementPlugin from "../recoil/actions/moveElement/plugin";
import afterUpdateElementsPlugin from "../recoil/actions/updateElementTree/plugin";
import elementSettingsPlugin from "../plugins/elementSettings/advanced/plugin";

Expand All @@ -23,6 +24,7 @@ export const ActionPlugins = memo(() => {
afterDropElementPlugin(),
deleteElementPlugin(),
moveBlockPlugin(),
moveElementPlugin(),
afterUpdateElementsPlugin(),
...dragPlugin(),
elementSettingsPlugin
Expand Down
2 changes: 2 additions & 0 deletions packages/app-page-builder/src/editor/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export { useCurrentBlockElement } from "./useCurrentBlockElement";
export { useCurrentElement } from "./useCurrentElement";
export { useDisplayMode } from "./useDisplayMode";
export { useElementById } from "./useElementById";
export { useGetElementById } from "./useGetElementById";
export { useMoveElement } from "./useMoveElement";
export { useElementSidebar } from "./useElementSidebar";
export { useElementVariables, useElementVariableValue } from "./useElementVariableValue";
export { useEventActionHandler } from "./useEventActionHandler";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useRecoilCallback } from "recoil";
import { elementByIdSelector } from "~/editor/recoil/modules";

export const useGetElementById = () => {
const getElementById = useRecoilCallback(({ snapshot }) => (value: string) => {
return snapshot.getPromise(elementByIdSelector(value));
});
return { getElementById };
};
Loading

0 comments on commit 741cf53

Please sign in to comment.