// Трансформации пишутся напрямую в DOM: проход через React означал бы
// ререндер всех строк на каждую пересечённую, а строка расписания — это
// ячейка сотрудника плюс по ячейке на каждый день месяца.
const applyShifts = (target: number) => {
const pitch = pitchRef.current;
const from = draggedRef.current;
if (from === null || !pitch) return;
rowElementsRef.current.forEach((elements, rowIndex) => {
let shift = 0;
if (rowIndex === from) shift = (target - from) * pitch;
else if (rowIndex > from && rowIndex <= target) shift = -pitch;
else if (rowIndex < from && rowIndex >= target) shift = pitch;
elements.forEach((element) => {
element.style.transform = shift ? `translateY(${shift}px)` : '';
});
});
};
const settle = () => {
// Новый порядок и снятые трансформации должны попасть на экран в одном
// кадре: применённые друг за другом, они дают моргание старым порядком.
flushSync(() => {
setDraggedIndex(null);
if (from !== null && to !== null && from !== to) onReorder(from, to);
});
};