Skip to content

Commit

Permalink
feat: MOVE_ELEMENT
Browse files Browse the repository at this point in the history
  • Loading branch information
bepyan committed Aug 15, 2024
1 parent eed3db0 commit 3af5748
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 5 deletions.
141 changes: 141 additions & 0 deletions src/components/editor/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ type EditorActionMap = {
containerId: string;
elementDetails: EditorElement;
};
MOVE_ELEMENT: {
elementId: string;
newParentId: string;
newIndex: number;
};
MOVE_ELEMENT_UP: {
elementId: string;
};
MOVE_ELEMENT_DOWN: {
elementId: string;
};
UPDATE_ELEMENT: {
elementDetails: EditorElement;
};
Expand Down Expand Up @@ -90,6 +101,63 @@ const traverseElements = (
}, []);
};

const findElementAndParent = (
elements: EditorElement[],
elementId: string,
): [EditorElement | null, EditorElement | null, number] => {
for (const el of elements) {
if (el.id === elementId) {
return [el, null, -1];
}
if (Array.isArray(el.content)) {
const index = el.content.findIndex((child) => child.id === elementId);
if (index !== -1) {
return [el.content[index], el, index];
}
const [foundEl, foundParent, foundIndex] = findElementAndParent(
el.content,
elementId,
);
if (foundEl) {
return [foundEl, foundParent, foundIndex];
}
}
}
return [null, null, -1];
};

const removeElementFromParent = (
elements: EditorElement[],
elementId: string,
): [EditorElement[], EditorElement | null] => {
let removedElement: EditorElement | null = null;
const newElements = elements.map((el) => {
if (Array.isArray(el.content)) {
const index = el.content.findIndex((child) => child.id === elementId);
if (index !== -1) {
removedElement = el.content[index];
return {
...el,
content: [
...el.content.slice(0, index),
...el.content.slice(index + 1),
],
};
}
const [newContent, removed] = removeElementFromParent(
el.content,
elementId,
);
if (removed) {
removedElement = removed;
return { ...el, content: newContent };
}
}
return el;
}) as EditorElement[];
return [newElements, removedElement];
};

/**
* Action Handlers
*/
Expand Down Expand Up @@ -120,6 +188,79 @@ const actionHandlers: {
});
},

MOVE_ELEMENT: (editor, payload) => {
const { elementId, newParentId, newIndex } = payload;

const [elements, removedElement] = removeElementFromParent(
editor.state.elements,
elementId,
);
if (!removedElement) return editor;

const insertElement = (els: EditorElement[]): EditorElement[] => {
return els.map((el) => {
if (el.id === newParentId && Array.isArray(el.content)) {
const newContent = [...el.content];
newContent.splice(newIndex, 0, removedElement);
return { ...el, content: newContent };
}
if (Array.isArray(el.content)) {
return { ...el, content: insertElement(el.content) };
}
return el;
}) as EditorElement[];
};

const newElements = insertElement(elements);

return updateEditorHistory(editor, {
...editor.state,
elements: newElements,
});
},

MOVE_ELEMENT_UP: (editor, payload) => {
const { elementId } = payload;
const [element, parent, currentIndex] = findElementAndParent(
editor.state.elements,
elementId,
);
if (
!element ||
!parent ||
!Array.isArray(parent.content) ||
currentIndex <= 0
)
return editor;

return actionHandlers.MOVE_ELEMENT(editor, {
elementId,
newParentId: parent.id,
newIndex: currentIndex - 1,
});
},

MOVE_ELEMENT_DOWN: (editor, payload) => {
const { elementId } = payload;
const [element, parent, currentIndex] = findElementAndParent(
editor.state.elements,
elementId,
);
if (
!element ||
!parent ||
!Array.isArray(parent.content) ||
currentIndex === parent.content.length - 1
)
return editor;

return actionHandlers.MOVE_ELEMENT(editor, {
elementId,
newParentId: parent.id,
newIndex: currentIndex + 1,
});
},

UPDATE_ELEMENT: (editor, payload) => {
const newElements = traverseElements(editor.state.elements, (element) => {
if (element.id === payload.elementDetails.id) {
Expand Down
29 changes: 24 additions & 5 deletions src/components/editor/elements/element-helper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import {
GripVerticalIcon,
Trash2Icon,
} from "lucide-react";
import { useRef } from "react";
import { createPortal } from "react-dom";
import { useResizeObserver } from "usehooks-ts";
import { useEditor } from "~/components/editor/provider";
import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button";
import { cn } from "~/lib/utils";

import { useRef } from "react";
import { useResizeObserver } from "usehooks-ts";

export default function ElementHelper() {
const { editor, dispatch } = useEditor();
const element = editor.state.selectedElement;
Expand All @@ -27,6 +26,26 @@ export default function ElementHelper() {
box: "border-box",
});

const handleMoveUp = (e: React.MouseEvent) => {
e.stopPropagation();
dispatch({
type: "MOVE_ELEMENT_UP",
payload: {
elementId: element.id,
},
});
};

const handleMoveDown = (e: React.MouseEvent) => {
e.stopPropagation();
dispatch({
type: "MOVE_ELEMENT_DOWN",
payload: {
elementId: element.id,
},
});
};

const handleDeleteElement = () => {
dispatch({
type: "DELETE_ELEMENT",
Expand Down Expand Up @@ -60,10 +79,10 @@ export default function ElementHelper() {
<IconButton>
<GripVerticalIcon className="h-4 w-4" />
</IconButton>
<IconButton>
<IconButton onClick={handleMoveUp}>
<ArrowUpIcon className="h-4 w-4" />
</IconButton>
<IconButton>
<IconButton onClick={handleMoveDown}>
<ArrowDownIcon className="h-4 w-4" />
</IconButton>
</div>
Expand Down

0 comments on commit 3af5748

Please sign in to comment.