Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functionality for switching between editing and interactive mode #674

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
17 changes: 16 additions & 1 deletion apps/demo/app/custom-ui/[...puckPath]/client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ import { ChevronUp, ChevronDown, Globe, Lock, Unlock } from "lucide-react";

const CustomHeader = ({ onPublish }: { onPublish: (data: Data) => void }) => {
const { appState, dispatch } = usePuck();
const {
ui: { mode },
} = appState;

const toggleMode = () => {
dispatch({
type: "setUi",
ui: {
mode: mode === "edit" ? "interactive" : "edit",
},
});
};

return (
<header
Expand All @@ -28,7 +40,10 @@ const CustomHeader = ({ onPublish }: { onPublish: (data: Data) => void }) => {
>
<span style={{ fontWeight: 600 }}>Custom UI example </span>
<div style={{ marginLeft: "auto", display: "flex", gap: 8 }}>
<div>
<div style={{ gap: 8, display: "flex" }}>
<Button onClick={toggleMode}>
Switch to {mode === "edit" ? "interactive" : "edit"} mode
</Button>
<Button
onClick={() => onPublish(appState.data)}
icon={<Globe size="14" />}
Expand Down
22 changes: 17 additions & 5 deletions packages/core/components/DraggableComponent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { useAppContext } from "../Puck/context";
import { DefaultDraggable } from "../Draggable";
import { Loader } from "../Loader";
import { ActionBar } from "../ActionBar";
import { DefaultOverride } from "../DefaultOverride";

const getClassName = getClassNameFactory("DraggableComponent", styles);

Expand Down Expand Up @@ -81,8 +80,15 @@ export const DraggableComponent = ({
indicativeHover?: boolean;
style?: CSSProperties;
}) => {
const { zoomConfig, status, overrides, selectedItem, getPermissions } =
useAppContext();
const {
zoomConfig,
status,
overrides,
selectedItem,
getPermissions,
mode,
} = useAppContext();
const state = useAppContext();
const isModifierHeld = useModifierHeld("Alt");

const El = status !== "LOADING" ? Draggable : DefaultDraggable;
Expand All @@ -108,6 +114,8 @@ export const DraggableComponent = ({
item: selectedItem,
});

const isInteractive = mode === "interactive";

return (
<El
key={id}
Expand All @@ -128,11 +136,15 @@ export const DraggableComponent = ({
isLocked,
forceHover,
indicativeHover,
isInteractive,
})}
style={{
...style,
...provided.draggableProps.style,
cursor: isModifierHeld || isDragDisabled ? "pointer" : "grab",
cursor:
isInteractive || isModifierHeld || isDragDisabled
? "default"
: "grab",
}}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
Expand Down Expand Up @@ -178,7 +190,7 @@ export const DraggableComponent = ({
)}

<div className={getClassName("overlay")} />
<div className={getClassName("contents")}>{children}</div>
<div className={getClassName("contents")}> {children}</div>
</div>
)}
</El>
Expand Down
20 changes: 17 additions & 3 deletions packages/core/components/DraggableComponent/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@
overflow: hidden;
}

.DraggableComponent--isInteractive > .DraggableComponent-contents {
pointer-events: auto !important;
}

.DraggableComponent--isInteractive > .DraggableComponent-overlay {
cursor: default !important;
background: transparent !important;
outline: none !important;
}

.DraggableComponent--isInteractive:hover > .DraggableComopnent-overlay {
outline: none !important;
}

.DraggableComponent-contents {
position: relative; /* Reset stacking context */
pointer-events: none;
Expand Down Expand Up @@ -43,7 +57,7 @@
}

.DraggableComponent--isDragging > .DraggableComponent-overlay {
outline: 2px var(--puck-color-azure-09) solid !important;
outline: 2px var(--puck-color-azure-09) solid;
}

.DraggableComponent-loadingOverlay {
Expand Down Expand Up @@ -75,7 +89,7 @@

.DraggableComponent:not(.DraggableComponent--isSelected):hover
> .DraggableComponent-overlay {
outline: 2px var(--puck-color-azure-09) solid !important;
outline: 2px var(--puck-color-azure-09) solid;
}

.DraggableComponent--indicativeHover > .DraggableComponent-overlay {
Expand All @@ -91,7 +105,7 @@
}

.DraggableComponent--isSelected > .DraggableComponent-overlay {
outline: 2px var(--puck-color-azure-07) solid !important;
outline: 2px var(--puck-color-azure-07) solid;
}

.DraggableComponent--isSelected > .DraggableComponent-actionsOverlay {
Expand Down
7 changes: 5 additions & 2 deletions packages/core/components/Puck/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const defaultAppState: AppState = {
itemSelector: null,
componentList: {},
isDragging: false,
mode: "edit",
viewports: {
current: {
width: defaultViewports[0].width,
Expand Down Expand Up @@ -71,6 +72,7 @@ export type AppContext<
resolveData: (newAppState: AppState) => void;
plugins: Plugin[];
overrides: Partial<Overrides>;
mode: "interactive" | "edit";
history: Partial<PuckHistory>;
viewports: Viewports;
zoomConfig: ZoomConfig;
Expand All @@ -90,8 +92,8 @@ const defaultContext: AppContext = {
dispatch: () => null,
config: { components: {} },
componentState: {},
setComponentState: () => {},
resolveData: () => {},
setComponentState: () => { },
resolveData: () => { },
plugins: [],
overrides: {},
history: {},
Expand All @@ -109,6 +111,7 @@ const defaultContext: AppContext = {
globalPermissions: {},
getPermissions: () => ({}),
refreshPermissions: () => null,
mode: "edit"
};

export const appContext = createContext<AppContext>(defaultContext);
Expand Down
27 changes: 14 additions & 13 deletions packages/core/components/Puck/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,19 +195,19 @@ export function Puck<
// Store categories under componentList on state to allow render functions and plugins to modify
componentList: config.categories
? Object.entries(config.categories).reduce(
(acc, [categoryName, category]) => {
return {
...acc,
[categoryName]: {
title: category.title,
components: category.components,
expanded: category.defaultExpanded,
visible: category.visible,
},
};
},
{}
)
(acc, [categoryName, category]) => {
return {
...acc,
[categoryName]: {
title: category.title,
components: category.components,
expanded: category.defaultExpanded,
visible: category.visible,
},
};
},
{}
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think your local prettier is conflicting with the shared prettier. Can you run npm run format and commit the results?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

: {},
},
} as G["UserAppState"];
Expand Down Expand Up @@ -415,6 +415,7 @@ export function Puck<
history,
viewports,
iframe,
mode: ui.mode,
globalPermissions: {
delete: true,
drag: true,
Expand Down
1 change: 0 additions & 1 deletion packages/core/lib/use-puck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export const usePuck = <UserConfig extends Config = Config>() => {
getPermissions,
refreshPermissions,
} = useAppContext<UserConfig>();

return {
appState,
config,
Expand Down
1 change: 1 addition & 0 deletions packages/core/types/AppState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export type UiState = {
rightSideBarVisible: boolean;
itemSelector: ItemSelector | null;
arrayState: Record<string, ArrayState | undefined>;
mode: "interactive" | "edit";
componentList: Record<
string,
{
Expand Down