Skip to content

Commit eda058d

Browse files
committed
feat: drag and drop
1 parent af85d1e commit eda058d

2 files changed

Lines changed: 154 additions & 0 deletions

File tree

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import * as React from "react"
2+
import { useSortable } from "@dnd-kit/sortable"
3+
import { CSS } from "@dnd-kit/utilities"
4+
import { Table } from "@/components/table"
5+
6+
interface DataTableNonSortableHeaderCellProps extends React.HTMLAttributes<HTMLTableCellElement> {
7+
id: string
8+
children: React.ReactNode
9+
}
10+
11+
export const DataTableNonSortableHeaderCell = React.forwardRef<
12+
HTMLTableCellElement,
13+
DataTableNonSortableHeaderCellProps
14+
>(({ id, children, className, style: propStyle, ...props }, ref) => {
15+
// Still use sortable hook but without listeners
16+
const {
17+
setNodeRef,
18+
transform,
19+
transition,
20+
} = useSortable({
21+
id,
22+
disabled: true, // Disable dragging
23+
})
24+
25+
// Only apply horizontal transform for smooth shifting
26+
const transformStyle = transform ? {
27+
x: transform.x,
28+
y: 0,
29+
scaleX: transform.scaleX,
30+
scaleY: transform.scaleY,
31+
} : null
32+
33+
const style: React.CSSProperties = {
34+
...propStyle,
35+
transform: transformStyle ? CSS.Transform.toString(transformStyle) : undefined,
36+
transition,
37+
position: 'relative' as const,
38+
}
39+
40+
const combineRefs = (element: HTMLTableCellElement | null) => {
41+
setNodeRef(element)
42+
if (ref) {
43+
if (typeof ref === 'function') {
44+
ref(element)
45+
} else {
46+
ref.current = element
47+
}
48+
}
49+
}
50+
51+
return (
52+
<Table.HeaderCell
53+
ref={combineRefs}
54+
style={style}
55+
className={className}
56+
{...props}
57+
>
58+
{children}
59+
</Table.HeaderCell>
60+
)
61+
})
62+
63+
DataTableNonSortableHeaderCell.displayName = "DataTableNonSortableHeaderCell"
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import * as React from "react"
2+
import { useSortable } from "@dnd-kit/sortable"
3+
import { CSS } from "@dnd-kit/utilities"
4+
import { DotsSix } from "@medusajs/icons"
5+
import { clx } from "@/utils/clx"
6+
import { Table } from "@/components/table"
7+
8+
interface DataTableSortableHeaderCellProps extends React.HTMLAttributes<HTMLTableCellElement> {
9+
id: string
10+
children: React.ReactNode
11+
}
12+
13+
export const DataTableSortableHeaderCell = React.forwardRef<
14+
HTMLTableCellElement,
15+
DataTableSortableHeaderCellProps
16+
>(({ id, children, className, style: propStyle, ...props }, ref) => {
17+
const {
18+
attributes,
19+
listeners,
20+
setNodeRef,
21+
transform,
22+
transition,
23+
isDragging,
24+
} = useSortable({
25+
id,
26+
})
27+
28+
// Only apply horizontal transform, ignore vertical movement
29+
const transformStyle = transform ? {
30+
x: transform.x,
31+
y: 0,
32+
scaleX: transform.scaleX,
33+
scaleY: transform.scaleY,
34+
} : null
35+
36+
const style: React.CSSProperties = {
37+
...propStyle,
38+
transform: transformStyle ? CSS.Transform.toString(transformStyle) : undefined,
39+
transition,
40+
opacity: isDragging ? 0.8 : 1,
41+
zIndex: isDragging ? 50 : undefined,
42+
position: 'relative' as const,
43+
cursor: isDragging ? 'grabbing' : undefined,
44+
}
45+
46+
const combineRefs = (element: HTMLTableCellElement | null) => {
47+
setNodeRef(element)
48+
if (ref) {
49+
if (typeof ref === 'function') {
50+
ref(element)
51+
} else {
52+
ref.current = element
53+
}
54+
}
55+
}
56+
57+
return (
58+
<Table.HeaderCell
59+
ref={combineRefs}
60+
style={style}
61+
className={clx(className, {
62+
"cursor-grabbing": isDragging,
63+
})}
64+
{...props}
65+
>
66+
<div className="group/header-cell flex h-full w-full items-center gap-1">
67+
<button
68+
type="button"
69+
className={clx(
70+
"flex h-5 w-4 cursor-grab items-center justify-center rounded outline-none",
71+
"text-ui-text-subtle transition-all",
72+
"opacity-0 group-hover/header-cell:opacity-100",
73+
"hover:text-ui-text-base",
74+
"focus-visible:text-ui-text-base focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-ui-focus",
75+
"disabled:cursor-not-allowed disabled:text-ui-text-disabled",
76+
{
77+
"opacity-100": isDragging,
78+
}
79+
)}
80+
{...attributes}
81+
{...listeners}
82+
>
83+
<DotsSix className="h-4 w-4" />
84+
</button>
85+
<div className="flex-1">{children}</div>
86+
</div>
87+
</Table.HeaderCell>
88+
)
89+
})
90+
91+
DataTableSortableHeaderCell.displayName = "DataTableSortableHeaderCell"

0 commit comments

Comments
 (0)