refactor: moved dnd part from Funnel into FunnelDnd
This commit is contained in:
42
src/components/dnd/FunnelDnd/FunnelColumn.tsx
Normal file
42
src/components/dnd/FunnelDnd/FunnelColumn.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import React, { ReactNode } from "react";
|
||||
import { useDroppable } from "@dnd-kit/core";
|
||||
import {
|
||||
SortableContext,
|
||||
verticalListSortingStrategy,
|
||||
} from "@dnd-kit/sortable";
|
||||
import { Stack } from "@mantine/core";
|
||||
import { BaseDraggable } from "@/components/dnd/types/types";
|
||||
|
||||
type Props<TItem> = {
|
||||
id: string;
|
||||
items: TItem[];
|
||||
renderItem: (item: TItem) => ReactNode;
|
||||
children?: ReactNode;
|
||||
};
|
||||
|
||||
const FunnelColumn = <TItem extends BaseDraggable>({
|
||||
id,
|
||||
items,
|
||||
renderItem,
|
||||
children,
|
||||
}: Props<TItem>) => {
|
||||
const { setNodeRef } = useDroppable({ id });
|
||||
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
<SortableContext
|
||||
id={id}
|
||||
items={items}
|
||||
strategy={verticalListSortingStrategy}>
|
||||
<Stack
|
||||
gap="xs"
|
||||
ref={setNodeRef}>
|
||||
{items.map(renderItem)}
|
||||
</Stack>
|
||||
</SortableContext>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FunnelColumn;
|
||||
126
src/components/dnd/FunnelDnd/FunnelDnd.tsx
Normal file
126
src/components/dnd/FunnelDnd/FunnelDnd.tsx
Normal file
@ -0,0 +1,126 @@
|
||||
"use client";
|
||||
|
||||
import React, { ReactNode } from "react";
|
||||
import {
|
||||
closestCorners,
|
||||
DndContext,
|
||||
DragEndEvent,
|
||||
DragOverEvent,
|
||||
DragStartEvent,
|
||||
} from "@dnd-kit/core";
|
||||
import {
|
||||
horizontalListSortingStrategy,
|
||||
SortableContext,
|
||||
} from "@dnd-kit/sortable";
|
||||
import { Group, ScrollArea } from "@mantine/core";
|
||||
import useDndSensors from "@/app/deals/hooks/useSensors";
|
||||
import SortableItem from "@/components/dnd/SortableItem";
|
||||
import { BaseDraggable } from "@/components/dnd/types/types";
|
||||
import FunnelColumn from "./FunnelColumn";
|
||||
import FunnelOverlay from "./FunnelOverlay";
|
||||
|
||||
type Props<TContainer, TItem> = {
|
||||
containers: TContainer[];
|
||||
items: TItem[];
|
||||
onDragStart: (event: DragStartEvent) => void;
|
||||
onDragOver: (event: DragOverEvent) => void;
|
||||
onDragEnd: (event: DragEndEvent) => void;
|
||||
renderContainer: (container: TContainer, children: ReactNode) => ReactNode;
|
||||
renderContainerOverlay: (
|
||||
container: TContainer,
|
||||
children: ReactNode
|
||||
) => ReactNode;
|
||||
renderItem: (item: TItem) => ReactNode;
|
||||
renderItemOverlay: (item: TItem) => ReactNode;
|
||||
getContainerId: (container: TContainer) => string;
|
||||
getItemsByContainer: (container: TContainer, items: TItem[]) => TItem[];
|
||||
activeContainer: TContainer | null;
|
||||
activeItem: TItem | null;
|
||||
};
|
||||
|
||||
const FunnelDnd = <
|
||||
TContainer extends BaseDraggable,
|
||||
TItem extends BaseDraggable,
|
||||
>({
|
||||
containers,
|
||||
items,
|
||||
onDragStart,
|
||||
onDragOver,
|
||||
onDragEnd,
|
||||
renderContainer,
|
||||
renderContainerOverlay,
|
||||
renderItem,
|
||||
renderItemOverlay,
|
||||
getContainerId,
|
||||
getItemsByContainer,
|
||||
activeContainer,
|
||||
activeItem,
|
||||
}: Props<TContainer, TItem>) => {
|
||||
const sensors = useDndSensors();
|
||||
|
||||
return (
|
||||
<ScrollArea
|
||||
offsetScrollbars="x"
|
||||
scrollbarSize="0.5rem">
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCorners}
|
||||
onDragStart={onDragStart}
|
||||
onDragOver={onDragOver}
|
||||
onDragEnd={onDragEnd}>
|
||||
<SortableContext
|
||||
items={containers.map(getContainerId)}
|
||||
strategy={horizontalListSortingStrategy}>
|
||||
<Group
|
||||
gap="xs"
|
||||
wrap="nowrap"
|
||||
align="start">
|
||||
{containers.map(container => {
|
||||
const containerItems = getItemsByContainer(
|
||||
container,
|
||||
items
|
||||
);
|
||||
const containerId = getContainerId(container);
|
||||
return (
|
||||
<SortableItem
|
||||
key={containerId}
|
||||
id={containerId}>
|
||||
{renderContainer(
|
||||
container,
|
||||
<FunnelColumn
|
||||
id={containerId}
|
||||
items={containerItems}
|
||||
renderItem={renderItem}
|
||||
/>
|
||||
)}
|
||||
</SortableItem>
|
||||
);
|
||||
})}
|
||||
<FunnelOverlay
|
||||
activeContainer={activeContainer}
|
||||
activeItem={activeItem}
|
||||
renderContainer={container => {
|
||||
const containerItems = getItemsByContainer(
|
||||
container,
|
||||
items
|
||||
);
|
||||
const containerId = getContainerId(container);
|
||||
return renderContainerOverlay(
|
||||
container,
|
||||
<FunnelColumn
|
||||
id={containerId}
|
||||
items={containerItems}
|
||||
renderItem={renderItem}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
renderItem={renderItemOverlay}
|
||||
/>
|
||||
</Group>
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
</ScrollArea>
|
||||
);
|
||||
};
|
||||
|
||||
export default FunnelDnd;
|
||||
30
src/components/dnd/FunnelDnd/FunnelOverlay.tsx
Normal file
30
src/components/dnd/FunnelDnd/FunnelOverlay.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import React, { ReactNode } from "react";
|
||||
import { defaultDropAnimation, DragOverlay } from "@dnd-kit/core";
|
||||
|
||||
type Props<TContainer, TItem> = {
|
||||
activeContainer: TContainer | null;
|
||||
activeItem: TItem | null;
|
||||
renderContainer: (container: TContainer) => ReactNode;
|
||||
renderItem: (item: TItem) => ReactNode;
|
||||
};
|
||||
|
||||
const FunnelOverlay = <TContainer, TItem>({
|
||||
activeContainer,
|
||||
activeItem,
|
||||
renderContainer,
|
||||
renderItem,
|
||||
}: Props<TContainer, TItem>) => {
|
||||
return (
|
||||
<DragOverlay dropAnimation={defaultDropAnimation}>
|
||||
<div style={{ cursor: "grabbing" }}>
|
||||
{activeItem
|
||||
? renderItem(activeItem)
|
||||
: activeContainer
|
||||
? renderContainer(activeContainer)
|
||||
: null}
|
||||
</div>
|
||||
</DragOverlay>
|
||||
);
|
||||
};
|
||||
|
||||
export default FunnelOverlay;
|
||||
3
src/components/dnd/FunnelDnd/index.ts
Normal file
3
src/components/dnd/FunnelDnd/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import FunnelDnd from "./FunnelDnd";
|
||||
|
||||
export default FunnelDnd;
|
||||
Reference in New Issue
Block a user