-
Notifications
You must be signed in to change notification settings - Fork 393
Expand file tree
/
Copy pathDashboardDndContext.tsx
More file actions
116 lines (103 loc) · 3.01 KB
/
DashboardDndContext.tsx
File metadata and controls
116 lines (103 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import React, { useCallback, useMemo, useState } from 'react';
import {
DndContext,
DragEndEvent,
DragOverlay,
DragStartEvent,
MouseSensor,
TouchSensor,
useSensor,
useSensors,
} from '@dnd-kit/core';
import {
SortableContext,
verticalListSortingStrategy,
} from '@dnd-kit/sortable';
import { DashboardContainer } from '@hyperdx/common-utils/dist/types';
import { Box, Text } from '@mantine/core';
// --- Types ---
export type DragHandleProps = React.HTMLAttributes<HTMLElement>;
export type DragData = {
type: 'container';
containerId: string;
containerTitle: string;
};
type Props = {
children: React.ReactNode;
containers: DashboardContainer[];
onReorderContainers: (fromIndex: number, toIndex: number) => void;
};
// --- Provider (container reorder only) ---
export function DashboardDndProvider({
children,
containers,
onReorderContainers,
}: Props) {
const [activeDrag, setActiveDrag] = useState<DragData | null>(null);
const mouseSensor = useSensor(MouseSensor, {
activationConstraint: { distance: 8 },
});
const touchSensor = useSensor(TouchSensor, {
activationConstraint: { delay: 200, tolerance: 5 },
});
const sensors = useSensors(mouseSensor, touchSensor);
const containerSortableIds = useMemo(
() => containers.map(c => `container-sort-${c.id}`),
[containers],
);
const handleDragStart = useCallback((event: DragStartEvent) => {
setActiveDrag((event.active.data.current as DragData) ?? null);
}, []);
const handleDragEnd = useCallback(
(event: DragEndEvent) => {
const { active, over } = event;
setActiveDrag(null);
if (!over) return;
const activeData = active.data.current as DragData | undefined;
if (!activeData) return;
// Container reorder via sortable
const overData = over.data.current as DragData | undefined;
if (
overData?.type === 'container' &&
activeData.containerId !== overData.containerId
) {
const from = containers.findIndex(c => c.id === activeData.containerId);
const to = containers.findIndex(c => c.id === overData.containerId);
if (from !== -1 && to !== -1) onReorderContainers(from, to);
}
},
[containers, onReorderContainers],
);
return (
<DndContext
sensors={sensors}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
>
<SortableContext
items={containerSortableIds}
strategy={verticalListSortingStrategy}
>
{children}
</SortableContext>
<DragOverlay dropAnimation={null}>
{activeDrag && (
<Box
px="sm"
py={4}
style={{
background: 'var(--mantine-color-body)',
border: '1px solid var(--mantine-color-default-border)',
borderRadius: 4,
opacity: 0.85,
}}
>
<Text size="sm" fw={500}>
{activeDrag.containerTitle}
</Text>
</Box>
)}
</DragOverlay>
</DndContext>
);
}