Skip to content

Commit

Permalink
Merge pull request #3 from JollyGrin/feat/nest-drop-v2
Browse files Browse the repository at this point in the history
Feat/nest drop v2
  • Loading branch information
JollyGrin authored Sep 8, 2024
2 parents eaca072 + 6647010 commit b038ace
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 40 deletions.
7 changes: 3 additions & 4 deletions src/components/atoms/mock-cards/atlas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ export const CardAtlas = ({
}
}, [isPressed]);

const show = preview && isHovering;
const show = preview && isHovering; // full preview of the card
return (
<Box
position="relative"
m="0.5rem auto"
w="calc(100% - 1rem)"
// h={show ? "150px" : "70px"}
h="70px"
bg="yellow"
borderRadius="1rem"
Expand All @@ -35,7 +34,6 @@ export const CardAtlas = ({
onMouseOut={() => setPreview(false)}
>
<Box
// bgImage={`url(/mock-cards/${img})`}
style={{ backgroundImage: `url(/mock-cards/${img})` }} // bgImage has caching issues
ref={hoverRef}
isolation="isolate"
Expand All @@ -48,11 +46,12 @@ export const CardAtlas = ({
backgroundRepeat="no-repeat"
transform={
show
? "scale(1.25) rotate(90deg) translate(-47.8%, 0px)"
? "scale(1.45) rotate(90deg) translate(-47.8%, 0px)"
: "scale(0.85) rotate(90deg) translate(-47.8%, 0px)"
}
bg="gray.400"
borderRadius="1rem"
transition="all 0.25s ease"
/>{" "}
</Box>
);
Expand Down
4 changes: 2 additions & 2 deletions src/components/atoms/mock-cards/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const CardImage = ({
bg="yellow"
overflow={show ? "unset" : "clip"}
borderRadius="1rem"
filter="drop-shadow(3px 3px 3px black)"
filter="drop-shadow(0 1px 3px rgba(0,0,0,0.2))"
zIndex={isHovering ? 1000 : index}
mb={position === "top" ? "unset" : "unset"}
mt={position === "bottom" ? "-0.25rem" : "unset"}
Expand All @@ -55,7 +55,7 @@ export const CardImage = ({
backgroundPosition="top"
backgroundSize="cover"
backgroundRepeat="no-repeat"
transform={show ? "scale(1.1)" : "unset"}
transform={show ? "scale(1.5)" : "unset"}
transition="all 0.25s ease"
// bg="gray.400"
/>{" "}
Expand Down
4 changes: 0 additions & 4 deletions src/components/molecules/DropGridItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,10 @@ export const DroppableGridItem = (props: {
const { isOver, setNodeRef } = useDroppable({
id: "droppable-" + props.id,
});
const style = {
color: isOver ? "green" : undefined,
};

return (
<div
ref={setNodeRef}
style={style}
className={css({
h: "100%",
w: "100%",
Expand Down
53 changes: 53 additions & 0 deletions src/components/molecules/SortItem/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, { ReactNode } from "react";
import { useSortable } from "@dnd-kit/sortable";

export function SortableItem(props: {
id: string;
gridIndex: number;
index: number;
children: ReactNode;
}) {
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
isDragging,
} = useSortable({
animateLayoutChanges: () => false,
id: props.id,
transition: {
duration: 500,
easing: "cubic-bezier(0.25, 1, 0.5, 1)",
},
data: {
gridIndex: props.gridIndex,
index: props.index,
},
});

// const style = {};
const style = transform
? {
transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`,
transition,
}
: undefined;

// const style = {
// transform: CSS.Transform.toString(transform),
// transition,
// };

return (
<li
ref={setNodeRef}
style={{ ...style, listStyle: "none", opacity: isDragging ? 0.5 : 1 }}
{...attributes}
{...listeners}
>
{props.children}
</li>
);
}
10 changes: 4 additions & 6 deletions src/components/organisms/GameBoard/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { ReactNode } from "react";
import { Grid, HStack } from "styled-system/jsx";
import { grid } from "styled-system/patterns";
import { LAYOUT_HEIGHTS } from "./constants";

const nav = `100px`;
const footer = `50px`;
const body = `calc(100vh - ${nav} - ${footer})`;
const { nav, body, footer } = LAYOUT_HEIGHTS;

export const GameLayout = (props: { children: ReactNode }) => {
return (
<Grid gridTemplateRows={`${nav} ${body} ${footer}`} gap={0}>
<Grid style={{ gridTemplateRows: `${nav} ${body} ${footer}` }} gap={0}>
<div style={{ background: "rgba(0,200,0,0.2)", padding: "1rem" }}>
<p>Experiment arranging a Sorcery Grid</p>
<p>
<p style={{ width: "fit-content", margin: "0 auto" }}>
While hovering over a card, click{" "}
<code
style={{
Expand Down
9 changes: 9 additions & 0 deletions src/components/organisms/GameBoard/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* LAYOUT
* */

const nav = `50px`;
const footer = `100px`;
const body = `calc(100vh - ${nav} - ${footer})`;

export const LAYOUT_HEIGHTS = { nav, footer, body };
33 changes: 24 additions & 9 deletions src/components/organisms/GameBoard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { CardAtlas } from "@/components/atoms/mock-cards/atlas";
import { SortableContext, rectSortingStrategy } from "@dnd-kit/sortable";
import { GameLayout } from "./Layout";
import { DragItem } from "@/components/molecules/DragItem";
import { DroppableGridItem } from "@/components/molecules/DropGridItem";
import { closestCenter, DndContext } from "@dnd-kit/core";
import { closestCorners, DndContext, DragOverlay } from "@dnd-kit/core";
import { useHandleDrag } from "./useHandleDrag";
import { SorceryCard } from "@/types/card";
import { CardImage } from "@/components/atoms/mock-cards/card";
import { SortableItem } from "@/components/molecules/SortItem";
import { Box } from "styled-system/jsx";

type GameCard = SorceryCard & { id: string }; // for game position
type Cards = GameCard[][];
Expand All @@ -17,13 +18,18 @@ export const GameBoard = ({
setGridItems(state: Cards): void;
gridItems: Cards;
}) => {
const { handleDragEnd } = useHandleDrag({
gridItems,
setGridItems,
});
const { handleDragEnd, handleDragStart, activeId, activeCard } =
useHandleDrag({
gridItems,
setGridItems,
});

return (
<DndContext onDragEnd={handleDragEnd} collisionDetection={closestCenter}>
<DndContext
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
collisionDetection={closestCorners}
>
<GameLayout>
{gridItems?.map((cards, gridIndex) => (
<DroppableGridItem
Expand All @@ -38,19 +44,28 @@ export const GameBoard = ({
strategy={rectSortingStrategy}
>
{cards.map((card, cardIndex) => (
<DragItem
<SortableItem
key={`card-${gridIndex}-${cardIndex}`}
id={`card-${gridIndex}-${cardIndex}`}
gridIndex={gridIndex}
index={cardIndex}
>
{card.type === "site" && <CardAtlas img={card.img} />}
{card.type !== "site" && <CardImage img={card.img} />}
</DragItem>
</SortableItem>
))}
</SortableContext>
</DroppableGridItem>
))}
</GameLayout>
<DragOverlay>
{activeId ? (
<Box opacity={0.8}>
{activeCard?.type === "site" && <CardAtlas img={activeCard?.img} />}
{activeCard?.type !== "site" && <CardImage img={activeCard?.img} />}
</Box>
) : null}
</DragOverlay>
</DndContext>
);
};
47 changes: 44 additions & 3 deletions src/components/organisms/GameBoard/useHandleDrag.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SorceryCard } from "@/types/card";
import { DragEndEvent } from "@dnd-kit/core";
import { useState } from "react";

type GameCard = SorceryCard & { id: string }; // for game position
type Cards = GameCard[][];
Expand All @@ -8,35 +9,75 @@ export const useHandleDrag = ({
gridItems,
setGridItems,
}: {
setGridItems(state: Cards): void;
gridItems: Cards;
setGridItems(state: Cards): void;
}) => {
const [active, setActive] = useState<DragEndEvent["active"] | null>(null);

function handleDragStart(event: DragEndEvent) {
setActive(event?.active);
}

function handleDragEnd(event: DragEndEvent) {
setActive(null);
const { active, over } = event;

if (over?.id === active.id) return; // if self, do nothing

if (over) {
const originIndex = parseInt(active.data.current?.gridIndex, 10);
const destinationIndex = parseInt(
(over?.id as string)?.split("-")[1],
10, // base 10 number
);

if (originIndex === destinationIndex) {
const updatedGrid = [...gridItems];
const cardsInCell = [...updatedGrid[originIndex]]; // Copy the cards in the original cell

const activeCardIndex = active?.data?.current?.index; // Index of the card being dragged
const destinationCardIndex = over?.data?.current?.index; // Index where the card will be dropped

// Remove the active card from its original position
const [activeCard] = cardsInCell.splice(activeCardIndex, 1);

// Insert the active card into the new position (destination)
cardsInCell.splice(destinationCardIndex, 0, activeCard);

// Update the original grid with the modified cards in the cell
updatedGrid[originIndex] = cardsInCell;

setGridItems(updatedGrid);
return;
}

// Remove card from the origin area
const updatedGrid = [...gridItems];

const [movedCard] = updatedGrid[originIndex].splice(
active?.data?.current?.index,
1,
);

// Place card in the destination area
updatedGrid[destinationIndex]?.push(movedCard);

setGridItems(updatedGrid);
}
}

console.log({
cardsInCell: gridItems[active?.data?.current?.gridIndex],
active: active?.id,
data: active?.data?.current,
find: gridItems.flat().find((card) => card?.id === active?.id),
});

return {
handleDragEnd,
handleDragStart,
activeId: active?.id,
activeCard:
gridItems?.[active?.data?.current?.gridIndex]?.[
active?.data?.current?.index
],
};
};
5 changes: 2 additions & 3 deletions src/pages/dnd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ import {
import { SortableContext, rectSortingStrategy } from "@dnd-kit/sortable";
import { ReactNode, useState } from "react";
import { Nav } from "@/components/molecules/Nav";
import { LAYOUT_HEIGHTS } from "@/components/organisms/GameBoard/constants";

const nav = `100px`;
const footer = `50px`;
const body = `calc(100vh - ${nav} - ${footer})`;
const { nav, body, footer } = LAYOUT_HEIGHTS;

export default function Home() {
const [gridItems, setGridItems] = useState(
Expand Down
5 changes: 2 additions & 3 deletions src/pages/hand.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ import {
} from "@dnd-kit/core";
import { SortableContext, rectSortingStrategy } from "@dnd-kit/sortable";
import { ReactNode, useState } from "react";
import { LAYOUT_HEIGHTS } from "@/components/organisms/GameBoard/constants";

const nav = `100px`;
const footer = `50px`;
const body = `calc(100vh - ${nav} - ${footer})`;
const { nav, body, footer } = LAYOUT_HEIGHTS;

export default function Home() {
// Initialize gridItems with cards
Expand Down
16 changes: 10 additions & 6 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@ import { DroppableGridItem } from "@/components/molecules/DropGridItem";
import { Grid } from "styled-system/jsx";
import { grid } from "styled-system/patterns";
import { DndContext, DragEndEvent, useDraggable } from "@dnd-kit/core";
import { ReactNode, useState } from "react";
import { ReactNode, useEffect } from "react";
import { LAYOUT_HEIGHTS } from "@/components/organisms/GameBoard/constants";
import { useRouter } from "next/router";

const nav = `100px`;
const footer = `50px`;
const body = `calc(100vh - ${nav} - ${footer})`;
const { nav, body, footer } = LAYOUT_HEIGHTS;

export default function Home() {
const [, setIsDropped] = useState(false);
const router = useRouter();
useEffect(() => {
router.push("/game");
}, []);
return null;

function handleDragEnd(event: DragEndEvent) {
if (event.over && event.over.id === "droppable") {
setIsDropped(true);
// setIsDropped(true);
}
}

Expand Down

0 comments on commit b038ace

Please sign in to comment.