1import React from "react"
2import { CSS } from "@dnd-kit/utilities"
3import { Slot, type SlotProps } from "@radix-ui/react-slot"
4import { useSortable } from "@dnd-kit/sortable"
5import { composeRefs, cn } from "@marzneshin/common/utils"
6import type {
7 UniqueIdentifier,
8} from "@dnd-kit/core"
9
10import { SortableItemContext } from "./context"
11
12interface SortableItemProps extends SlotProps {
13 value: UniqueIdentifier
14 asChild?: boolean
15}
16
17export const SortableItem = React.forwardRef<HTMLDivElement, SortableItemProps>(
18 ({ asChild, className, value, ...props }, ref) => {
19 const {
20 attributes,
21 listeners,
22 setNodeRef,
23 transform,
24 transition,
25 isDragging,
26 } = useSortable({ id: value })
27
28 const context = React.useMemo(
29 () => ({
30 attributes,
31 listeners,
32 }),
33 [attributes, listeners]
34 )
35 const style: React.CSSProperties = {
36 opacity: isDragging ? 0.4 : undefined,
37 transform: CSS.Translate.toString(transform),
38 transition,
39 }
40
41 const Comp = asChild ? Slot : "div"
42
43 return (
44 <SortableItemContext.Provider value={context}>
45 <Comp
46 className={cn(isDragging && "cursor-grabbing", className)}
47 ref={composeRefs(ref, setNodeRef as React.Ref<HTMLDivElement>)}
48 style={style}
49 {...props}
50 />
51 </SortableItemContext.Provider>
52 )
53 }
54)
55SortableItem.displayName = "SortableItem"