92 lines
2.6 KiB
TypeScript
92 lines
2.6 KiB
TypeScript
import { createContext, useContext } from 'react';
|
||
import { useSortable } from '@dnd-kit/sortable';
|
||
import { CSS } from '@dnd-kit/utilities';
|
||
import { TableRow, TableCell, Box } from '@mui/material';
|
||
import { DragIndicator } from '@mui/icons-material';
|
||
import { flexRender } from '@tanstack/react-table';
|
||
import type { Row } from '@tanstack/react-table';
|
||
import type { Idea } from '../../types/idea';
|
||
|
||
// Контекст для передачи информации о drag handle в ячейку
|
||
interface DragHandleContextValue {
|
||
attributes: ReturnType<typeof useSortable>['attributes'];
|
||
listeners: ReturnType<typeof useSortable>['listeners'];
|
||
isDragging: boolean;
|
||
}
|
||
|
||
const DragHandleContext = createContext<DragHandleContextValue | null>(null);
|
||
|
||
// Компонент drag handle для использования в колонке
|
||
export function DragHandle() {
|
||
const context = useContext(DragHandleContext);
|
||
|
||
if (!context) {
|
||
return null;
|
||
}
|
||
|
||
const { attributes, listeners, isDragging } = context;
|
||
|
||
return (
|
||
<Box
|
||
{...attributes}
|
||
{...listeners}
|
||
sx={{
|
||
cursor: isDragging ? 'grabbing' : 'grab',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
color: 'text.secondary',
|
||
touchAction: 'none',
|
||
'&:hover': { color: 'text.primary' },
|
||
}}
|
||
>
|
||
<DragIndicator fontSize="small" />
|
||
</Box>
|
||
);
|
||
}
|
||
|
||
interface DraggableRowProps {
|
||
row: Row<Idea>;
|
||
}
|
||
|
||
export function DraggableRow({ row }: DraggableRowProps) {
|
||
const {
|
||
attributes,
|
||
listeners,
|
||
setNodeRef,
|
||
transform,
|
||
transition,
|
||
isDragging,
|
||
} = useSortable({ id: row.original.id });
|
||
|
||
// Используем CSS.Translate вместо CSS.Transform для лучшей совместимости с таблицами
|
||
const style = {
|
||
transform: CSS.Translate.toString(transform),
|
||
transition,
|
||
opacity: isDragging ? 0.5 : 1,
|
||
backgroundColor: row.original.color
|
||
? `${row.original.color}15`
|
||
: isDragging
|
||
? 'action.hover'
|
||
: undefined,
|
||
position: isDragging ? ('relative' as const) : undefined,
|
||
zIndex: isDragging ? 1000 : undefined,
|
||
'&:hover': {
|
||
backgroundColor: row.original.color
|
||
? `${row.original.color}25`
|
||
: undefined,
|
||
},
|
||
};
|
||
|
||
return (
|
||
<DragHandleContext.Provider value={{ attributes, listeners, isDragging }}>
|
||
<TableRow ref={setNodeRef} hover sx={style}>
|
||
{row.getVisibleCells().map((cell) => (
|
||
<TableCell key={cell.id}>
|
||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||
</TableCell>
|
||
))}
|
||
</TableRow>
|
||
</DragHandleContext.Provider>
|
||
);
|
||
}
|