Skip to content

Commit

Permalink
feat: add drag, insert, delete, duplicate & drag permissions, and isD…
Browse files Browse the repository at this point in the history
…isabled prop to Drawer.Item
  • Loading branch information
xaviemirmon authored Aug 28, 2024
1 parent 39d63e0 commit cad95b8
Show file tree
Hide file tree
Showing 15 changed files with 188 additions and 74 deletions.
81 changes: 47 additions & 34 deletions apps/demo/app/custom-ui/[...puckPath]/client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -301,11 +301,53 @@ const CustomActionBar = ({ children, label }) => {
);
};

const CustomDrawer = () => {
const { getPermissions } = usePuck();

return (
<Drawer direction="horizontal">
<div
style={{
display: "flex",
pointerEvents: "all",
padding: "16px",
background: "var(--puck-color-grey-12)",
}}
>
{Object.keys(config.components).map((componentKey, componentIndex) => {
const canInsert = getPermissions({
type: componentKey,
}).insert;
return (
<Drawer.Item
key={componentKey}
name={componentKey}
index={componentIndex}
isDragDisabled={!canInsert}
>
{({ children }) => (
<div
style={{
marginRight: 8,
}}
>
{children}
</div>
)}
</Drawer.Item>
);
})}
</div>
</Drawer>
);
};

export function Client({ path, isEdit }: { path: string; isEdit: boolean }) {
const { data, resolvedData, key } = useDemoData({
path,
isEdit,
});

const configOverride: UserConfig = {
...config,
components: {
Expand All @@ -314,6 +356,10 @@ export function Client({ path, isEdit }: { path: string; isEdit: boolean }) {
...config.components.Hero,
permissions: {
debug: false,
drag: false,
delete: false,
duplicate: false,
insert: false,
},
},
},
Expand All @@ -335,40 +381,7 @@ export function Client({ path, isEdit }: { path: string; isEdit: boolean }) {
actionBar: ({ children, label }) => (
<CustomActionBar label={label}>{children}</CustomActionBar>
),
components: () => {
return (
<Drawer direction="horizontal">
<div
style={{
display: "flex",
pointerEvents: "all",
padding: "16px",
background: "var(--puck-color-grey-12)",
}}
>
{Object.keys(config.components).map(
(componentKey, componentIndex) => (
<Drawer.Item
key={componentKey}
name={componentKey}
index={componentIndex}
>
{({ children }) => (
<div
style={{
marginRight: 8,
}}
>
{children}
</div>
)}
</Drawer.Item>
)
)}
</div>
</Drawer>
);
},
components: () => <CustomDrawer />,
puck: () => <CustomPuck dataKey={key} />,
}}
/>
Expand Down
11 changes: 8 additions & 3 deletions packages/core/components/ActionBar/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
color: var(--puck-color-white);
font-family: var(--puck-font-family);
gap: 4px;
min-height: 26px;
}

.ActionBarComponent-actionsLabel {
Expand All @@ -19,13 +20,17 @@
justify-content: center;
align-items: center;
padding-left: 8px;
padding-right: 16px;
margin-right: 8px;
border-right: 0.5px solid var(--puck-color-grey-05); /* Fractional value required due to scaling */
padding-right: 8px;
text-overflow: ellipsis;
white-space: nowrap;
}

.ActionBarComponent-action:first-of-type {
border-left: 0.5px solid var(--puck-color-grey-05); /* Fractional value required due to scaling */
border-radius: 0;
padding-left: 16px;
}

.ActionBarComponent-action {
background: transparent;
border: none;
Expand Down
18 changes: 16 additions & 2 deletions packages/core/components/ComponentList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { useAppContext } from "../Puck/context";
import { ChevronDown, ChevronUp } from "lucide-react";
import { Drawer } from "../Drawer";

import { getPermissions } from "../../lib/get-permissions";

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

const ComponentListItem = ({
Expand All @@ -16,9 +18,21 @@ const ComponentListItem = ({
label?: string;
index: number;
}) => {
const { overrides } = useAppContext();
const { overrides, config, globalPermissions } = useAppContext();

const canInsert = getPermissions({
type: name,
config,
globalPermissions: globalPermissions || {},
}).insert;

return (
<Drawer.Item label={label} name={name} index={index}>
<Drawer.Item
label={label}
name={name}
index={index}
isDragDisabled={!canInsert}
>
{overrides.componentItem}
</Drawer.Item>
);
Expand Down
4 changes: 2 additions & 2 deletions packages/core/components/DragIcon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import styles from "./styles.module.css";

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

export const DragIcon = () => (
<div className={getClassName()}>
export const DragIcon = ({ isDragDisabled }: { isDragDisabled?: boolean }) => (
<div className={getClassName({ disabled: isDragDisabled })}>
<svg viewBox="0 0 20 20" width="12" fill="currentColor">
<path d="M7 2a2 2 0 1 0 .001 4.001A2 2 0 0 0 7 2zm0 6a2 2 0 1 0 .001 4.001A2 2 0 0 0 7 8zm0 6a2 2 0 1 0 .001 4.001A2 2 0 0 0 7 14zm6-8a2 2 0 1 0-.001-4.001A2 2 0 0 0 13 6zm0 2a2 2 0 1 0 .001 4.001A2 2 0 0 0 13 8zm0 6a2 2 0 1 0 .001 4.001A2 2 0 0 0 13 14z"></path>
</svg>
Expand Down
6 changes: 5 additions & 1 deletion packages/core/components/DragIcon/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
border-radius: 4px;
}

.DragIcon--disabled {
cursor: no-drop;
}

@media (hover: hover) and (pointer: fine) {
.DragIcon:hover {
.DragIcon:not(.DragIcon--disabled):hover {
color: var(--puck-color-azure-05);
background-color: var(--puck-color-azure-12);
}
Expand Down
1 change: 1 addition & 0 deletions packages/core/components/Draggable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export const Draggable = ({
snapshot.isDragging || !disableAnimations
? provided.draggableProps.style?.transform
: "translate(0px, 0px)",
cursor: isDragDisabled ? "no-drop" : "grab",
}}
>
{children(provided, snapshot)}
Expand Down
37 changes: 29 additions & 8 deletions packages/core/components/DraggableComponent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Loader } from "../Loader";
import { ActionBar } from "../ActionBar";
import { DefaultOverride } from "../DefaultOverride";
import { useLoadedOverrides } from "../../lib/use-loaded-overrides";
import { getPermissions } from "../../lib/get-permissions";

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

Expand Down Expand Up @@ -82,7 +83,15 @@ export const DraggableComponent = ({
indicativeHover?: boolean;
style?: CSSProperties;
}) => {
const { zoomConfig, status, overrides, plugins } = useAppContext();
const {
zoomConfig,
status,
overrides,
plugins,
selectedItem,
config,
globalPermissions,
} = useAppContext();
const isModifierHeld = useModifierHeld("Alt");

const El = status !== "LOADING" ? Draggable : DefaultDraggable;
Expand All @@ -109,6 +118,14 @@ export const DraggableComponent = ({
[loadedOverrides]
);

const permissions =
selectedItem &&
getPermissions({
selectedItem,
globalPermissions: globalPermissions || {},
config,
});

return (
<El
key={id}
Expand All @@ -133,7 +150,7 @@ export const DraggableComponent = ({
style={{
...style,
...provided.draggableProps.style,
cursor: isModifierHeld ? "initial" : "grab",
cursor: isModifierHeld || isDragDisabled ? "initial" : "grab",
}}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
Expand Down Expand Up @@ -163,12 +180,16 @@ export const DraggableComponent = ({
}}
>
<CustomActionBar label={label}>
<ActionBar.Action onClick={onDuplicate} label="Duplicate">
<Copy size={16} />
</ActionBar.Action>
<ActionBar.Action onClick={onDelete} label="Delete">
<Trash size={16} />
</ActionBar.Action>
{permissions && permissions.duplicate && (
<ActionBar.Action onClick={onDuplicate} label="Duplicate">
<Copy size={16} />
</ActionBar.Action>
)}
{permissions && permissions.delete && (
<ActionBar.Action onClick={onDelete} label="Delete">
<Trash size={16} />
</ActionBar.Action>
)}
</CustomActionBar>
</div>
</div>
Expand Down
39 changes: 25 additions & 14 deletions packages/core/components/Drawer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,42 @@ const DrawerDraggable = ({
children,
id,
index,
isDragDisabled,
}: {
children: ReactNode;
id: string;
index: number;
}) => (
<Draggable
key={id}
id={id}
index={index}
showShadow
disableAnimations
className={() => getClassNameItem()}
>
{() => children}
</Draggable>
);
isDragDisabled?: boolean;
}) => {
return (
<Draggable
key={id}
id={id}
index={index}
isDragDisabled={isDragDisabled}
showShadow
disableAnimations
className={() => getClassNameItem({ disabled: isDragDisabled })}
>
{() => children}
</Draggable>
);
};

const DrawerItem = ({
name,
children,
id,
label,
index,
isDragDisabled,
}: {
name: string;
children?: (props: { children: ReactNode; name: string }) => ReactElement;
id?: string;
label?: string;
index: number;
isDragDisabled?: boolean;
}) => {
const ctx = useContext(drawerContext);

Expand All @@ -66,13 +73,17 @@ const DrawerItem = ({
);

return (
<DrawerDraggable id={resolvedId} index={index}>
<DrawerDraggable
id={resolvedId}
index={index}
isDragDisabled={isDragDisabled}
>
<CustomInner name={name}>
<div className={getClassNameItem("draggableWrapper")}>
<div className={getClassNameItem("draggable")}>
<div className={getClassNameItem("name")}>{label ?? name}</div>
<div className={getClassNameItem("icon")}>
<DragIcon />
<DragIcon isDragDisabled={isDragDisabled} />
</div>
</div>
</div>
Expand Down
11 changes: 9 additions & 2 deletions packages/core/components/Drawer/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
font-family: var(--puck-font-family);
}

.DrawerItem--disabled {
background: var(--puck-color-grey-11);
color: var(--puck-color-grey-05);
cursor: not-allowed; /** Move this out of inline styles */
}

.DrawerItem-default .DrawerItem-draggableWrapper {
/* padding required here to prevent bug when cancelling a drag) */
padding-bottom: 12px;
Expand All @@ -20,7 +26,6 @@
font-size: var(--puck-font-size-xxs);
justify-content: space-between;
align-items: center;
cursor: grab;
transition: background-color 50ms ease-in, color 50ms ease-in;
}

Expand All @@ -37,7 +42,9 @@
}

@media (hover: hover) and (pointer: fine) {
.Drawer:not(.Drawer--isDraggingFrom) .DrawerItem-draggable:hover {
.Drawer:not(.Drawer--isDraggingFrom)
.DrawerItem:not(.DrawerItem--disabled)
.DrawerItem-draggable:hover {
background-color: var(--puck-color-azure-12);
color: var(--puck-color-azure-04);
transition: none;
Expand Down
Loading

0 comments on commit cad95b8

Please sign in to comment.